00001 # TKE - Advanced Programmer's Editor 00002 # Copyright (C) 2014-2019 Trevor Williams (phase1geo@gmail.com) 00003 # 00004 # This program is free software; you can redistribute it and/or modify 00005 # it under the terms of the GNU General Public License as published by 00006 # the Free Software Foundation; either version 2 of the License, or 00007 # (at your option) any later version. 00008 # 00009 # This program is distributed in the hope that it will be useful, 00010 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 # GNU General Public License for more details. 00013 # 00014 # You should have received a copy of the GNU General Public License along 00015 # with this program; if not, write to the Free Software Foundation, Inc., 00016 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00017 00018 ###################################################################### 00019 # Name: themes.tcl 00020 # Author: Trevor Williams (phase1geo@gmail.com) 00021 # Date: 07/09/2014 00022 # Brief: Creates and sets the main UI theme to the given value. 00023 ###################################################################### 00024 00025 namespace eval themes { 00026 00027 variable curr_theme "" 00028 00029 array set files {} 00030 00031 set themes_dir [file join $::tke_home themes] 00032 00033 ###################################################################### 00034 # Updates the user's home themes directory 00035 proc update_themes_dir {} { 00036 00037 variable themes_dir 00038 00039 foreach fname [glob -nocomplain -directory $themes_dir *.tketheme] { 00040 file mkdir [file rootname $fname] 00041 file rename $fname [file rootname $fname] 00042 } 00043 00044 } 00045 00046 ###################################################################### 00047 # Loads the theme information. 00048 proc load {} { 00049 00050 variable files 00051 variable themes_dir 00052 00053 # Update the user's themes directory 00054 update_themes_dir 00055 00056 # Trace changes to syntax preference values 00057 if {[array size files] == 0} { 00058 trace variable preferences::prefs(Appearance/Theme) w themes::handle_theme_change 00059 trace variable preferences::prefs(Appearance/Colorize) w themes::handle_colorize_change 00060 trace variable preferences::prefs(Appearance/HiddenThemes) w themes::handle_hidden_change 00061 } 00062 00063 # Reset the files/themes arrays and unregister launcher items 00064 array unset files 00065 launcher::unregister [msgcat::mc "Theme:*"] 00066 00067 # Load the tke_dir theme files 00068 set tfiles [utils::glob_install [file join $::tke_dir data themes] *.tketheme] 00069 00070 # Load the theme files 00071 foreach item [glob -nocomplain -directory $themes_dir -types d *] { 00072 if {[file exists [file join $item [file tail $item].tketheme]]} { 00073 lappend tfiles [file join $item [file tail $item].tketheme] 00074 } 00075 } 00076 00077 # Get the theme information 00078 foreach tfile $tfiles { 00079 set name [file rootname [file tail $tfile]] 00080 set files($name) $tfile 00081 } 00082 00083 # Create the launcher items (only display the visible themes) 00084 foreach name [get_visible_themes] { 00085 launcher::register [format "%s: %s" [msgcat::mc "Theme"] $name] [list theme::load_theme $files($name)] "" [list themes::theme_okay] 00086 } 00087 00088 # Allow the preferences UI to be updated, if it exists 00089 pref_ui::themes_populate_table 00090 00091 } 00092 00093 ###################################################################### 00094 # Deletes the given theme from the file system. 00095 proc delete_theme {name} { 00096 00097 variable files 00098 00099 # If the theme file exists, delete the file 00100 if {[info exists files($name)] && [file exists $files($name)]} { 00101 file delete -force $files($name) 00102 } 00103 00104 # Reload the theme information 00105 load 00106 00107 } 00108 00109 ###################################################################### 00110 # Returns true if it is okay to change the theme. 00111 proc theme_okay {} { 00112 00113 return [expr [themer::window_exists] ^ 1] 00114 00115 } 00116 00117 ###################################################################### 00118 # Returns the filename associated with the given theme name. If the 00119 # theme name does not exist, returns an error. 00120 proc get_file {theme_name} { 00121 00122 variable files 00123 00124 if {[info exists files($theme_name)]} { 00125 return $files($theme_name) 00126 } 00127 00128 return -code error "Filename for theme $theme_name does not exist" 00129 00130 } 00131 00132 ###################################################################### 00133 # Returns a sorted list of all the themes. 00134 proc get_all_themes {} { 00135 00136 variable files 00137 00138 return [lsort [array names files]] 00139 00140 } 00141 00142 ###################################################################### 00143 # Returns the list of themes that will be visible from the theme menu. 00144 proc get_visible_themes {} { 00145 00146 variable files 00147 00148 # Create list of files to 00149 return [lsort [::struct::set difference [array names files] [preferences::get Appearance/HiddenThemes]]] 00150 00151 } 00152 00153 ###################################################################### 00154 # Called whenever the Appearance/Theme preference value is changed. 00155 proc handle_theme_change {{name1 ""} {name2 ""} {op ""}} { 00156 00157 variable files 00158 00159 set user_theme [preferences::get Appearance/Theme] 00160 00161 if {[info exists files($user_theme)]} { 00162 theme::load_theme $files($user_theme) 00163 } else { 00164 theme::load_theme $files(Default) 00165 } 00166 00167 } 00168 00169 ###################################################################### 00170 # Called whenever the Appearance/Colorize preference value is changed. 00171 proc handle_colorize_change {name1 name2 op} { 00172 00173 theme::update_syntax 00174 00175 } 00176 00177 ###################################################################### 00178 # Handle a change to the Appearance/HiddenThemes preference value. 00179 proc handle_hidden_change {name1 name2 op} { 00180 00181 # Reload the themes 00182 load 00183 00184 } 00185 00186 ###################################################################### 00187 # Imports the contents of the given theme file (which must have either 00188 # the .tketheme or .tkethemz file extensions). Imports the theme into 00189 # the user directory. Returns the name of the installed .tketheme file 00190 # if successful; otherwise, returns the empty string. 00191 proc import {parent_win fname} { 00192 00193 variable files 00194 variable themes_dir 00195 00196 # If the directory exists, move it out of the way 00197 set odir [file join $themes_dir [file rootname [file tail $fname]]] 00198 if {[file exists $odir]} { 00199 file rename $odir $odir.old 00200 } 00201 00202 # Unzip the file contents 00203 if {[catch { zipper::unzip $fname $themes_dir } rc]} { 00204 if {[catch { exec -ignorestderr unzip -u $fname -d $themes_dir } rc]} { 00205 catch { file rename $odir.old $odir } 00206 tk_messageBox -parent $parent_win -icon error -type ok -default ok \ 00207 -message "Unable to unzip theme file" -detail $rc 00208 return "" 00209 } 00210 } 00211 00212 # Remove the old file if it exists 00213 catch { file delete [file exists $odir.old] } 00214 00215 # Reload the available themes 00216 load 00217 00218 # Return the pathname of the installed .tketheme file 00219 return $files([file rootname [file tail $fname]]) 00220 00221 } 00222 00223 ###################################################################### 00224 # Exports the contents of the given theme to the given .tkethemz 00225 # directory. 00226 proc export {parent_win theme odir creator website license} { 00227 00228 # Create the theme directory 00229 file mkdir [set theme_dir [file join $odir $theme]] 00230 00231 # Populate the theme directory with the given contents 00232 if {![theme::export $theme $theme_dir $creator $website $license]} { 00233 tk_messageBox -parent $parent_win -icon error -type ok -default ok \ 00234 -message "Unable to export theme contents" 00235 return 00236 } 00237 00238 # Get the current working directory 00239 set pwd [pwd] 00240 00241 # Set the current working directory to the user themes directory 00242 cd $odir 00243 00244 # Perform the archive 00245 if {[catch { zipper::list2zip [pwd] [glob -directory $theme *] $theme.tkethemz } rc]} { 00246 if {[catch { exec -ignorestderr zip -r [file join .. $theme.tkethemz] $theme } rc]} { 00247 tk_messageBox -parent $parent_win -icon error -type ok -default ok \ 00248 -message "Unable to zip theme file" 00249 return 00250 } 00251 } 00252 00253 # Restore the current working directory 00254 cd $pwd 00255 00256 # Delete the theme directory and its contents 00257 catch { file delete -force $theme_dir } 00258 00259 } 00260 00261 ###################################################################### 00262 # Batch exports all custom themes to a directory on the Desktop. 00263 proc export_custom {{parent_win .}} { 00264 00265 variable files 00266 variable themes_dir 00267 00268 # Create the themes directory 00269 set output_dir [file join ~ Desktop UpdatedThemes] 00270 set current [theme::get_current_theme] 00271 00272 # If the output directory exists, delete it 00273 if {[file exists $output_dir]} { 00274 file delete -force $output_dir 00275 } 00276 00277 # Make the output directory 00278 file mkdir $output_dir 00279 00280 # Load each theme and then export it 00281 foreach {name theme_file} [array get files] { 00282 00283 # Only consider themes from the themes_dir 00284 if {[string compare -length [string length $themes_dir] $theme_file $themes_dir] != 0} { 00285 continue 00286 } 00287 00288 # Initialize some variables 00289 set license [file join [file dirname $theme_file] LICENSE] 00290 00291 # Load the theme 00292 theme::read_tketheme $theme_file 00293 00294 # Export the theme to the output directory 00295 array set attrs [list creator "" website "" date ""] 00296 array set attrs [theme::get_attributions] 00297 00298 # Export the loaded theme 00299 export $parent_win $name $output_dir $attrs(creator) $attrs(website) $license 00300 00301 } 00302 00303 # Restore the theme namespace with the current theme contents 00304 theme::load_theme $files($current) 00305 00306 # Tell the user that the export was successful 00307 gui::set_info_message [msgcat::mc "Batch custom theme export completed successfully"] 00308 00309 } 00310 00311 ###################################################################### 00312 # Repopulates the specified theme selection menu. 00313 proc populate_theme_menu {mnu} { 00314 00315 variable files 00316 variable curr_theme 00317 00318 # Get the current theme 00319 set curr_theme [theme::get_current_theme] 00320 00321 # Figure out the state for the items 00322 set state [expr {[themer::window_exists] ? "disabled" : "normal"}] 00323 00324 # Clear the menu 00325 $mnu delete 0 end 00326 00327 # Populate the menu with the available themes 00328 foreach name [get_visible_themes] { 00329 $mnu add radiobutton -label $name -variable themes::curr_theme -value $name -command [list theme::load_theme $files($name)] -state $state 00330 } 00331 00332 return $mnu 00333 00334 } 00335 00336 ###################################################################### 00337 # Returns the name of the currently displayed theme. 00338 proc get_current_theme {} { 00339 00340 variable curr_theme 00341 00342 return $curr_theme 00343 00344 } 00345 00346 ###################################################################### 00347 # Returns 1 if the given file is imported; otherwise, returns 0. 00348 proc get_imported {name} { 00349 00350 variable files 00351 variable themes_dir 00352 00353 if {[info exists files($name)]} { 00354 return [expr [string compare -length [string length $themes_dir] $themes_dir $files($name)] == 0] 00355 } 00356 00357 return 0 00358 00359 } 00360 00361 ###################################################################### 00362 # Returns the creator, website and/or date information from the file in array format. 00363 proc get_attributions {name} { 00364 00365 variable files 00366 00367 array set attrs [list creator "" website "" date ""] 00368 00369 if {[info exists files($name)]} { 00370 array set attrs [theme::get_file_attributions $files($name)] 00371 } 00372 00373 return [array get attrs] 00374 00375 } 00376 00377 ###################################################################### 00378 # Returns the location of the user themes directory. 00379 proc get_user_directory {} { 00380 00381 variable themes_dir 00382 00383 return $themes_dir 00384 00385 } 00386 00387 ###################################################################### 00388 # Returns the list of files in the TKE home directory to copy. 00389 proc get_share_items {dir} { 00390 00391 return [list themes] 00392 00393 } 00394 00395 ###################################################################### 00396 # Called whenever the share directory changes. 00397 proc share_changed {dir} { 00398 00399 variable themes_dir 00400 00401 set themes_dir [file join $dir themes] 00402 00403 } 00404 00405 }