home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-12-13 | 42.8 KB | 1,463 lines | [TEXT/ALFA] |
- ## -*-Tcl-*-
- # ###################################################################
- # Alpha - new Tcl folder configuration
- #
- # FILE: "dialogs.tcl"
- # created: 12/1/96 {5:36:49 pm}
- # last update: 13/12/97 {1:13:17 pm}
- # Author: Vince Darley
- # E-mail: <darley@fas.harvard.edu>
- # mail: Division of Engineering and Applied Sciences, Harvard University
- # Oxford Street, Cambridge MA 02138, USA
- # www: <http://www.fas.harvard.edu/~darley/>
- #
- # Much copyright (c) 1997 Vince Darley, rest Pete Keleher.
- #
- # Reorganisation carried out by Vince Darley with much help from Tom
- # Fetherston, Johan Linde and suggestions from the Alpha-D mailing list.
- # Alpha is shareware; please register with the author using the register
- # button in the about box.
- #
- # Description:
- #
- # Much more flexible dialogs for querying the user about flags and
- # vars. These may be global, mode-dependent, or package-dependent.
- #
- # Things you may wish to do:
- #
- # dialog::pkg_options Pkg
- #
- # creates a dialog for all array entries 'PkgmodeVars'. These
- # must have been previously declared using 'newPref'. These
- # variables are _not_ copied into the global scope; only
- # existing as array entries.
- #
- # Note that rather than setting up traces on variables, you are
- # often better off using the optional proc argument to newPref;
- # the name of a procedure to call if that element is changed by
- # the user.
- #
- # The old procedure 'newModeVar' is obsolete. Use the
- # new procedure 'newPref'. Why? It has optional arguments
- # which allow you to declare:
- #
- # lists
- # indexed lists
- # folders
- # files
- # bindings
- # menu-bindings
- # applications
- # variable-list elements
- # array elements
- #
- # all of which can be set using the same central mode/global
- # dialogs.
- #
- # It also lets you add an optional procedure to call when an
- # item changes... Also if Alpha upgrades to Tcl 8 and namespaces,
- # it is easy to modify that central procedure to fit everything
- # with the new scheme.
- #
- # Most modes will just want to declare their vars using newPref.
- # There is usually no need to do _anything_ else.
- #
- # ---
- #
- # The prefs dialog procs below were based upon Pete Keleher's
- # originals.
- # ###################################################################
- ##
-
- namespace eval dialog {}
- namespace eval global {}
- namespace eval flag {}
-
-
-
- # ◊◊◊◊ Toplevel dialog procedures ◊◊◊◊ #
-
- ##
- # -------------------------------------------------------------------------
- #
- # "dialog::pkg_options" --
- #
- # Make a dialog for the given package, with 'title' for the dialog box.
- # 'not_global' indicates the variables are never copied into the global
- # scope, remaining in their array ${pkg}modeVars (or '$var' if it is given)
- #
- # Results:
- # Nothing
- #
- # Side effects:
- # May modify any of the given package's variables.
- #
- # --Version--Author------------------Changes-------------------------------
- # 1.0 <darley@fas.harvard.edu> original
- # -------------------------------------------------------------------------
- ##
- proc dialog::pkg_options {pkg {title ""} {not_global 1} {var ""}} {
- if {!$not_global} {
- # make sure the package variables are global
- global ${pkg}modeVars
- if {[info exists ${pkg}modeVars]} {
- foreach v [array names ${pkg}modeVars] {
- global $v
- set $v [set ${pkg}modeVars($v)]
- }
- }
- }
- if {$title == ""} { set title "Preferences for the '[quote::Prettify $pkg]' package" }
- if {$not_global} {
- global dialog::_not_global_flag
- if {$var == ""} {
- set dialog::_not_global_flag ${pkg}modeVars
- } else {
- set dialog::_not_global_flag $var
- }
- }
- catch {dialog::modifyModeFlags $title $not_global $pkg} result
- if {$not_global} {
- global dialog::_not_global_flag
- set dialog::_not_global_flag ""
- }
- }
- proc dialog::edit_array {var {title ""}} {
- if {$title == ""} {set title "Contents of '$var' array"}
- dialog::pkg_options "" $title 1 $var
- }
- ##
- # -------------------------------------------------------------------------
- #
- # "dialog::variable" --
- #
- # Ask for a value, with default given by the given variable, and using
- # that variable's type (list, file, ...) as a constraint.
- #
- # Currently assumes the variable is a list var, but this will change.
- # -------------------------------------------------------------------------
- ##
- proc dialog::variable {var {title ""}} {
- if {$title == ""} { set title [quote::Prettify $var] }
- return [dialog::optionMenu $title [flag::options $var] \
- [uplevel [list set $var]]]
- }
-
- proc suffixMappings {} {
- global filepats
-
- set l1 5
- set w1 38
- set l2 [expr $l1 + $w1 + 5]
- set w2 200
- set h 18
- set top 5
- set mar 5
-
- set modes [lsort -ignore [array names filepats]]
- set len [expr [llength $modes] + 1]
- set modes1 [lrange $modes 0 [expr $len/2 - 1]]
- set modes2 [lrange $modes [expr $len/2] end]
-
- foreach m $modes1 {
- lappend items -t $m $l1 $top [expr $l1 + $w1] [expr $top + $h]
- lappend items -e $filepats($m) $l2 $top [expr $l2 + $w2] [expr $top + $h - 2]
- incr top [expr $h + $mar]
- }
-
- set top2 5
- set l1 [expr $l2 + $w2 + 20]
- set l2 [expr $l1 + $w1 + 5]
- foreach m $modes2 {
- lappend items -t $m $l1 $top2 [expr $l1 + $w1] [expr $top2 + $h]
- lappend items -e $filepats($m) $l2 $top2 [expr $l2 + $w2] [expr $top2 + $h - 2]
- incr top2 [expr $h + $mar]
- }
-
- if {$top2 > $top} {
- set top $top2
- }
- incr top $mar
-
- set l1 5
- lappend buts -b OK $l1 $top [expr $l1 + 60] [expr $top + 20]
- lappend buts -b Cancel [expr $l1 + 100] $top [expr $l1 + 160] [expr $top + 20]
-
- set res [eval "dialog -w [expr $l2 + $w2 + 10] -h [expr $top + 27]" \
- $buts $items]
-
- if {[car $res]} {
- set res [cddr $res]
-
- foreach m [lsort -ignore [array names filepats]] {
- if {$filepats($m) != [car $res]} {
- lappend changed [list $m [car $res]]
- }
- set res [cdr $res]
- }
-
- foreach pair $changed {
- addArrDef filepats [car $pair] [cadr $pair]
- set filepats([car $pair]) [cadr $pair]
- }
- }
- mode::updateSuffixes
- }
- proc dialog::mode {flags vars {title ""}} {
- set lim [expr 10 - [llength $flags]/4]
- if {[llength $vars] > $lim } {
- set args {}
- set nvars [llength $vars]
- set j 0
- for {set i 0} {$i < $nvars} {incr i $lim ; set lim 10} {
- lappend args [list "Page [incr j] of ${title}" $flags [lrange $vars $i [expr $i+$lim -1]]]
- set flags ""
- }
- dialog::multipage $args
- } else {
- dialog::onepage $flags $vars $title
- }
- }
- ##
- # -------------------------------------------------------------------------
- #
- # "dialog::modifyModeFlags" --
- #
- # Currently 'not_global == 0' implies this is a mode, or at least that
- # the variables are stored in ${mm}modeVars(...)
- #
- # 'not_global == 1' implies that the variables are stored in the
- # array given by the value of the variable 'dialog::_not_global_flag'
- #
- # Recently removed a call to mode::updateSuffixes which is not necessary
- # -------------------------------------------------------------------------
- ##
- proc dialog::modifyModeFlags {{title ""} {not_global 0} {mm ""}} {
- global mode invisibleModeVars modifiedArrayElements dialog::_not_global_flag \
- allFlags flag::procs
- # Check whether this is a mode or package, and where variable values
- # are stored, and whether that's at the global level as well as in
- # an array...
- if {$not_global} {
- set storage ${dialog::_not_global_flag}
- if {$title == ""} {
- set title "Preferences for '${mm}' package"
- }
- } else {
- if {$mm == ""} {
- set mm $mode
- if {$mm == ""} {
- alertnote "No mode set!"
- return
- }
- }
- set storage ${mm}modeVars
- if {$title == ""} {
- set title "Preferences for '${mm}' mode"
- }
- }
- # check for mode specific proc
- if {[info commands ${mm}modifyFlags] != ""} {${mm}modifyFlags; return}
- if {[info tclversion] >= 8.0} { set storage ::$storage }
- set flags {}
- set vars {}
- global $storage ${storage}Invisible
- if {[info exists $storage]} {
- set unsortedNames [array names $storage]
- set colors {}
- set rest {}
- foreach i $unsortedNames {
- if {[regexp {Colou?r$} $i]} {
- lappend colors $i
- } else {
- lappend rest $i
- }
- }
-
- foreach v [concat [lsort $rest] [lsort $colors]] {
- if {[info exists invisibleModeVars($v)] \
- || [info exists ${storage}Invisible($v)]} continue
-
- if {[lsearch $allFlags $v] >= 0} {
- lappend flags $v
- } else {
- lappend vars $v
- }
- }
-
- set values_items [dialog::mode $flags $vars $title]
- set res [lindex $values_items 0]
- set editItems [lindex $values_items 1]
- unset values_items
-
- foreach fset $editItems {
- if {[llength $fset] > 1} {
- set fset [lrange $fset 1 end]
- }
- foreach flag $fset {
- set val [lindex $res 0]
- set res [lrange $res 1 end]
- dialog::postManipulate
- if {$not_global} {
- # it's a package which keeps its vars in the array
- if {[set ${storage}($flag)] != $val} {
- set ${storage}($flag) $val
- lappend modifiedArrayElements [list $flag $storage]
- if {[info exists flag::procs($flag)]} {
- [set flag::procs($flag)] $flag
- }
- }
- } else {
- # modes keep a copy of their vars at the global level when active
- global $flag
- if {[set $flag] != $val} {
- set $flag $val
- set ${storage}($flag) $val
- lappend modifiedArrayElements [list $flag $storage]
-
- if {[info exists flag::procs($flag)]} {
- [set flag::procs($flag)] $flag
- }
- }
- }
- }
- }
- } else {
- alertnote "The '$mm' mode/package has no preference settings."
- }
-
- hook::callAll dialog::modifyModeFlags $mm $title
-
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "dialog::getAKey" --
- #
- # Returns a keystring to be used for binding a key in a menu,
- # using a nice dialog box to ask the user.
- #
- # Possible improvements: we could replace the dialog
- # box with a status-line prompt (which would allow the use of
- # getModifiers to check what keys the user pressed).
- #
- # Now handles 'prefixChar' bindings for non-menu items.
- # i.e. you can use this dialog to bind something to 'ctrl-x ctrl-s',
- # for instance.
- #
- # If the name contains '/' it is considered to be two items,
- # separated by that '/', which are to take the same binding,
- # except that one of them will use the option key.
- #
- # Similarly '//' means use shift, '///' means shift-option,
- # For instance 'dialog::getAKey close/closeAll//closeFloat /W<O'
- # would give you the menu-item for 'close' in the file menu.
- # except these last two aren't implemented yet ;-)
- # --Version--Author------------------Changes-------------------------------
- # 1.0 Johan Linde original
- # 1.1 <darley@fas.harvard.edu> can do non-menu bindings too
- # 1.2 <darley@fas.harvard.edu> handles arrow keys
- # -------------------------------------------------------------------------
- ##
- proc dialog::getAKey {{name {}} {keystr {}} {for_menu 1}} {
- global keys::func
- # two lists for any other keys which look better with a text description
- set otherKeys {"<No binding>" "-" Space}
- set otherKeyChars [list "" "" " "]
- if {!$for_menu} {
- lappend otherKeys Left Right Up Down
- lappend otherKeyChars "" "" "\x10" ""
- }
- set nname $name
- set shift-opt [expr ![regsub {///} $nname { so-} $nname]]
- set shift [expr ![regsub {//} $nname { s-} $nname]]
- set option [expr ![regsub {/} $nname { o-} $nname]]
- if {[string length $keystr]} {
- set values "0 0"
- set mkey [keys::verboseKey $keystr normal]
- if $normal {
- lappend values "Normal Key"
- } else {
- lappend values $mkey
- set mkey {}
- }
- lappend values [regexp {<U} $keystr]
- lappend values [regexp {<B} $keystr]
- if !$for_menu {
- if [regexp "«(.*)»" $keystr "" i] {
- if {$i == "e"} {
- lappend values "escape"
- } else {
- lappend values "ctrl-$i"
- }
- } else {
- lappend values "<none>"
- }
- }
- if {$option} {lappend values [regexp {<I} $keystr]}
- lappend values [regexp {<O} $keystr]
- lappend values $mkey
- } else {
- set values {0 0 "" 0 0}
- if !$for_menu { lappend values <none> }
- if {$option} {lappend values 0}
- lappend values 0 ""
- }
- if $for_menu {
- set title "Menu key binding"
- } else {
- set title "Key binding"
- set prefixes [keys::findPrefixChars]
- foreach i $prefixes {
- lappend prefix "ctrl-$i"
- }
- lappend prefixes e
- lappend prefix "escape"
- }
- if {$name != ""} { append title " for '$name'" }
- set usep [info exists prefix]
- while {1} {
- # Build box
- set box "-t [list $title] 10 10 315 25 -t Key 10 40 40 55 -m [list [concat [list [lindex $values 2]] [list "Normal key"] $otherKeys ${keys::func}]] 80 40 180 55 -c Shift [list [lindex $values 3]] 10 70 60 85 -c Control [list [lindex $values 4]] 80 70 150 85"
- if $usep {
- lappend box -t Prefix 190 40 230 55 -m [concat [list [lindex $values 5]] "<none>" "-" $prefix] 235 40 315 55
- }
- if {$option} {lappend box -c Option [lindex $values [expr 5 + $usep]] 160 70 220 85}
- lappend box -c Command [lindex $values [expr 5 + $option +$usep]] 230 70 315 85
- lappend box -n "Normal key" -e [lindex $values [expr 6 + $option +$usep]] 50 40 70 55
- set values [eval [concat dialog -w 330 -h 130 -b OK 20 100 85 120 -b Cancel 105 100 170 120 $box]]
- # Interpret result
- if {[lindex $values 1]} {error "Cancel"}
- # work around a little Tcl problem
- regsub "\{\{\}" $values "\\\{" values
- set elemKey [string toupper [string trim [lindex $values [expr 6 + $option +$usep]]]]
- set special [lindex $values 2]
- set keyStr ""
- if {[lindex $values 3]} {append keyStr "<U"}
- if {[lindex $values 4]} {append keyStr "<B"}
- if {$option && [lindex $values [expr 5 + $usep]]} {append keyStr "<I"}
- if {[lindex $values [expr 5 + $option +$usep]]} {append keyStr "<O"}
- if $usep {
- set pref [lindex $values 5]
- if {$pref != "<none>"} {
- set i [lsearch -exact $prefix $pref]
- append keyStr "«[lindex $prefixes $i]»"
- }
- }
- if {[string length $elemKey] > 1 && $special == "Normal key"} {
- alertnote "You should only give one character for key binding."
- } else {
- if $for_menu {
- if {$special == "Normal key" && [text::Ascii $elemKey] > 126} {
- alertnote "Sorry, can't define a key binding with $elemKey."
- } elseif {$elemKey != "" && $special == "Normal key" && ($keyStr == "" || $keyStr == "<U")} {
- alertnote "You must choose at least one of the modifiers control, option and command."
- } elseif {![regexp {F[0-9]} $special] && $special != "Tab" && $special != "Normal key" && $keyStr == ""} {
- alertnote "You must choose at least one modifier."
- } else {
- break
- }
- } else {
- break
- }
- }
- }
- if {$special == "<No binding>"} {set elemKey ""}
- if {$special != "Normal key" && $special != "<No binding>"} {
- if {[set i [lsearch -exact $otherKeys $special]] != -1} {
- set elemKey [lindex $otherKeyChars $i]
- } else {
- set elemKey [text::Ascii [expr [lsearch -exact ${keys::func} $special] + 97] 1]
- }
- }
- if {![string length $elemKey]} {
- set keyStr ""
- } else {
- append keyStr "/$elemKey"
- }
- return $keyStr
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "dialog::optionMenu" --
- #
- # names is the list of items. An item '-' is a divider, and empty items
- # are not allowed.
- # -------------------------------------------------------------------------
- ##
- proc dialog::optionMenu {prompt names {default ""} {index 0}} {
- if {$default == ""} {set default [lindex $names 0]}
-
- set y 5
- set w [expr [string length $prompt] > 20 ? 350 : 200]
- if {[string length $prompt] > 60} { set w 500 }
-
- # in case we need a wide pop-up area that needs more room
- set popUpWidth [expr 7 * [maxListItemLength $names]]
- set altWidth [expr $popUpWidth + 60]
- set w [expr $altWidth > $w ? $altWidth : $w]
-
- set dialog [dialog::text $prompt 5 y [expr $w /6]]
- incr y 10
- eval lappend dialog [dialog::menu 30 y $names $default $popUpWidth]
- incr y 20
- eval lappend dialog [dialog::okcancel [expr $w - 160] y 0]
- set res [eval dialog -w $w -h $y $dialog]
-
- if [lindex $res 2] { error "Cancel" }
- # cancel was pressed
- if $index {
- # we have to take out the entries correponding to pop-up
- # menu separator lines -trf
- set possibilities [lremove -all $names "-"]
- return [lsearch -exact $possibilities [lindex $res 0]]
- } else {
- return [lindex $res 0]
- }
- }
-
- proc dialog::yesno {args} {
- switch -- [eval askyesno $args] {
- "yes" {return 1}
- "no" {return 0}
- "cancel" {error "cancelled"}
- }
- }
-
- proc global::allPrefs {{which "AllPreferences"}} {
- dialog::resetModified
- global flagPrefs varPrefs
- global::updateHelperFlags
- global::updateMiscFlags
- set AllPreferences [array names flagPrefs]
- set InterfacePreferences {Tiling Window Wrapping Gui}
- set StandardPreferences {Backups Electrics Miscellaneous Printer Tags WWW}
- set OtherPreferences [lremove -l $AllPreferences \
- $InterfacePreferences $StandardPreferences]
- foreach nm [set [join ${which} ""]] {
- lappend args [list $nm $flagPrefs($nm) $varPrefs($nm)]
- }
- dialog::is_global {
- dialog::global_adjust_flags [dialog::multipage $args]
- }
- }
-
- proc dialog::preferences {menu nm} {
- global flagPrefs varPrefs
- if ![info exists flagPrefs($nm)] {
- set nm "[string toupper [string index $nm 0]][string range $nm 1 end]"
- }
- if [string match "*Preferences" $nm] { return [global::allPrefs $nm] }
- if {$nm == "Miscellaneous"} { global::updateMiscFlags }
- if {$nm == "Helpers"} { global::updateHelperFlags }
- dialog::is_global {
- dialog::global_adjust_flags [dialog::onepage $flagPrefs($nm) $varPrefs($nm) "$nm preferences…"]
- }
- }
-
-
- # ◊◊◊◊ Global/mode menus ◊◊◊◊ #
-
- proc dialog::pickMenus {mode} {
- global modeMenus menus globalMenus_curr
- set w 20
- set h 45
- set endw [expr [llength [set all [lsort -ignore $menus]]] > 26 ? 560 : 380]
- if {$mode == "global"} {
- set current $globalMenus_curr
- set box "-t {Select global menus} [expr ($endw - 150)/2] 10 $endw 30"
- } else {
- set current $modeMenus($mode)
- set box "-t {Select menus for mode '$mode'} [expr ($endw - 180)/2] 10 $endw 30"
- }
- append box " -t {General menus:} 10 $h [expr $w +160] [expr $h +15]"
- incr h 20
- global alpha::package_menus
- set nonpkgs [lremove -l $all ${alpha::package_menus}]
- set npl [llength $nonpkgs]
- foreach m [set all [concat $nonpkgs ${alpha::package_menus}]] {
- if {[incr npl -1] == -1} {
- if {$w != 20} {
- incr h 30
- }
- append box " -t {Package menus:} 10 $h 180 [expr $h +15]"
- incr h 20
- set w 20
- }
- # Trying to be userfriendly
- switch -- $m {
- MATLMenu {set name "Matlab menu"}
- htmlUtilsMenu {set name "Html utilities menu"}
- default {
- set name $m
- regexp {(.*)Menu$} $name blah name
- set name "[string toupper [string index $name 0]][string tolower [string range $name 1 end]] menu"
- }
- }
- append box " -c [list $name] [expr ([lsearch -exact $current $m] >= 0)] $w $h \
- [expr $w + 160] [expr $h + 15]"
- incr w 180
- if {$w == $endw} {set w 20; incr h 20}
- }
- if {$w > 20} {set w 20; incr h 20}
- incr h 20
- set values [eval [concat dialog -w $endw -h [expr $h + 30] -b OK 20 $h 85 [expr $h + 20] \
- -b Cancel 105 $h 170 [expr $h + 20] $box]]
- if {[lindex $values 1]} {return $current}
- set newmenus ""
- for {set i 0} {$i < [llength $all]} {incr i} {
- if {[lindex $values [expr $i + 2]]} {lappend newmenus [lindex $all $i]}
- }
- return $newmenus
- }
-
-
- # ◊◊◊◊ Dialog sub-panes ◊◊◊◊ #
-
- set dialog::_not_global_flag ""
-
- ##
- # -------------------------------------------------------------------------
- #
- # "dialog::flag" --
- #
- # Builds a dialog-box page to be used for setting global/mode/package
- # preferences. It can contain preferences for flags (on/off), variables,
- # list items, mode items, files, folders, apps,...
- #
- # Results:
- # part of a script to generate the dialog
- #
- # Side effects:
- # sets maxT to the maximum height desired by the dialog
- #
- # --Version--Author------------------Changes-------------------------------
- # 1.0 Pete Keleher original
- # 2.0 <darley@fas.harvard.edu> much more sophisticated (and complex!)
- # -------------------------------------------------------------------------
- ##
- proc dialog::flag {flags vars {left 20} {top 40} {title {}}} {
- global maxT spelling alpha::prefNames
-
- if {$title != ""} {
- lappend args "-t" $title 30 10 400 25
- incr top 25
- }
- # if variable names are very long, switch to 2 columns
- if {[maxListItemLength $flags] > 18} {
- set perRow 2
- set width 225
- } else {
- set perRow 3
- set width 150
- }
- set height 15
-
- set ind 0
- set l $left
- foreach f $flags {
- set fname [quote::Prettify $f]
- if $spelling {text::british fname}
- lappend args "-c" $fname [dialog::getFlag $f] \
- $l $top [incr l $width] [expr $top + $height]
- if {[incr ind] % $perRow == 0} { set l $left ; incr top $height }
- }
-
- if {$ind} {
- set top [expr $top + 20]
- lappend args -p 100 [expr $top + 27] 300 [expr $top + 28]
- }
-
- dialog::buildSection $vars top 440 $left args alpha::prefNames
- incr top 30
-
- if {$top > $maxT} {set maxT $top}
- return $args
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "dialog::buildSection" --
- #
- # Build a dialog box section for a bunch of preferences. If 'flag_check'
- # is set the prefs can be flags or vars, else just vars.
- #
- # 'yvar' is a variable which contains the current y-pos in the box,
- # and should be incremented as appropriate by this procedure.
- # 'width' is the width of the dialog box (default 420)
- # 'l' is the left indent of all the items (default 20)
- # 'dialogvar' is the variable onto which all the construction code
- # should be lappended. If it is not given, then this proc will
- # return the items.
- # 'names', if given, is an array containing textual replacements for
- # the names of the variables to be used in the box.
- #
- # A minimal call would be:
- #
- # set y 20
- # set build [dialog::buildSection [list fillColumn] y]
- # eval lappend build [dialog::okcancel 20 y]
- # set res [eval dialog -w 480 -h $y $build]
- #
- # -------------------------------------------------------------------------
- ##
- proc dialog::buildSection {vars yvar {width 420} {l 20} {dialogvar ""} {names ""} {flag_check 1}} {
- global flag::list flag::type allFlags spelling alpha::colors modeMenus
- upvar $yvar t
- if {$dialogvar != ""} {upvar $dialogvar args}
- if {$names != ""} { upvar $names name }
- set height 17
- set lf 135
- set r [expr $l + $width]
- set rb [expr $r -45]
- foreach vset $vars {
- if {[llength $vset] > 1} {
- incr t 5
- if {[lindex $vset 0] != ""} {
- lappend args "-t" "[lindex $vset 0]" [expr $l -10] $t $r [expr $t +15]
- incr t 20
- }
- set vset [lrange $vset 1 end]
- }
- foreach v $vset {
- set vv [dialog::getFlag $v]
- if [info exists name($v)] {
- set vname $name($v)
- } else {
- set vname [quote::Prettify $v]
- }
- if $spelling {
- text::british vname
- }
- if {$flag_check && [lcontains allFlags $v]} {
- lappend args "-c" $vname $vv $l $t $r [expr $t + 15]
- incr t 15
- continue
- }
- # attempt to indent correctly
- set len [string length $vname]
- if {$len > 40} {
- lappend args "-t" "$vname:" $l $t [expr $r -30] [expr $t + $height]
- incr t 15
- set indent 100
- set tle ""
- } elseif {$len > 17} {
- set indent [expr 31 + 7 * $len]
- set tle {"-t" "$vname:" $l $t [expr $l + $indent] [expr $t + $height]}
- } else {
- set indent $lf
- set tle {"-t" "$vname:" $l $t [expr $l + $indent] [expr $t + $height]}
- }
-
- if {[info exists flag::list($v)]} {
- incr t 5
- eval lappend args $tle
- set litems [flag::options $v]
- if [regexp "index" [lindex [set flag::list($v)] 0]] {
- # set item to index, making sure bad values don't error
- if [catch {lindex $litems $vv} vv] { set vv [lindex $litems 0] }
- }
- lappend args "-m" [concat [list $vv] $litems] [expr $l + $indent -2] [expr $t -2] [expr $r - 14] [expr $t + $height +1]
- incr t 17
- } elseif {[regexp "Colou?r$" $v]} {
- incr t 5
- eval lappend args $tle
- lappend args "-m" [concat [list $vv] ${alpha::colors}] [expr $l + $indent -2] [expr $t -2] [expr $r - 14] [expr $t + $height +1]
- incr t 17
- } elseif {[regexp "Mode$" $v]} {
- incr t 5
- eval lappend args $tle
- if {$vv == ""} { set vv "<none>" }
- lappend args "-m" [concat [list $vv] [concat "<none>" [lsort [array names modeMenus]]]] [expr $l + $indent -2] $t [expr $r - 14] [expr $t + $height +1]
- incr t 17
- } elseif {[regexp "Sig$" $v]} {
- eval lappend args $tle
- set vv [dialog::specialView_Sig $vv]
- lappend args "-t" $vv [expr $l + $indent] $t $rb [expr $t + $height +1]
- eval lappend args [dialog::buttonSet $rb $t]
- incr t 17
- } elseif {[regexp "SearchPath$" $v]} {
- eval lappend args $tle
- if {$vv == ""} {
- lappend args "-t" "No search paths currently set." \
- [expr $l + $indent] $t $rb [expr $t + $height +1]
- eval lappend args [dialog::buttonSet $rb $t]
- incr t 17
- } else {
- eval lappend args [dialog::buttonSet $rb $t]
- foreach ppath $vv {
- lappend args "-t" [dialog::specialView_file $ppath] \
- [expr $l + $indent] $t $rb [expr $t + $height +1]
- incr t 17
- }
- }
- } elseif {[regexp "(Path|Folder)$" $v]} {
- eval lappend args $tle
- set vv [dialog::specialView_file $vv]
- lappend args "-t" $vv [expr $l + $indent] $t $rb [expr $t + $height +1]
- eval lappend args [dialog::buttonSet $rb $t]
- incr t 17
- } elseif {[info exists flag::type($v)]} {
- eval lappend args $tle
- set vv [dialog::specialView_[set flag::type($v)] $vv]
- lappend args "-t" $vv [expr $l + $indent] $t $rb [expr $t + $height +1]
- eval lappend args [dialog::buttonSet $rb $t]
- incr t 17
- } else {
- set eh [expr 1 + [string length $vv] / 60]
- incr t [expr 7 * $eh]
- eval lappend args $tle
- incr t [expr 5 -7 * $eh]
- lappend args "-e" $vv [expr $l + $indent] $t $r [expr $t + $eh * $height]
- incr t [expr 5 + 17 * $eh]
- }
- }
- }
- if {$dialogvar == ""} {return $args}
- }
- proc dialog::multipage {data} {
- dialog::resetModified
- global maxT
- # in case internal 'command-buttons' are used in the dialog
- while 1 {
-
- set left 20
-
- set names {}
- set editItems {}
- set cmd ""
- set maxT 0
- foreach arg [lsort $data] {
- if {[llength $arg] != 3} {error "Bad structure"}
- lappend names [lindex $arg 0]
- set flags [lindex $arg 1]
- set vars [lindex $arg 2]
- eval lappend editItems $flags $vars
- append cmd " -n \{[lindex $arg 0]\} " [dialog::flag $flags $vars]
- }
-
- set buttons [dialog::okcancel $left maxT]
- set height $maxT
- set res [eval [concat dialog -w 480 -h $height \
- -t "Preferences:" 60 10 140 30 $buttons \
- [list -m [concat [list [lindex $names 0]] $names] 150 10 405 30] $cmd]]
-
- if {[lindex $res 0]} {
- return [list [lrange $res 3 end] $editItems]
- } else {
- if [lindex $res 1] {
- error "Cancel chosen"
- }
- # a 'set…' button was pressed
- dialog::handleSet [lrange $res 3 end] $editItems
- }
- # end of large while loop
- }
-
- }
-
- proc dialog::onepage {flags vars {title ""}} {
- dialog::resetModified
- global maxT
- while 1 {
- set left 20
- set maxT 0
-
- set args [dialog::flag $flags $vars 20 10 $title]
- set height [expr $maxT + 30]
- set buttons [dialog::okcancel $left maxT]
- set height $maxT
- set res [eval [concat dialog -w 480 -h $height $buttons $args]]
-
- if [lindex $res 0] {
- return [list [lrange $res 2 end] [concat $flags $vars]]
- } else {
- if [lindex $res 1] {
- error "Cancel chosen"
- }
- dialog::handleSet [lrange $res 2 end] [concat $flags $vars]
- }
- # big while loop end
- }
-
- }
-
-
- # ◊◊◊◊ Dialog utilities ◊◊◊◊ #
- proc dialog::handleSet {res names} {
- global flag::type
- # a 'set…' button was pressed
- for {set i 0} {$i < [llength $names]} {incr i} {
- if {[lindex $res $i] == 1} {
- set v [lindex $names $i]
- if {[regexp "SearchPath$" $v]} {
- set res [buttonAlert "Perform what action to one of the [quote::Prettify $v]s" "Add" "Remove" "Change" "Cancel"]
- switch -- $res {
- "Add" {
- # this set… pressed
- set newval [get_directory -p "New [quote::Prettify $v]:"]
- if {$newval != ""} {
- set newval [concat [dialog::getFlag $v] [list $newval]]
- dialog::modified $v $newval
- }
- }
- "Remove" {
- if ![catch {set remove [listpick -p "Remove which items from [quote::Prettify $v]:" -l [dialog::getFlag $v]]}] {
- # remove them
- set newval [lremove -l [dialog::getFlag $v] $remove]
- dialog::modified $v $newval
- }
- }
- "Change" {
- if ![catch {set change [listpick -p "Change which item from [quote::Prettify $v]:" [dialog::getFlag $v]]}] {
- # change it
- set newval [get_directory -p "Replacement [quote::Prettify $v]:"]
- if {$newval != ""} {
- set old [dialog::getFlag $v]
- set i [lsearch -exact $old $change]
- set old [lreplace $old $i $i $newval]
- dialog::modified $v $old
- }
- }
- }
- }
- break
- } elseif {[regexp "(Path|Folder)$" $v]} {
- # this set… pressed
- set newval [get_directory -p "New [quote::Prettify $v]:"]
- if {$newval != ""} {
- dialog::modified $v $newval
- }
- break
- } elseif {[info exists flag::type($v)]} {
- dialog::specialSet_[set flag::type($v)] $v
- break
- } elseif {[regexp "Sig$" $v]} {
- global $v
- set newval [dialog::findApp $v [set $v]]
- if {$newval != ""} {
- dialog::modified $v $newval
- }
- break
- }
- }
- }
- }
-
- proc dialog::setFlag {name val} {
- global dialog::_not_global_flag
- if {${dialog::_not_global_flag} != ""} {
- global ${dialog::_not_global_flag}
- set ${dialog::_not_global_flag}($name) $val
- } else {
- global $name
- set $name $val
- }
- }
-
- proc dialog::getFlag {name} {
- global dialog::_modified
- if [info exists dialog::_modified($name)] {
- return [set dialog::_modified($name)]
- } else {
- return [dialog::getOldFlag $name]
- }
- }
- proc dialog::getOldFlag {name} {
- global dialog::_not_global_flag
- if {${dialog::_not_global_flag} != ""} {
- global ${dialog::_not_global_flag}
- return [set ${dialog::_not_global_flag}($name)]
- } else {
- global dialog::_is_global
- if [info exists dialog::_is_global] {
- global global::_vars
- if {[info exists global::_vars] \
- && [set i [lsearch ${global::_vars} $name]] != -1} {
- return [lindex ${global::_vars} [incr i]]
- }
- }
- }
- global $name
- if [info exists $name] {
- return [set $name]
- } else {
- alertnote "Global variable '$name' in the dialog isn't set.\r\
- I'll try to fix that."
- return [set $name ""]
- }
- }
-
- proc dialog::is_global {script} {
- global dialog::_is_global
- set dialog::_is_global 1
- catch "[list uplevel $script]"
- unset dialog::_is_global
- }
- proc dialog::resetModified {} {
- global dialog::_modified
- catch {unset dialog::_modified}
- }
-
- proc dialog::global_adjust_flags {values_items} {
- global flag::procs modifiedVars global::_vars
- set res [lindex $values_items 0]
- set editItems [lindex $values_items 1]
- unset values_items
- foreach fset $editItems {
- if {[llength $fset] > 1} {
- set fset [lrange $fset 1 end]
- }
- foreach flag $fset {
- set val [lindex $res 0]
- set res [lrange $res 1 end]
- dialog::postManipulate
- if {[info exists global::_vars] \
- && [set i [lsearch ${global::_vars} $flag]] != -1} {
- set orig [lindex ${global::_vars} [incr i]]
- if {$orig != $val} {
- set global::_vars [lreplace ${global::_vars} $i $i $val]
- lappend warn_global $flag
- }
- } else {
- global $flag
- set orig [set $flag]
- if {$orig != $val} {
- set $flag $val
- }
- }
- if {$orig != $val} {
- if {[info exists flag::procs($flag)]} {
- [set flag::procs($flag)] $flag
- }
- lappend modifiedVars $flag
- }
- }
- }
- if [info exists warn_global] {
- if {[llength $warn_global] == 1} {
- set msg "is a global pref"
- } else {
- set msg "are global prefs"
- }
- alertnote "You modified [join $warn_global {, }] which $msg,\
- but currently over-ridden by mode-specific values. If you meant to\
- modify the latter values, use the mode prefs dialog."
- }
- }
-
- proc dialog::postManipulate {} {
- global flag::list flag::type
- upvar flag f
- upvar val v
-
- if [info exists flag::list($f)] {
- switch -- [lindex [set l [set flag::list($f)]] 0] {
- "index" {
- set v [lsearch -exact [lindex $l 1] $v]
- }
- "varindex" {
- set itemv [lindex $l 1]
- global $itemv
- set v [lsearch -exact [set $itemv] $v]
- }
- }
- }
- if {$v == "<none>" && [regexp "Mode$" $f]} { set v "" }
- # This check also captures any 'dialog::modified items
- # This allows flags which are somehow already set by the
- # dialog (for instance if called recursively, or if set by embedded
- # 'Set…' buttons) to be registered as modifed by our calling procedure.
- if {[regexp "(Path|Folder|Sig)$" $f]} {
- set v [dialog::getFlag $f]
- } elseif {[info exists flag::type($f)]} {
- switch -- [set flag::type($f)] {
- "binding" {
- # setup the changed binding
- set old [dialog::getOldFlag $f]
- set v [dialog::getFlag $f]
- if {$old != $v} {
- global flag::binding
- if [info exists flag::binding($f)] {
- set m [lindex [set flag::binding($f)] 0]
- if {[set proc [lindex [set flag::binding($f)] 1]] == 1} {
- set proc $f
- }
- namespace eval ::alpha [list catch "unbind [keys::toBind $old] [list $proc] $m"]
- namespace eval ::alpha [list catch "bind [keys::toBind $v] [list $proc] $m"]
- }
- }
- }
- default {
- set v [dialog::getFlag $f]
- }
- }
- }
- }
-
- proc dialog::modified {name val} {
- global dialog::_modified
- set dialog::_modified($name) $val
- }
-
- # Used on modified mode flags.
- set flag::procs(stringColor) "stringColorProc"
- set flag::procs(commentColor) "stringColorProc"
- set flag::procs(keywordColor) "stringColorProc"
- set flag::procs(funcColor) "stringColorProc"
- set flag::procs(sectionColor) "stringColorProc"
- set flag::procs(bracesColor) "stringColorProc"
-
- proc global::updateHelperFlags {} {
- uplevel #0 {
- set flagPrefs(Helpers) {}
- set varPrefs(Helpers) [info globals *Sig]
- }
- }
-
- proc global::updateMiscFlags {} {
- global flagPrefs varPrefs allFlags modeVars allVars
- # flags can be in either flagPrefs or varPrefs if we're grouping
- # preferences according to function
- set all {}
- set flagPrefs(Miscellaneous) {}
- set varPrefs(Miscellaneous) {}
- foreach v [array names flagPrefs] {
- eval lappend all $flagPrefs($v)
- if [regexp {[{}]} $varPrefs($v)] {
- # we're grouping
- foreach i $varPrefs($v) {
- if {[llength $i] > 1} {
- eval lappend all [lrange $i 1 end]
- } else {
- lappend all $i
- }
- }
- } else {
- eval lappend all $varPrefs($v)
- }
- }
- foreach f $allFlags {
- if {([lsearch $modeVars $f] < 0)} {
- if {[lsearch -exact $all $f] == -1} {
- lappend flagPrefs(Miscellaneous) $f
- }
- }
- }
-
- foreach f $allVars {
- if {([lsearch $modeVars $f] < 0)} {
- if {[lsearch -exact $all $f] == -1} {
- if [regexp {Sig$} $f] {
- lappend varPrefs(Helpers) $f
- } else {
- lappend varPrefs(Miscellaneous) $f
- }
- }
- }
- }
- }
-
- #================================================================================
-
- proc maxListItemLength {l} {
- set m 0
- foreach item $l {
- if {[set mm [string length $item]] > $m} { set m $mm }
- }
- return $m
- }
-
- proc stringColorProc {flag} {
- global $flag mode
-
- if {[set $flag] == "none"} {
- set $flag "foreground"
- }
- if {$flag == "stringColor"} {
- regModeKeywords -a -s $stringColor $mode
- } elseif {$flag == "commentColor"} {
- regModeKeywords -a -c $commentColor $mode
- } elseif {$flag == "funcColor"} {
- regModeKeywords -a -f $funcColor $mode
- } elseif {$flag == "bracesColor"} {
- regModeKeywords -a -I $bracesColor $mode
- } elseif {($flag == "keywordColor") || ($flag == "sectionColor")} {
- alertnote "Change in keyword color will take effect after Alpha restarts."
- return
- } else {
- alertnote "Change in $flag color will take effect after Alpha restarts."
- return
- }
- refresh
- }
-
- # ◊◊◊◊ Dialog sub-items ◊◊◊◊ #
-
- proc dialog::buttonSet {x y} {
- return [list -b Set… $x $y [expr $x + 45] [expr $y + 15]]
- }
-
- proc dialog::okcancel {x yy {vertical 0}} {
- upvar $yy y
- set i [dialog::button "OK" $x y]
- if {!$vertical} {
- incr y -30
- incr x 80
- }
- eval lappend i [dialog::button "Cancel" $x y]
- return $i
- }
-
- proc dialog::menu {x yy item {def "def"} {requestedWidth 0}} {
- upvar $yy y
- set m [concat [list $def] $item]
- if {$requestedWidth == 0} {
- set popUpWidth 340
- } else {
- set popUpWidth $requestedWidth
- }
-
- set res [list -m $m $x $y [expr $x + $popUpWidth] [expr $y +20]]
- incr y 20
- return $res
- }
- proc dialog::button {name x yy args} {
- upvar $yy y
- set incr 65
- if {[set i [expr [string length $name] - 7]] > 0} {
- incr incr [expr $i * 7]
- }
- set res [list -b $name $x $y [expr $x +$incr] [expr $y +20]]
- if [llength $args] {
- eval lappend res [eval dialog::button $args]
- return $res
- }
- incr y 30
- return $res
- }
- proc dialog::title {name w} {
- set l [expr ${w}/2 - 4 * [string length $name]]
- if {$l < 0} {set l 0}
- return [list -t $name $l 10 [expr $w - $l] 25]
- }
- proc dialog::text {name x yy {split 0}} {
- upvar $yy y
- if {!$split || $name == ""} {
- set res [list -t $name $x $y [expr $x + 7 * [string length $name]] \
- [expr $y +15]]
- incr y 18
- } else {
- global fillColumn
- set f $fillColumn
- set fillColumn $split
- # modified to handle return deliminated text as paragraphs -trf
- set paragraphList [split $name "\r"]
- foreach para $paragraphList {
- set lines [breakIntoLines $para]
- foreach line [split $lines "\r"] {
- eval lappend res [list -t $line $x $y [expr $x + 4+ 8 * [string length $line]] \
- [expr $y +15]]
- incr y 18
- }
- incr y 10
- }
- set fillColumn $f
- }
- return $res
- }
- proc dialog::edit {name x yy chars {cols 1}} {
- upvar $yy y
- set res [list -e $name $x $y [expr $x + 10 * $chars] [expr $y + 15 * $cols]]
- incr y [expr 5 + 15*$cols]
- return $res
- }
- proc dialog::textedit {name default x yy chars {height 1}} {
- upvar $yy y
- set res [list -t $name $x $y [expr $x + 8 * [string length $name]]\
- [expr $y +16] \
- -e $default $x [expr $y + 20] [expr $x + 10 * $chars] \
- [expr $y +20 + 16*$height]]
- incr y [expr 24 + 16*$height]
- return $res
- }
- proc dialog::checkbox {name default x yy} {
- upvar $yy y
- set res [list -c $name $default $x $y]
- set c [regsub -all -nocase {[wm]} $name "" ""]
- set len [expr 10 * [string length $name] + 4 * $c]
- lappend res [expr $x + $len] [expr $y +15]
- incr y 18
- return $res
- }
-
- # ◊◊◊◊ Multiple bindings dialogs ◊◊◊◊ #
-
- proc dialog::arrayBindings {name array {for_menu 0}} {
- upvar $array a
- foreach n [array names a] {
- lappend l [list $a($n) $n]
- }
- if [info exists l] {
- eval dialog::adjustBindings [list $name modified "" $for_menu] $l
- }
- array set a [array get modified]
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "dialog::adjustBindings" --
- #
- # 'args' is a list of pairs. The first element of each pair is the
- # menu binding, and the second element is a descriptive name for the
- # element. 'array' is the name of an array in the calling proc's
- # scope which is used to return modified bindings.
- #
- # Results:
- #
- #
- #
- # CURRENTLY UNDER DEVELOPMENT. Should eventually work for html mode,
- # any general binding set you like, in menus or outside (e.g. for
- # completion key-sets),…
- #
- # NOTE for Johan: this proc takes 'name', the 'for_menu' flag
- # and a list of items. It returns the modified items in 'array',
- # which can be turned into a list using 'array get'. It returns
- # just the names of the modified items in the list 'mod', if given.
- #
- # It doesn't use your 'array($name/$value)'
- # --Version--Author------------------Changes-------------------------------
- # 1.0 Johan Linde original for html mode
- # 1.1 <darley@fas.harvard.edu> general purpose version
- # -------------------------------------------------------------------------
- ##
- proc dialog::adjustBindings {name array {mod {}} {for_menu 1} args} {
- regsub -all {\"\(-\"} $args "" items
- upvar $array key_changes
-
- foreach it $items {
- if {[info exists key_changes([lindex $it 1])]} {
- set tmpKeys([lindex $it 1]) $key_changes([lindex $it 1])
- } else {
- set tmpKeys([lindex $it 1]) [lindex $it 0]
- }
- }
- # do we return modified stuff?
- if {$mod != ""} { upvar $mod modified }
- set modified ""
- while {1} {
- # Build dialog.
- set box ""
- set h 30
- foreach it $items {
- if {$it == "(-"} {continue}
- set w 210
- set w2 370
- set key $tmpKeys([lindex $it 1])
- set key1 [dialog::specialView_binding $key]
- set it2 [split [lindex $it 1] /]
- if {[llength $it2] == 1} {
- lappend box -t [lindex $it2 0] 65 $h 205 [expr $h + 15] -t $key1 $w $h $w2 [expr $h + 15]
- eval lappend box [dialog::buttonSet 10 $h]
- incr h 17
- } else {
- lappend box -t [lindex $it2 0] 65 $h 205 [expr $h + 15] -t $key1 $w $h $w2 [expr $h + 15]
- eval lappend box [dialog::buttonSet 10 [expr $h +8]]
- incr h 17
- if {$key1 != "<no binding>"} {regsub {((ctrl-)?(shift-)?)(.*)} $key1 {\1opt-\4} key1}
- lappend box -t [lindex $it2 1] 65 $h 205 [expr $h + 15] -t $key1 $w $h $w2 [expr $h + 15]
- incr h 17
- }
- }
- set buttons "-b OK 20 [expr $h + 10] 85 [expr $h + 30] -b Cancel 105 [expr $h + 10] 170 [expr $h + 30]"
- set values [eval [concat dialog -w 380 -h [expr $h + 40] $buttons -t [list $name] 50 10 250 25 $box]]
- if {[lindex $values 1]} {
- # Cancel
- return "Cancel"
- } elseif {[lindex $values 0]} {
- # Save new key bindings
- foreach it $modified {
- set key_changes($it) $tmpKeys($it)
- }
- return
- } else {
- # Get a new key.
- set it [lindex [lindex $items [expr [lsearch $values 1] - 2]] 1]
- if {![catch {dialog::getAKey $it $tmpKeys($it) $for_menu} newKey] && $newKey != $tmpKeys($it)} {
- set tmpKeys($it) $newKey
- lappend modified $it
- }
- }
- }
- }
-
- # ◊◊◊◊ Manipulation of special pref types ◊◊◊◊ #
-
- proc dialog::specialView_binding {key} {
- append key1 [keys::modifiersTo $key "verbose"]
- append key1 [keys::verboseKey $key]
- if {$key1 == ""} { return "<no binding>" }
- return $key1
- }
-
- proc dialog::specialSet_binding {v {menu 0}} {
- # Set… pressed
- set oldB [dialog::getFlag $v]
- if {![catch {dialog::getAKey [quote::Prettify $v] $oldB $menu} newKey] && $newKey != $oldB} {
- dialog::modified $v $newKey
- }
- }
-
- proc dialog::specialView_menubinding {key} {
- dialog::specialView_binding $key
- }
-
- proc dialog::specialSet_menubinding {v} {
- dialog::specialSet_binding $v 1
- }
- proc dialog::specialView_Sig {vv} {
- if {$vv != ""} {
- if [catch {nameFromAppl $vv} path] {
- return "Unknown application with sig '$vv'"
- } else {
- return [dialog::specialView_file $path]
- }
- }
- return ""
- }
-
- proc dialog::specialView_io-file {vv} {
- dialog::specialView_file $vv
- }
-
- proc dialog::specialView_file {vv} {
- if {[set sl [string length $vv]] > 40} {
- set vv "[string range $vv 0 14]...[string range $vv [expr $sl -22] end]"
- }
- return $vv
- }
- proc dialog::specialSet_file {v} {
- # Set… pressed
- set old [dialog::getFlag $v]
- if {![catch {getfile [quote::Prettify "New $v"] [dialog::getFlag $v]} ff] \
- && $ff != $old} {
- dialog::modified $v $ff
- }
- }
- proc dialog::specialSet_io-file {v} {
- # Set… pressed
- set old [dialog::getFlag $v]
- if {![catch {putfile [quote::Prettify "New $v"] [dialog::getFlag $v]} ff] \
- && $ff != $old} {
- dialog::modified $v $ff
- }
- }
-
-
-