diff options
author | Shashank | 2017-05-29 12:40:26 +0530 |
---|---|---|
committer | Shashank | 2017-05-29 12:40:26 +0530 |
commit | 0345245e860375a32c9a437c4a9d9cae807134e9 (patch) | |
tree | ad51ecbfa7bcd3cc5f09834f1bb8c08feaa526a4 /modules/tclsci/tcl/BWidget | |
download | scilab_for_xcos_on_cloud-0345245e860375a32c9a437c4a9d9cae807134e9.tar.gz scilab_for_xcos_on_cloud-0345245e860375a32c9a437c4a9d9cae807134e9.tar.bz2 scilab_for_xcos_on_cloud-0345245e860375a32c9a437c4a9d9cae807134e9.zip |
CMSCOPE changed
Diffstat (limited to 'modules/tclsci/tcl/BWidget')
79 files changed, 19585 insertions, 0 deletions
diff --git a/modules/tclsci/tcl/BWidget/arrow.tcl b/modules/tclsci/tcl/BWidget/arrow.tcl new file mode 100755 index 000000000..e51753a92 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/arrow.tcl @@ -0,0 +1,551 @@ +# ------------------------------------------------------------------------------ +# arrow.tcl +# This file is part of Unifix BWidget Toolkit +# ------------------------------------------------------------------------------ +# Index of commands: +# Public commands +# - ArrowButton::create +# - ArrowButton::configure +# - ArrowButton::cget +# - ArrowButton::invoke +# Private commands (redraw commands) +# - ArrowButton::_redraw +# - ArrowButton::_redraw_state +# - ArrowButton::_redraw_relief +# - ArrowButton::_redraw_whole +# Private commands (event bindings) +# - ArrowButton::_destroy +# - ArrowButton::_enter +# - ArrowButton::_leave +# - ArrowButton::_press +# - ArrowButton::_release +# - ArrowButton::_repeat +# ------------------------------------------------------------------------------ + +namespace eval ArrowButton { + Widget::define ArrowButton arrow DynamicHelp + + Widget::tkinclude ArrowButton button .c \ + include [list \ + -borderwidth -bd \ + -relief -highlightbackground \ + -highlightcolor -highlightthickness -takefocus] + + Widget::declare ArrowButton [list \ + [list -type Enum button 0 [list arrow button]] \ + [list -dir Enum top 0 [list top bottom left right]] \ + [list -width Int 15 0 "%d >= 0"] \ + [list -height Int 15 0 "%d >= 0"] \ + [list -ipadx Int 0 0 "%d >= 0"] \ + [list -ipady Int 0 0 "%d >= 0"] \ + [list -clean Int 2 0 "%d >= 0 && %d <= 2"] \ + [list -activeforeground TkResource "" 0 button] \ + [list -activebackground TkResource "" 0 button] \ + [list -disabledforeground TkResource "" 0 button] \ + [list -foreground TkResource "" 0 button] \ + [list -background TkResource "" 0 button] \ + [list -state TkResource "" 0 button] \ + [list -troughcolor TkResource "" 0 scrollbar] \ + [list -arrowbd Int 1 0 "%d >= 0 && %d <= 2"] \ + [list -arrowrelief Enum raised 0 [list raised sunken]] \ + [list -command String "" 0] \ + [list -armcommand String "" 0] \ + [list -disarmcommand String "" 0] \ + [list -repeatdelay Int 0 0 "%d >= 0"] \ + [list -repeatinterval Int 0 0 "%d >= 0"] \ + [list -fg Synonym -foreground] \ + [list -bg Synonym -background] \ + ] + DynamicHelp::include ArrowButton balloon + + bind BwArrowButtonC <Enter> {ArrowButton::_enter %W} + bind BwArrowButtonC <Leave> {ArrowButton::_leave %W} + bind BwArrowButtonC <ButtonPress-1> {ArrowButton::_press %W} + bind BwArrowButtonC <ButtonRelease-1> {ArrowButton::_release %W} + bind BwArrowButtonC <Key-space> {ArrowButton::invoke %W; break} + bind BwArrowButtonC <Return> {ArrowButton::invoke %W; break} + bind BwArrowButton <Configure> {ArrowButton::_redraw_whole %W %w %h} + bind BwArrowButton <Destroy> {ArrowButton::_destroy %W} + + variable _grab + variable _moved + + array set _grab {current "" pressed "" oldstate "normal" oldrelief ""} +} + + +# ----------------------------------------------------------------------------- +# Command ArrowButton::create +# ----------------------------------------------------------------------------- +proc ArrowButton::create { path args } { + # Initialize configuration mappings and parse arguments + array set submaps [list ArrowButton [list ] .c [list ]] + array set submaps [Widget::parseArgs ArrowButton $args] + + # Create the class frame (so we can do the option db queries) + frame $path -class ArrowButton -borderwidth 0 -highlightthickness 0 + Widget::initFromODB ArrowButton $path $submaps(ArrowButton) + + # Create the canvas with the initial options + eval [list canvas $path.c] $submaps(.c) + + # Compute the width and height of the canvas from the width/height + # of the ArrowButton and the borderwidth/hightlightthickness. + set w [Widget::getMegawidgetOption $path -width] + set h [Widget::getMegawidgetOption $path -height] + set bd [Widget::cget $path -borderwidth] + set ht [Widget::cget $path -highlightthickness] + set pad [expr {2*($bd+$ht)}] + + $path.c configure -width [expr {$w-$pad}] -height [expr {$h-$pad}] + bindtags $path [list $path BwArrowButton [winfo toplevel $path] all] + bindtags $path.c [list $path.c BwArrowButtonC [winfo toplevel $path.c] all] + pack $path.c -expand yes -fill both + + DynamicHelp::sethelp $path $path.c 1 + + set ::ArrowButton::_moved($path) 0 + + return [Widget::create ArrowButton $path] +} + + +# ----------------------------------------------------------------------------- +# Command ArrowButton::configure +# ----------------------------------------------------------------------------- +proc ArrowButton::configure { path args } { + set res [Widget::configure $path $args] + + set ch1 [expr {[Widget::hasChanged $path -width w] | + [Widget::hasChanged $path -height h] | + [Widget::hasChanged $path -borderwidth bd] | + [Widget::hasChanged $path -highlightthickness ht]}] + set ch2 [expr {[Widget::hasChanged $path -type val] | + [Widget::hasChanged $path -ipadx val] | + [Widget::hasChanged $path -ipady val] | + [Widget::hasChanged $path -arrowbd val] | + [Widget::hasChanged $path -clean val] | + [Widget::hasChanged $path -dir val]}] + + if { $ch1 } { + set pad [expr {2*($bd+$ht)}] + $path.c configure \ + -width [expr {$w-$pad}] -height [expr {$h-$pad}] \ + -borderwidth $bd -highlightthickness $ht + set ch2 1 + } + if { $ch2 } { + _redraw_whole $path [winfo width $path] [winfo height $path] + } else { + _redraw_relief $path + _redraw_state $path + } + DynamicHelp::sethelp $path $path.c + + return $res +} + + +# ----------------------------------------------------------------------------- +# Command ArrowButton::cget +# ----------------------------------------------------------------------------- +proc ArrowButton::cget { path option } { + return [Widget::cget $path $option] +} + + +# ------------------------------------------------------------------------------ +# Command ArrowButton::invoke +# ------------------------------------------------------------------------------ +proc ArrowButton::invoke { path } { + if { ![string equal [winfo class $path] "ArrowButton"] } { + set path [winfo parent $path] + } + if { ![string equal [Widget::getoption $path -state] "disabled"] } { + set oldstate [Widget::getoption $path -state] + if { [string equal [Widget::getoption $path -type] "button"] } { + set oldrelief [Widget::getoption $path -relief] + configure $path -state active -relief sunken + } else { + set oldrelief [Widget::getoption $path -arrowrelief] + configure $path -state active -arrowrelief sunken + } + update idletasks + if {[llength [set cmd [Widget::getoption $path -armcommand]]]} { + uplevel \#0 $cmd + } + after 10 + if { [string equal [Widget::getoption $path -type] "button"] } { + configure $path -state $oldstate -relief $oldrelief + } else { + configure $path -state $oldstate -arrowrelief $oldrelief + } + if {[llength [set cmd [Widget::getoption $path -disarmcommand]]]} { + uplevel \#0 $cmd + } + if {[llength [set cmd [Widget::getoption $path -command]]]} { + uplevel \#0 $cmd + } + } +} + + +# ------------------------------------------------------------------------------ +# Command ArrowButton::_redraw +# ------------------------------------------------------------------------------ +proc ArrowButton::_redraw { path width height } { + variable _moved + + set _moved($path) 0 + set type [Widget::getoption $path -type] + set dir [Widget::getoption $path -dir] + set bd [expr {[$path.c cget -borderwidth] + [$path.c cget -highlightthickness] + 1}] + set clean [Widget::getoption $path -clean] + if { [string equal $type "arrow"] } { + if { [set id [$path.c find withtag rect]] == "" } { + $path.c create rectangle $bd $bd [expr {$width-$bd-1}] [expr {$height-$bd-1}] -tags rect + } else { + $path.c coords $id $bd $bd [expr {$width-$bd-1}] [expr {$height-$bd-1}] + } + $path.c lower rect + set arrbd [Widget::getoption $path -arrowbd] + set bd [expr {$bd+$arrbd-1}] + } else { + $path.c delete rect + } + # w and h are max width and max height of arrow + set w [expr {$width - 2*([Widget::getoption $path -ipadx]+$bd)}] + set h [expr {$height - 2*([Widget::getoption $path -ipady]+$bd)}] + + if { $w < 2 } {set w 2} + if { $h < 2 } {set h 2} + + if { $clean > 0 } { + # arrange for base to be odd + if { [string equal $dir "top"] || [string equal $dir "bottom"] } { + if { !($w % 2) } { + incr w -1 + } + if { $clean == 2 } { + # arrange for h = (w+1)/2 + set h2 [expr {($w+1)/2}] + if { $h2 > $h } { + set w [expr {2*$h-1}] + } else { + set h $h2 + } + } + } else { + if { !($h % 2) } { + incr h -1 + } + if { $clean == 2 } { + # arrange for w = (h+1)/2 + set w2 [expr {($h+1)/2}] + if { $w2 > $w } { + set h [expr {2*$w-1}] + } else { + set w $w2 + } + } + } + } + + set x0 [expr {($width-$w)/2}] + set y0 [expr {($height-$h)/2}] + set x1 [expr {$x0+$w-1}] + set y1 [expr {$y0+$h-1}] + + switch $dir { + top { + set xd [expr {($x0+$x1)/2}] + if { [set id [$path.c find withtag poly]] == "" } { + $path.c create polygon $x0 $y1 $x1 $y1 $xd $y0 -tags poly + } else { + $path.c coords $id $x0 $y1 $x1 $y1 $xd $y0 + } + if { [string equal $type "arrow"] } { + if { [set id [$path.c find withtag bot]] == "" } { + $path.c create line $x0 $y1 $x1 $y1 $xd $y0 -tags bot + } else { + $path.c coords $id $x0 $y1 $x1 $y1 $xd $y0 + } + if { [set id [$path.c find withtag top]] == "" } { + $path.c create line $x0 $y1 $xd $y0 -tags top + } else { + $path.c coords $id $x0 $y1 $xd $y0 + } + $path.c itemconfigure top -width $arrbd + $path.c itemconfigure bot -width $arrbd + } else { + $path.c delete top + $path.c delete bot + } + } + bottom { + set xd [expr {($x0+$x1)/2}] + if { [set id [$path.c find withtag poly]] == "" } { + $path.c create polygon $x1 $y0 $x0 $y0 $xd $y1 -tags poly + } else { + $path.c coords $id $x1 $y0 $x0 $y0 $xd $y1 + } + if { [string equal $type "arrow"] } { + if { [set id [$path.c find withtag top]] == "" } { + $path.c create line $x1 $y0 $x0 $y0 $xd $y1 -tags top + } else { + $path.c coords $id $x1 $y0 $x0 $y0 $xd $y1 + } + if { [set id [$path.c find withtag bot]] == "" } { + $path.c create line $x1 $y0 $xd $y1 -tags bot + } else { + $path.c coords $id $x1 $y0 $xd $y1 + } + $path.c itemconfigure top -width $arrbd + $path.c itemconfigure bot -width $arrbd + } else { + $path.c delete top + $path.c delete bot + } + } + left { + set yd [expr {($y0+$y1)/2}] + if { [set id [$path.c find withtag poly]] == "" } { + $path.c create polygon $x1 $y0 $x1 $y1 $x0 $yd -tags poly + } else { + $path.c coords $id $x1 $y0 $x1 $y1 $x0 $yd + } + if { [string equal $type "arrow"] } { + if { [set id [$path.c find withtag bot]] == "" } { + $path.c create line $x1 $y0 $x1 $y1 $x0 $yd -tags bot + } else { + $path.c coords $id $x1 $y0 $x1 $y1 $x0 $yd + } + if { [set id [$path.c find withtag top]] == "" } { + $path.c create line $x1 $y0 $x0 $yd -tags top + } else { + $path.c coords $id $x1 $y0 $x0 $yd + } + $path.c itemconfigure top -width $arrbd + $path.c itemconfigure bot -width $arrbd + } else { + $path.c delete top + $path.c delete bot + } + } + right { + set yd [expr {($y0+$y1)/2}] + if { [set id [$path.c find withtag poly]] == "" } { + $path.c create polygon $x0 $y1 $x0 $y0 $x1 $yd -tags poly + } else { + $path.c coords $id $x0 $y1 $x0 $y0 $x1 $yd + } + if { [string equal $type "arrow"] } { + if { [set id [$path.c find withtag top]] == "" } { + $path.c create line $x0 $y1 $x0 $y0 $x1 $yd -tags top + } else { + $path.c coords $id $x0 $y1 $x0 $y0 $x1 $yd + } + if { [set id [$path.c find withtag bot]] == "" } { + $path.c create line $x0 $y1 $x1 $yd -tags bot + } else { + $path.c coords $id $x0 $y1 $x1 $yd + } + $path.c itemconfigure top -width $arrbd + $path.c itemconfigure bot -width $arrbd + } else { + $path.c delete top + $path.c delete bot + } + } + } +} + + +# ------------------------------------------------------------------------------ +# Command ArrowButton::_redraw_state +# ------------------------------------------------------------------------------ +proc ArrowButton::_redraw_state { path } { + set state [Widget::getoption $path -state] + if { [string equal [Widget::getoption $path -type] "button"] } { + switch $state { + normal {set bg -background; set fg -foreground} + active {set bg -activebackground; set fg -activeforeground} + disabled {set bg -background; set fg -disabledforeground} + } + set fg [Widget::getoption $path $fg] + $path.c configure -background [Widget::getoption $path $bg] + $path.c itemconfigure poly -fill $fg -outline $fg + } else { + switch $state { + normal {set stipple ""; set bg [Widget::getoption $path -background] } + active {set stipple ""; set bg [Widget::getoption $path -activebackground] } + disabled {set stipple gray50; set bg black } + } + set thrc [Widget::getoption $path -troughcolor] + $path.c configure -background [Widget::getoption $path -background] + $path.c itemconfigure rect -fill $thrc -outline $thrc + $path.c itemconfigure poly -fill $bg -outline $bg -stipple $stipple + } +} + + +# ------------------------------------------------------------------------------ +# Command ArrowButton::_redraw_relief +# ------------------------------------------------------------------------------ +proc ArrowButton::_redraw_relief { path } { + variable _moved + + if { [string equal [Widget::getoption $path -type] "button"] } { + if { [string equal [Widget::getoption $path -relief] "sunken"] } { + if { !$_moved($path) } { + $path.c move poly 1 1 + set _moved($path) 1 + } + } else { + if { $_moved($path) } { + $path.c move poly -1 -1 + set _moved($path) 0 + } + } + } else { + set col3d [BWidget::get3dcolor $path [Widget::getoption $path -background]] + switch [Widget::getoption $path -arrowrelief] { + raised {set top [lindex $col3d 1]; set bot [lindex $col3d 0]} + sunken {set top [lindex $col3d 0]; set bot [lindex $col3d 1]} + } + $path.c itemconfigure top -fill $top + $path.c itemconfigure bot -fill $bot + } +} + + +# ------------------------------------------------------------------------------ +# Command ArrowButton::_redraw_whole +# ------------------------------------------------------------------------------ +proc ArrowButton::_redraw_whole { path width height } { + _redraw $path $width $height + _redraw_relief $path + _redraw_state $path +} + + +# ------------------------------------------------------------------------------ +# Command ArrowButton::_enter +# ------------------------------------------------------------------------------ +proc ArrowButton::_enter { path } { + variable _grab + set path [winfo parent $path] + set _grab(current) $path + if { ![string equal [Widget::getoption $path -state] "disabled"] } { + set _grab(oldstate) [Widget::getoption $path -state] + configure $path -state active + if { $_grab(pressed) == $path } { + if { [string equal [Widget::getoption $path -type] "button"] } { + set _grab(oldrelief) [Widget::getoption $path -relief] + configure $path -relief sunken + } else { + set _grab(oldrelief) [Widget::getoption $path -arrowrelief] + configure $path -arrowrelief sunken + } + } + } +} + + +# ------------------------------------------------------------------------------ +# Command ArrowButton::_leave +# ------------------------------------------------------------------------------ +proc ArrowButton::_leave { path } { + variable _grab + set path [winfo parent $path] + set _grab(current) "" + if { ![string equal [Widget::getoption $path -state] "disabled"] } { + configure $path -state $_grab(oldstate) + if { $_grab(pressed) == $path } { + if { [string equal [Widget::getoption $path -type] "button"] } { + configure $path -relief $_grab(oldrelief) + } else { + configure $path -arrowrelief $_grab(oldrelief) + } + } + } +} + + +# ------------------------------------------------------------------------------ +# Command ArrowButton::_press +# ------------------------------------------------------------------------------ +proc ArrowButton::_press { path } { + variable _grab + set path [winfo parent $path] + if { ![string equal [Widget::getoption $path -state] "disabled"] } { + set _grab(pressed) $path + if { [string equal [Widget::getoption $path -type] "button"] } { + set _grab(oldrelief) [Widget::getoption $path -relief] + configure $path -relief sunken + } else { + set _grab(oldrelief) [Widget::getoption $path -arrowrelief] + configure $path -arrowrelief sunken + } + if {[llength [set cmd [Widget::getoption $path -armcommand]]]} { + uplevel \#0 $cmd + if { [set delay [Widget::getoption $path -repeatdelay]] > 0 || + [set delay [Widget::getoption $path -repeatinterval]] > 0 } { + after $delay [list ArrowButton::_repeat $path] + } + } + } +} + + +# ------------------------------------------------------------------------------ +# Command ArrowButton::_release +# ------------------------------------------------------------------------------ +proc ArrowButton::_release { path } { + variable _grab + set path [winfo parent $path] + if { $_grab(pressed) == $path } { + set _grab(pressed) "" + if { [string equal [Widget::getoption $path -type] "button"] } { + configure $path -relief $_grab(oldrelief) + } else { + configure $path -arrowrelief $_grab(oldrelief) + } + if {[llength [set cmd [Widget::getoption $path -disarmcommand]]]} { + uplevel \#0 $cmd + } + if { $_grab(current) == $path && + ![string equal [Widget::getoption $path -state] "disabled"] && + [llength [set cmd [Widget::getoption $path -command]]]} { + uplevel \#0 $cmd + } + } +} + + +# ------------------------------------------------------------------------------ +# Command ArrowButton::_repeat +# ------------------------------------------------------------------------------ +proc ArrowButton::_repeat { path } { + variable _grab + if { $_grab(current) == $path && $_grab(pressed) == $path && + ![string equal [Widget::getoption $path -state] "disabled"] && + [llength [set cmd [Widget::getoption $path -armcommand]]]} { + uplevel \#0 $cmd + } + if { $_grab(pressed) == $path && + ([set delay [Widget::getoption $path -repeatinterval]] > 0 || + [set delay [Widget::getoption $path -repeatdelay]] > 0) } { + after $delay [list ArrowButton::_repeat $path] + } +} + + +# ------------------------------------------------------------------------------ +# Command ArrowButton::_destroy +# ------------------------------------------------------------------------------ +proc ArrowButton::_destroy { path } { + variable _moved + Widget::destroy $path + unset _moved($path) +} diff --git a/modules/tclsci/tcl/BWidget/bitmap.tcl b/modules/tclsci/tcl/BWidget/bitmap.tcl new file mode 100755 index 000000000..3e157d520 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/bitmap.tcl @@ -0,0 +1,94 @@ +# ------------------------------------------------------------------------------ +# bitmap.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: bitmap.tcl,v 1.4 2003/10/20 21:23:52 damonc Exp $ +# ------------------------------------------------------------------------------ +# Index of commands: +# - Bitmap::get +# - Bitmap::_init +# ---------------------------------------------------------------------------- +namespace eval Bitmap { + Widget::define Bitmap bitmap -classonly + + variable path + variable _bmp + variable _types { + photo .gif + photo .ppm + bitmap .xbm + photo .xpm + } + + proc use {} {} +} + + +# ---------------------------------------------------------------------------- +# Command Bitmap::get +# ---------------------------------------------------------------------------- +proc Bitmap::get { name } { + variable path + variable _bmp + variable _types + + if {[info exists _bmp($name)]} { + return $_bmp($name) + } + + # --- Nom de fichier avec extension --------------------------------- + set ext [file extension $name] + if { $ext != "" } { + if { ![info exists _bmp($ext)] } { + error "$ext not supported" + } + + if { [file exists $name] } { + if {[string equal $ext ".xpm"]} { + set _bmp($name) [xpm-to-image $name] + return $_bmp($name) + } + if {![catch {set _bmp($name) [image create $_bmp($ext) -file $name]}]} { + return $_bmp($name) + } + } + } + + foreach dir $path { + foreach {type ext} $_types { + if { [file exists [file join $dir $name$ext]] } { + if {[string equal $ext ".xpm"]} { + set _bmp($name) [xpm-to-image [file join $dir $name$ext]] + return $_bmp($name) + } else { + if {![catch {set _bmp($name) [image create $type -file [file join $dir $name$ext]]}]} { + return $_bmp($name) + } + } + } + } + } + + return -code error "$name not found" +} + + +# ---------------------------------------------------------------------------- +# Command Bitmap::_init +# ---------------------------------------------------------------------------- +proc Bitmap::_init { } { + global env + variable path + variable _bmp + variable _types + + set path [list "." [file join $::BWIDGET::LIBRARY images]] + set supp [image types] + foreach {type ext} $_types { + if { [lsearch $supp $type] != -1} { + set _bmp($ext) $type + } + } +} + + +Bitmap::_init diff --git a/modules/tclsci/tcl/BWidget/button.tcl b/modules/tclsci/tcl/BWidget/button.tcl new file mode 100755 index 000000000..5b8fc23c5 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/button.tcl @@ -0,0 +1,393 @@ +# ---------------------------------------------------------------------------- +# button.tcl +# This file is part of Unifix BWidget Toolkit +# ---------------------------------------------------------------------------- +# Index of commands: +# Public commands +# - Button::create +# - Button::configure +# - Button::cget +# - Button::invoke +# Private commands (event bindings) +# - Button::_destroy +# - Button::_enter +# - Button::_leave +# - Button::_press +# - Button::_release +# - Button::_repeat +# ---------------------------------------------------------------------------- + +namespace eval Button { + Widget::define Button button DynamicHelp + + set remove [list -command -relief -text -textvariable -underline -state] + if {[info tclversion] > 8.3} { + lappend remove -repeatdelay -repeatinterval + } + Widget::tkinclude Button button :cmd remove $remove + + Widget::declare Button { + {-name String "" 0} + {-text String "" 0} + {-textvariable String "" 0} + {-underline Int -1 0 "%d >= -1"} + {-armcommand String "" 0} + {-disarmcommand String "" 0} + {-command String "" 0} + {-state TkResource "" 0 button} + {-repeatdelay Int 0 0 "%d >= 0"} + {-repeatinterval Int 0 0 "%d >= 0"} + {-relief Enum raised 0 {raised sunken flat ridge solid groove link}} + } + + DynamicHelp::include Button balloon + + Widget::syncoptions Button "" :cmd {-text {} -underline {}} + + variable _current "" + variable _pressed "" + + bind BwButton <Enter> {Button::_enter %W} + bind BwButton <Leave> {Button::_leave %W} + bind BwButton <ButtonPress-1> {Button::_press %W} + bind BwButton <ButtonRelease-1> {Button::_release %W} + bind BwButton <Key-space> {Button::invoke %W; break} + bind BwButton <Return> {Button::invoke %W; break} + bind BwButton <<Invoke>> {Button::invoke %W; break} + bind BwButton <Destroy> {Widget::destroy %W} +} + + +# ---------------------------------------------------------------------------- +# Command Button::create +# ---------------------------------------------------------------------------- +proc Button::create { path args } { + array set maps [list Button {} :cmd {}] + array set maps [Widget::parseArgs Button $args] + if {$::Widget::_theme} { + eval [concat [list ttk::button $path] $maps(:cmd)] + } else { + eval [concat [list button $path] $maps(:cmd)] + } + Widget::initFromODB Button $path $maps(Button) + + # Do some extra configuration on the button + set var [Widget::getMegawidgetOption $path -textvariable] + set st [Widget::getMegawidgetOption $path -state] + if { ![string length $var] } { + set desc [BWidget::getname [Widget::getMegawidgetOption $path -name]] + if { [llength $desc] } { + set text [lindex $desc 0] + set under [lindex $desc 1] + Widget::configure $path [list -text $text] + Widget::configure $path [list -underline $under] + } else { + set text [Widget::getMegawidgetOption $path -text] + set under [Widget::getMegawidgetOption $path -underline] + } + } else { + set under -1 + set text "" + Widget::configure $path [list -underline $under] + } + + $path configure -text $text -underline $under \ + -textvariable $var -state $st + # Map relief flat on Toolbutton for ttk + set relief [Widget::getMegawidgetOption $path -relief] + if {$::Widget::_theme} { + if { [string equal $relief "link"] } { + $path configure -style Toolbutton + } + } else { + if { [string equal $relief "link"] } { + set relief "flat" + } + $path configure -relief $relief + } + bindtags $path [list $path BwButton [winfo toplevel $path] all] + + set accel1 [string tolower [string index $text $under]] + set accel2 [string toupper $accel1] + if { $accel1 != "" } { + bind [winfo toplevel $path] <Alt-$accel1> [list Button::invoke $path] + bind [winfo toplevel $path] <Alt-$accel2> [list Button::invoke $path] + } + + DynamicHelp::sethelp $path $path 1 + + return [Widget::create Button $path] +} + + +# ---------------------------------------------------------------------------- +# Command Button::configure +# ---------------------------------------------------------------------------- +proc Button::configure { path args } { + set oldunder [$path:cmd cget -underline] + if { $oldunder != -1 } { + set oldaccel1 [string tolower [string index [$path:cmd cget -text] $oldunder]] + set oldaccel2 [string toupper $oldaccel1] + } else { + set oldaccel1 "" + set oldaccel2 "" + } + set res [Widget::configure $path $args] + + # Extract all the modified bits we're interested in + foreach {cr cs cv cn ct cu} [Widget::hasChangedX $path \ + -relief -state -textvariable -name -text -underline] break + if { $cr || $cs } { + set relief [Widget::cget $path -relief] + set state [Widget::cget $path -state] + if { $::Widget::_theme} { + if { [string equal $relief "link"] } { + $path:cmd configure -style Toolbutton + } else { + $path:cmd configure -style "" + } + } else { + if { [string equal $relief "link"] } { + if { [string equal $state "active"] } { + set relief "raised" + } else { + set relief "flat" + } + } + $path:cmd configure -relief $relief + } + $path:cmd configure -state $state + } + + if { $cv || $cn || $ct || $cu } { + set var [Widget::cget $path -textvariable] + set text [Widget::cget $path -text] + set under [Widget::cget $path -underline] + if { ![string length $var] } { + set desc [BWidget::getname [Widget::cget $path -name]] + if { [llength $desc] } { + set text [lindex $desc 0] + set under [lindex $desc 1] + } + } else { + set under -1 + set text "" + } + set top [winfo toplevel $path] + if { $oldaccel1 != "" } { + bind $top <Alt-$oldaccel1> {} + bind $top <Alt-$oldaccel2> {} + } + set accel1 [string tolower [string index $text $under]] + set accel2 [string toupper $accel1] + if { $accel1 != "" } { + bind $top <Alt-$accel1> [list Button::invoke $path] + bind $top <Alt-$accel2> [list Button::invoke $path] + } + $path:cmd configure -text $text -underline $under -textvariable $var + } + DynamicHelp::sethelp $path $path + + set res +} + + +# ---------------------------------------------------------------------------- +# Command Button::cget +# ---------------------------------------------------------------------------- +proc Button::cget { path option } { + Widget::cget $path $option +} + + +# ---------------------------------------------------------------------------- +# Command Button::identify +# ---------------------------------------------------------------------------- +proc Button::identify { path args } { + eval $path:cmd identify $args +} + + +# ---------------------------------------------------------------------------- +# Command Button::instate +# ---------------------------------------------------------------------------- +proc Button::instate { path args } { + eval $path:cmd instate $args +} + + +# ---------------------------------------------------------------------------- +# Command Button::state +# ---------------------------------------------------------------------------- +proc Button::state { path args } { + eval $path:cmd state $args +} + + +# ---------------------------------------------------------------------------- +# Command Button::invoke +# ---------------------------------------------------------------------------- +proc Button::invoke { path } { + if { ![string equal [$path:cmd cget -state] "disabled"] } { + if { $::Widget::_theme} { + $path:cmd configure -state active + $path:cmd state pressed + } else { + $path:cmd configure -state active -relief sunken + } + update idletasks + set cmd [Widget::getMegawidgetOption $path -armcommand] + if { $cmd != "" } { + uplevel \#0 $cmd + } + after 100 + $path:cmd configure -state [Widget::getMegawidgetOption $path -state] + if { $::Widget::_theme} { + $path:cmd state !pressed + } else { + set relief [Widget::getMegawidgetOption $path -relief] + if { [string equal $relief "link"] } { + set relief flat + } + $path:cmd configure -relief $relief + } + set cmd [Widget::getMegawidgetOption $path -disarmcommand] + if { $cmd != "" } { + uplevel \#0 $cmd + } + set cmd [Widget::getMegawidgetOption $path -command] + if { $cmd != "" } { + uplevel \#0 $cmd + } + } +} + +# ---------------------------------------------------------------------------- +# Command Button::_enter +# ---------------------------------------------------------------------------- +proc Button::_enter { path } { + variable _current + variable _pressed + + set _current $path + if { ![string equal [$path:cmd cget -state] "disabled"] } { + $path:cmd configure -state active + if { $::Widget::_theme } { + # $path:cmd state active + } else { + if { $_pressed == $path } { + $path:cmd configure -relief sunken + } elseif { [string equal [Widget::cget $path -relief] "link"] } { + $path:cmd configure -relief raised + } + } + } +} + + +# ---------------------------------------------------------------------------- +# Command Button::_leave +# ---------------------------------------------------------------------------- +proc Button::_leave { path } { + variable _current + variable _pressed + + set _current "" + if { ![string equal [$path:cmd cget -state] "disabled"] } { + $path:cmd configure -state [Widget::cget $path -state] + if { $::Widget::_theme } { + } else { + set relief [Widget::cget $path -relief] + if { $_pressed == $path } { + if { [string equal $relief "link"] } { + set relief raised + } + $path:cmd configure -relief $relief + } elseif { [string equal $relief "link"] } { + $path:cmd configure -relief flat + } + } + } +} + + +# ---------------------------------------------------------------------------- +# Command Button::_press +# ---------------------------------------------------------------------------- +proc Button::_press { path } { + variable _pressed + + if { ![string equal [$path:cmd cget -state] "disabled"] } { + set _pressed $path + if { $::Widget::_theme} { + ttk::clickToFocus $path + $path state pressed + } else { + $path:cmd configure -relief sunken + } + set cmd [Widget::getMegawidgetOption $path -armcommand] + if { $cmd != "" } { + uplevel \#0 $cmd + set repeatdelay [Widget::getMegawidgetOption $path -repeatdelay] + set repeatint [Widget::getMegawidgetOption $path -repeatinterval] + if { $repeatdelay > 0 } { + after $repeatdelay "Button::_repeat $path" + } elseif { $repeatint > 0 } { + after $repeatint "Button::_repeat $path" + } + } + } +} + + +# ---------------------------------------------------------------------------- +# Command Button::_release +# ---------------------------------------------------------------------------- +proc Button::_release { path } { + variable _current + variable _pressed + + if { $_pressed == $path } { + set _pressed "" + after cancel "Button::_repeat $path" + if { $::Widget::_theme} { + $path state !pressed + } else { + set relief [Widget::getMegawidgetOption $path -relief] + if { [string equal $relief "link"] } { + set relief raised + } + $path:cmd configure -relief $relief + } + set cmd [Widget::getMegawidgetOption $path -disarmcommand] + if { $cmd != "" } { + uplevel \#0 $cmd + } + if { $_current == $path && + ![string equal [$path:cmd cget -state] "disabled"] && \ + [set cmd [Widget::getMegawidgetOption $path -command]] != "" } { + uplevel \#0 $cmd + } + } +} + + +# ---------------------------------------------------------------------------- +# Command Button::_repeat +# ---------------------------------------------------------------------------- +proc Button::_repeat { path } { + variable _current + variable _pressed + + if { $_current == $path && $_pressed == $path && + ![string equal [$path:cmd cget -state] "disabled"] && + [set cmd [Widget::getMegawidgetOption $path -armcommand]] != "" } { + uplevel \#0 $cmd + } + if { $_pressed == $path && + ([set delay [Widget::getMegawidgetOption $path -repeatinterval]] >0 || + [set delay [Widget::getMegawidgetOption $path -repeatdelay]] > 0) } { + after $delay "Button::_repeat $path" + } +} + diff --git a/modules/tclsci/tcl/BWidget/buttonbox.tcl b/modules/tclsci/tcl/BWidget/buttonbox.tcl new file mode 100755 index 000000000..9fefc2a37 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/buttonbox.tcl @@ -0,0 +1,419 @@ +# ---------------------------------------------------------------------------- +# buttonbox.tcl +# This file is part of Unifix BWidget Toolkit +# ---------------------------------------------------------------------------- +# Index of commands: +# - ButtonBox::create +# - ButtonBox::configure +# - ButtonBox::cget +# - ButtonBox::add +# - ButtonBox::itemconfigure +# - ButtonBox::itemcget +# - ButtonBox::setfocus +# - ButtonBox::invoke +# - ButtonBox::index +# - ButtonBox::_destroy +# ---------------------------------------------------------------------------- + +namespace eval ButtonBox { + Widget::define ButtonBox buttonbox Button + + Widget::declare ButtonBox { + {-background TkResource "" 0 frame} + {-orient Enum horizontal 1 {horizontal vertical}} + {-state Enum "normal" 0 {normal disabled}} + {-homogeneous Boolean 1 1} + {-spacing Int 10 0 "%d >= 0"} + {-padx TkResource "" 0 button} + {-pady TkResource "" 0 button} + {-default Int -1 0 "%d >= -1"} + {-bg Synonym -background} + } + + Widget::addmap ButtonBox "" :cmd {-background {}} + + bind ButtonBox <Destroy> [list ButtonBox::_destroy %W] +} + + +# ---------------------------------------------------------------------------- +# Command ButtonBox::create +# ---------------------------------------------------------------------------- +proc ButtonBox::create { path args } { + Widget::init ButtonBox $path $args + + variable $path + upvar 0 $path data + + eval [list frame $path] [Widget::subcget $path :cmd] \ + [list -class ButtonBox -takefocus 0 -highlightthickness 0] + # For 8.4+ we don't want to inherit the padding + catch {$path configure -padx 0 -pady 0} + + set data(max) 0 + set data(nbuttons) 0 + set data(buttons) [list] + set data(default) [Widget::getoption $path -default] + + return [Widget::create ButtonBox $path] +} + + +# ---------------------------------------------------------------------------- +# Command ButtonBox::configure +# ---------------------------------------------------------------------------- +proc ButtonBox::configure { path args } { + variable $path + upvar 0 $path data + + set res [Widget::configure $path $args] + + if { [Widget::hasChanged $path -default val] } { + if { $data(default) != -1 && $val != -1 } { + set but $path.b$data(default) + if { [winfo exists $but] } { + $but configure -default normal + } + set but $path.b$val + if { [winfo exists $but] } { + $but configure -default active + } + set data(default) $val + } else { + Widget::setoption $path -default $data(default) + } + } + + if {[Widget::hasChanged $path -state val]} { + foreach i $data(buttons) { + $path.b$i configure -state $val + } + } + + return $res +} + + +# ---------------------------------------------------------------------------- +# Command ButtonBox::cget +# ---------------------------------------------------------------------------- +proc ButtonBox::cget { path option } { + return [Widget::cget $path $option] +} + + +# ---------------------------------------------------------------------------- +# Command ButtonBox::add +# ---------------------------------------------------------------------------- +proc ButtonBox::add { path args } { + return [eval [linsert $args 0 insert $path end]] +} + + +proc ButtonBox::insert { path idx args } { + variable $path + upvar 0 $path data + + set but $path.b$data(nbuttons) + set spacing [Widget::getoption $path -spacing] + + ## Save the current spacing setting for this button. Buttons + ## appended to the end of the box have their spacing applied + ## to their left while all other have their spacing applied + ## to their right. + if {$idx == "end"} { + set data(spacing,$data(nbuttons)) [list left $spacing] + lappend data(buttons) $data(nbuttons) + } else { + set data(spacing,$data(nbuttons)) [list right $spacing] + set data(buttons) [linsert $data(buttons) $idx $data(nbuttons)] + } + + if { $data(nbuttons) == $data(default) } { + set style active + } elseif { $data(default) == -1 } { + set style disabled + } else { + set style normal + } + + array set flags $args + set tags "" + if { [info exists flags(-tags)] } { + set tags $flags(-tags) + unset flags(-tags) + set args [array get flags] + } + + if { $::Widget::_theme} { + eval [list Button::create $but] \ + $args [list -default $style] + } else { + eval [list Button::create $but \ + -background [Widget::getoption $path -background]\ + -padx [Widget::getoption $path -padx] \ + -pady [Widget::getoption $path -pady]] \ + $args [list -default $style] + } + + # ericm@scriptics.com: set up tags, just like the menu items + foreach tag $tags { + lappend data(tags,$tag) $but + if { ![info exists data(tagstate,$tag)] } { + set data(tagstate,$tag) 0 + } + } + set data(buttontags,$but) $tags + # ericm@scriptics.com + + _redraw $path + + incr data(nbuttons) + + return $but +} + + +proc ButtonBox::delete { path idx } { + variable $path + upvar 0 $path data + + set i [lindex $data(buttons) $idx] + set data(buttons) [lreplace $data(buttons) $idx $idx] + destroy $path.b$i +} + + +# ButtonBox::setbuttonstate -- +# +# Set the state of a given button tag. If this makes any buttons +# enable-able (ie, all of their tags are TRUE), enable them. +# +# Arguments: +# path the button box widget name +# tag the tag to modify +# state the new state of $tag (0 or 1) +# +# Results: +# None. + +proc ButtonBox::setbuttonstate {path tag state} { + variable $path + upvar 0 $path data + # First see if this is a real tag + if { [info exists data(tagstate,$tag)] } { + set data(tagstate,$tag) $state + foreach but $data(tags,$tag) { + set expression "1" + foreach buttontag $data(buttontags,$but) { + append expression " && $data(tagstate,$buttontag)" + } + if { [expr $expression] } { + set state normal + } else { + set state disabled + } + $but configure -state $state + } + } + return +} + +# ButtonBox::getbuttonstate -- +# +# Retrieve the state of a given button tag. +# +# Arguments: +# path the button box widget name +# tag the tag to modify +# +# Results: +# None. + +proc ButtonBox::getbuttonstate {path tag} { + variable $path + upvar 0 $path data + # First see if this is a real tag + if { [info exists data(tagstate,$tag)] } { + return $data(tagstate,$tag) + } else { + error "unknown tag $tag" + } +} + +# ---------------------------------------------------------------------------- +# Command ButtonBox::itemconfigure +# ---------------------------------------------------------------------------- +proc ButtonBox::itemconfigure { path index args } { + if { [set idx [lsearch $args -default]] != -1 } { + set args [lreplace $args $idx [expr {$idx+1}]] + } + return [eval [list Button::configure $path.b[index $path $index]] $args] +} + + +# ---------------------------------------------------------------------------- +# Command ButtonBox::itemcget +# ---------------------------------------------------------------------------- +proc ButtonBox::itemcget { path index option } { + return [Button::cget $path.b[index $path $index] $option] +} + + +# ---------------------------------------------------------------------------- +# Command ButtonBox::setfocus +# ---------------------------------------------------------------------------- +proc ButtonBox::setfocus { path index } { + set but $path.b[index $path $index] + if { [winfo exists $but] } { + focus $but + } +} + + +# ---------------------------------------------------------------------------- +# Command ButtonBox::invoke +# ---------------------------------------------------------------------------- +proc ButtonBox::invoke { path index } { + set but $path.b[index $path $index] + if { [winfo exists $but] } { + Button::invoke $but + } +} + + +# ---------------------------------------------------------------------------- +# Command ButtonBox::index +# ---------------------------------------------------------------------------- +proc ButtonBox::index { path index } { + variable $path + upvar 0 $path data + + set n [expr {$data(nbuttons) - 1}] + + if {[string equal $index "default"]} { + set res [Widget::getoption $path -default] + } elseif {$index == "end" || $index == "last"} { + set res $n + } elseif {![string is integer -strict $index]} { + ## It's not an integer. Search the text of each button + ## in the box and return the index that matches. + foreach i $data(buttons) { + set w $path.b$i + lappend text [$w cget -text] + lappend names [$w cget -name] + } + set res [lsearch -exact [concat $names $text] $index] + } else { + set res $index + if {$index > $n} { set res $n } + } + return $res +} + + +# ButtonBox::gettags -- +# +# Return a list of all the tags on all the buttons in a buttonbox. +# +# Arguments: +# path the buttonbox to query. +# +# Results: +# taglist a list of tags on the buttons in the buttonbox + +proc ButtonBox::gettags {path} { + upvar ::ButtonBox::$path data + set taglist {} + foreach tag [array names data "tags,*"] { + lappend taglist [string range $tag 5 end] + } + return $taglist +} + + +# ---------------------------------------------------------------------------- +# Command ButtonBox::_redraw +# ---------------------------------------------------------------------------- +proc ButtonBox::_redraw { path } { + variable $path + upvar 0 $path data + Widget::getVariable $path buttons + + # For tk >= 8.4, -uniform gridding option is used. + # Otherwise, there is the constraint, that button size may not change after + # creation. + set uniformAvailable [expr {0 <= [package vcompare [info patchlevel] 8.4.0]}] + + ## We re-grid the buttons from left-to-right. As we go through + ## each button, we check its spacing and which direction the + ## spacing applies to. Once spacing has been applied to an index, + ## it is not changed. This means spacing takes precedence from + ## left-to-right. + + set idx 0 + set idxs [list] + foreach i $data(buttons) { + set dir [lindex $data(spacing,$i) 0] + set spacing [lindex $data(spacing,$i) 1] + set but $path.b$i + if {[string equal [Widget::getoption $path -orient] "horizontal"]} { + grid $but -column $idx -row 0 -sticky nsew + if { [Widget::getoption $path -homogeneous] } { + if {$uniformAvailable} { + grid columnconfigure $path $idx -uniform koen -weight 1 + } else { + set req [winfo reqwidth $but] + if { $req > $data(max) } { + grid columnconfigure $path [expr {2*$i}] -minsize $req + set data(max) $req + } + grid columnconfigure $path $idx -weight 1 + } + } else { + grid columnconfigure $path $idx -weight 0 + } + + set col [expr {$idx - 1}] + if {[string equal $dir "right"]} { set col [expr {$idx + 1}] } + if {$col > 0 && [lsearch $idxs $col] < 0} { + lappend idxs $col + grid columnconfigure $path $col -minsize $spacing + } + } else { + grid $but -column 0 -row $idx -sticky nsew + grid rowconfigure $path $idx -weight 0 + + set row [expr {$idx - 1}] + if {[string equal $dir "right"]} { set row [expr {$idx + 1}] } + if {$row > 0 && [lsearch $idxs $row] < 0} { + lappend idxs $row + grid rowconfigure $path $row -minsize $spacing + } + } + incr idx 2 + } + + if {!$uniformAvailable} { + # Now that the maximum size has been calculated, go back through + # and correctly set the size for homogeneous horizontal buttons. + if { [string equal [Widget::getoption $path -orient] "horizontal"] && [Widget::getoption $path -homogeneous] } { + set idx 0 + foreach i $data(buttons) { + grid columnconfigure $path $idx -minsize $data(max) + incr idx 2 + } + } + } +} + + +# ---------------------------------------------------------------------------- +# Command ButtonBox::_destroy +# ---------------------------------------------------------------------------- +proc ButtonBox::_destroy { path } { + variable $path + upvar 0 $path data + Widget::destroy $path + unset data +} diff --git a/modules/tclsci/tcl/BWidget/color.tcl b/modules/tclsci/tcl/BWidget/color.tcl new file mode 100755 index 000000000..dd545eddc --- /dev/null +++ b/modules/tclsci/tcl/BWidget/color.tcl @@ -0,0 +1,493 @@ +namespace eval SelectColor { + Widget::define SelectColor color Dialog + + Widget::declare SelectColor { + {-title String "Select a color" 0} + {-parent String "" 0} + {-color TkResource "" 0 {label -background}} + {-type Enum "dialog" 1 {dialog popup}} + {-placement String "center" 1} + } + + variable _baseColors { + \#0000ff \#00ff00 \#00ffff \#ff0000 \#ff00ff \#ffff00 + \#000099 \#009900 \#009999 \#990000 \#990099 \#999900 + \#000000 \#333333 \#666666 \#999999 \#cccccc \#ffffff + } + + variable _userColors { + \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff + \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff + } + + if {[string equal $::tcl_platform(platform) "unix"]} { + set useTkDialogue 0 + } else { + set useTkDialogue 1 + } + + variable _selectype + variable _selection + variable _wcolor + variable _image + variable _hsv +} + +proc SelectColor::create { path args } { + Widget::init SelectColor $path $args + + set type [Widget::cget $path -type] + + switch -- [Widget::cget $path -type] { + "dialog" { + return [eval [list SelectColor::dialog $path] $args] + } + + "popup" { + set list [list at center left right above below] + set placement [Widget::cget $path -placement] + set where [lindex $placement 0] + + if {[lsearch $list $where] < 0} { + return -code error \ + [BWidget::badOptionString placement $placement $list] + } + + ## If they specified a parent and didn't pass a second argument + ## in the placement, set the placement relative to the parent. + set parent [Widget::cget $path -parent] + if {[string length $parent]} { + if {[llength $placement] == 1} { lappend placement $parent } + } + return [eval [list SelectColor::menu $path $placement] $args] + } + } +} + +proc SelectColor::menu {path placement args} { + variable _baseColors + variable _userColors + variable _wcolor + variable _selectype + variable _selection + + Widget::init SelectColor $path $args + set top [toplevel $path] + set parent [winfo toplevel [winfo parent $top]] + wm withdraw $top + wm transient $top $parent + wm overrideredirect $top 1 + catch { wm attributes $top -topmost 1 } + + set frame [frame $top.frame \ + -highlightthickness 0 \ + -relief raised -borderwidth 2] + set col 0 + set row 0 + set count 0 + set colors [concat $_baseColors $_userColors] + foreach color $colors { + set f [frame $frame.c$count \ + -highlightthickness 2 \ + -highlightcolor white \ + -relief solid -borderwidth 1 \ + -width 16 -height 16 -background $color] + bind $f <1> "set SelectColor::_selection $count; break" + bind $f <Enter> {focus %W} + grid $f -column $col -row $row + incr count + if {[incr col] == 6 } { + set col 0 + incr row + } + } + set f [label $frame.c$count \ + -highlightthickness 2 \ + -highlightcolor white \ + -relief flat -borderwidth 0 \ + -width 16 -height 16 -image [Bitmap::get palette]] + grid $f -column $col -row $row + bind $f <1> "set SelectColor::_selection $count; break" + bind $f <Enter> {focus %W} + pack $frame + + bind $top <1> {set SelectColor::_selection -1} + bind $top <Escape> {set SelectColor::_selection -2} + bind $top <FocusOut> [subst {if {"%W" == "$top"} \ + {set SelectColor::_selection -2}}] + eval [list BWidget::place $top 0 0] $placement + + wm deiconify $top + raise $top + if {$::tcl_platform(platform) == "unix"} { + tkwait visibility $top + update + } + BWidget::SetFocusGrab $top $frame.c0 + + vwait SelectColor::_selection + BWidget::RestoreFocusGrab $top $frame.c0 destroy + Widget::destroy $top + if {$_selection == $count} { + array set opts { + -parent -parent + -title -title + -color -initialcolor + } + if {[Widget::theme]} { + set native 1 + set nativecmd [list tk_chooseColor -parent $parent] + foreach {key val} $args { + if {![info exists opts($key)]} { + set native 0 + break + } + lappend nativecmd $opts($key) $val + } + if {$native} { + return [eval $nativecmd] + } + } + return [eval [list dialog $path] $args] + } else { + return [lindex $colors $_selection] + } +} + + +proc SelectColor::dialog {path args} { + variable _baseColors + variable _userColors + variable _widget + variable _selection + variable _image + variable _hsv + + Widget::init SelectColor $path:SelectColor $args + set top [Dialog::create $path \ + -title [Widget::cget $path:SelectColor -title] \ + -parent [Widget::cget $path:SelectColor -parent] \ + -separator 1 -default 0 -cancel 1 -anchor e] + wm resizable $top 0 0 + set dlgf [$top getframe] + set fg [frame $dlgf.fg] + set desc [list \ + base _baseColors "Base colors" \ + user _userColors "User colors"] + set count 0 + foreach {type varcol defTitle} $desc { + set col 0 + set lin 0 + set title [lindex [BWidget::getname "${type}Colors"] 0] + if {![string length $title]} { + set title $defTitle + } + set titf [TitleFrame $fg.$type -text $title] + set subf [$titf getframe] + foreach color [set $varcol] { + set fround [frame $fg.round$count \ + -highlightthickness 1 \ + -relief sunken -borderwidth 2] + set fcolor [frame $fg.color$count -width 16 -height 12 \ + -highlightthickness 0 \ + -relief flat -borderwidth 0 \ + -background $color] + pack $fcolor -in $fround + grid $fround -in $subf -row $lin -column $col -padx 1 -pady 1 + + bind $fround <ButtonPress-1> [list SelectColor::_select_rgb $count] + bind $fcolor <ButtonPress-1> [list SelectColor::_select_rgb $count] + + bind $fround <Double-1> \ + "SelectColor::_select_rgb [list $count]; [list $top] invoke 0" + bind $fcolor <Double-1> \ + "SelectColor::_select_rgb [list $count]; [list $top] invoke 0" + + incr count + if {[incr col] == 6} { + incr lin + set col 0 + } + } + pack $titf -anchor w -pady 2 + } + set fround [frame $fg.round \ + -highlightthickness 0 \ + -relief sunken -borderwidth 2] + set fcolor [frame $fg.color \ + -width 50 \ + -highlightthickness 0 \ + -relief flat -borderwidth 0] + pack $fcolor -in $fround -fill y -expand yes + pack $fround -anchor e -pady 2 -fill y -expand yes + + set fd [frame $dlgf.fd] + set f1 [frame $fd.f1 -relief sunken -borderwidth 2] + set f2 [frame $fd.f2 -relief sunken -borderwidth 2] + set c1 [canvas $f1.c -width 200 -height 200 -bd 0 -highlightthickness 0] + set c2 [canvas $f2.c -width 15 -height 200 -bd 0 -highlightthickness 0] + + for {set val 0} {$val < 40} {incr val} { + $c2 create rectangle 0 [expr {5*$val}] 15 [expr {5*$val+5}] -tags val[expr {39-$val}] + } + $c2 create polygon 0 0 10 5 0 10 -fill black -outline white -tags target + + pack $c1 $c2 + pack $f1 $f2 -side left -padx 10 -anchor n + + pack $fg $fd -side left -anchor n -fill y + + bind $c1 <ButtonPress-1> [list SelectColor::_select_hue_sat %x %y] + bind $c1 <B1-Motion> [list SelectColor::_select_hue_sat %x %y] + + bind $c2 <ButtonPress-1> [list SelectColor::_select_value %x %y] + bind $c2 <B1-Motion> [list SelectColor::_select_value %x %y] + + if {![info exists _image] || [catch {image type $_image}]} { + set _image [image create photo -width 200 -height 200] + for {set x 0} {$x < 200} {incr x 4} { + for {set y 0} {$y < 200} {incr y 4} { + $_image put \ + [eval [list format "\#%04x%04x%04x"] \ + [hsvToRgb [expr {$x/196.0}] [expr {(196-$y)/196.0}] 0.85]] \ + -to $x $y [expr {$x+4}] [expr {$y+4}] + } + } + } + $c1 create image 0 0 -anchor nw -image $_image + $c1 create bitmap 0 0 \ + -bitmap @[file join $::BWIDGET::LIBRARY "images" "target.xbm"] \ + -anchor nw -tags target + + set _selection -1 + set _widget(fcolor) $fg + set _widget(chs) $c1 + set _widget(cv) $c2 + set rgb [winfo rgb $path [Widget::cget $path:SelectColor -color]] + set _hsv [eval rgbToHsv $rgb] + _set_rgb [eval [list format "\#%04x%04x%04x"] $rgb] + _set_hue_sat [lindex $_hsv 0] [lindex $_hsv 1] + _set_value [lindex $_hsv 2] + + $top add -name ok + $top add -name cancel + set res [$top draw] + if {$res == 0} { + set color [$fg.color cget -background] + } else { + set color "" + } + destroy $top + return $color +} + +proc SelectColor::setcolor { idx color } { + variable _userColors + set _userColors [lreplace $_userColors $idx $idx $color] +} + +proc SelectColor::_select_rgb {count} { + variable _baseColors + variable _userColors + variable _selection + variable _widget + variable _hsv + + set frame $_widget(fcolor) + if {$_selection >= 0} { + $frame.round$_selection configure \ + -relief sunken -highlightthickness 1 -borderwidth 2 + } + $frame.round$count configure \ + -relief flat -highlightthickness 2 -borderwidth 1 + focus $frame.round$count + set _selection $count + set bg [$frame.color$count cget -background] + set user [expr {$_selection-[llength $_baseColors]}] + if {$user >= 0 && + [string equal \ + [winfo rgb $frame.color$_selection $bg] \ + [winfo rgb $frame.color$_selection white]]} { + set bg [$frame.color cget -bg] + $frame.color$_selection configure -background $bg + set _userColors [lreplace $_userColors $user $user $bg] + } else { + set _hsv [eval rgbToHsv [winfo rgb $frame.color$count $bg]] + _set_hue_sat [lindex $_hsv 0] [lindex $_hsv 1] + _set_value [lindex $_hsv 2] + $frame.color configure -background $bg + } +} + + +proc SelectColor::_set_rgb {rgb} { + variable _selection + variable _baseColors + variable _userColors + variable _widget + + set frame $_widget(fcolor) + $frame.color configure -background $rgb + set user [expr {$_selection-[llength $_baseColors]}] + if {$user >= 0} { + $frame.color$_selection configure -background $rgb + set _userColors [lreplace $_userColors $user $user $rgb] + } +} + + +proc SelectColor::_select_hue_sat {x y} { + variable _widget + variable _hsv + + if {$x < 0} { + set x 0 + } elseif {$x > 200} { + set x 200 + } + if {$y < 0 } { + set y 0 + } elseif {$y > 200} { + set y 200 + } + set hue [expr {$x/200.0}] + set sat [expr {(200-$y)/200.0}] + set _hsv [lreplace $_hsv 0 1 $hue $sat] + $_widget(chs) coords target [expr {$x-9}] [expr {$y-9}] + _draw_values $hue $sat + _set_rgb [eval [list format "\#%04x%04x%04x"] [eval [list hsvToRgb] $_hsv]] +} + + +proc SelectColor::_set_hue_sat {hue sat} { + variable _widget + + set x [expr {$hue*200-9}] + set y [expr {(1-$sat)*200-9}] + $_widget(chs) coords target $x $y + _draw_values $hue $sat +} + + + +proc SelectColor::_select_value {x y} { + variable _widget + variable _hsv + + if {$y < 0} { + set y 0 + } elseif {$y > 200} { + set y 200 + } + $_widget(cv) coords target 0 [expr {$y-5}] 10 $y 0 [expr {$y+5}] + set _hsv [lreplace $_hsv 2 2 [expr {(200-$y)/200.0}]] + _set_rgb [eval [list format "\#%04x%04x%04x"] [eval [list hsvToRgb] $_hsv]] +} + + +proc SelectColor::_draw_values {hue sat} { + variable _widget + + for {set val 0} {$val < 40} {incr val} { + set l [hsvToRgb $hue $sat [expr {$val/39.0}]] + set col [eval [list format "\#%04x%04x%04x"] $l] + $_widget(cv) itemconfigure val$val -fill $col -outline $col + } +} + + +proc SelectColor::_set_value {value} { + variable _widget + + set y [expr {int((1-$value)*200)}] + $_widget(cv) coords target 0 [expr {$y-5}] 10 $y 0 [expr {$y+5}] +} + + +# -- +# Taken from tk8.0/demos/tcolor.tcl +# -- +# The procedure below converts an HSB value to RGB. It takes hue, saturation, +# and value components (floating-point, 0-1.0) as arguments, and returns a +# list containing RGB components (integers, 0-65535) as result. The code +# here is a copy of the code on page 616 of "Fundamentals of Interactive +# Computer Graphics" by Foley and Van Dam. + +proc SelectColor::hsvToRgb {hue sat val} { + set v [expr {round(65535.0*$val)}] + if {$sat == 0} { + return [list $v $v $v] + } else { + set hue [expr {$hue*6.0}] + if {$hue >= 6.0} { + set hue 0.0 + } + set i [expr {int($hue)}] + set f [expr {$hue-$i}] + set p [expr {round(65535.0*$val*(1 - $sat))}] + set q [expr {round(65535.0*$val*(1 - ($sat*$f)))}] + set t [expr {round(65535.0*$val*(1 - ($sat*(1 - $f))))}] + switch $i { + 0 {return [list $v $t $p]} + 1 {return [list $q $v $p]} + 2 {return [list $p $v $t]} + 3 {return [list $p $q $v]} + 4 {return [list $t $p $v]} + 5 {return [list $v $p $q]} + } + } +} + + +# -- +# Taken from tk8.0/demos/tcolor.tcl +# -- +# The procedure below converts an RGB value to HSB. It takes red, green, +# and blue components (0-65535) as arguments, and returns a list containing +# HSB components (floating-point, 0-1) as result. The code here is a copy +# of the code on page 615 of "Fundamentals of Interactive Computer Graphics" +# by Foley and Van Dam. + +proc SelectColor::rgbToHsv {red green blue} { + if {$red > $green} { + set max $red.0 + set min $green.0 + } else { + set max $green.0 + set min $red.0 + } + if {$blue > $max} { + set max $blue.0 + } else { + if {$blue < $min} { + set min $blue.0 + } + } + set range [expr {$max-$min}] + if {$max == 0} { + set sat 0 + } else { + set sat [expr {($max-$min)/$max}] + } + if {$sat == 0} { + set hue 0 + } else { + set rc [expr {($max - $red)/$range}] + set gc [expr {($max - $green)/$range}] + set bc [expr {($max - $blue)/$range}] + if {$red == $max} { + set hue [expr {.166667*($bc - $gc)}] + } else { + if {$green == $max} { + set hue [expr {.166667*(2 + $rc - $bc)}] + } else { + set hue [expr {.166667*(4 + $gc - $rc)}] + } + } + if {$hue < 0.0} { + set hue [expr {$hue + 1.0}] + } + } + return [list $hue $sat [expr {$max/65535}]] +} + diff --git a/modules/tclsci/tcl/BWidget/combobox.tcl b/modules/tclsci/tcl/BWidget/combobox.tcl new file mode 100755 index 000000000..13389d32c --- /dev/null +++ b/modules/tclsci/tcl/BWidget/combobox.tcl @@ -0,0 +1,885 @@ +# ---------------------------------------------------------------------------- +# combobox.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: combobox.tcl,v 1.42.2.1 2009/08/10 11:28:50 oehhar Exp $ +# ---------------------------------------------------------------------------- +# Index of commands: +# - ComboBox::create +# - ComboBox::configure +# - ComboBox::cget +# - ComboBox::setvalue +# - ComboBox::getvalue +# - ComboBox::clearvalue +# - ComboBox::_create_popup +# - ComboBox::_mapliste +# - ComboBox::_unmapliste +# - ComboBox::_select +# - ComboBox::_modify_value +# ---------------------------------------------------------------------------- + +# ComboBox uses the 8.3 -listvariable listbox option +package require Tk 8.3 + +namespace eval ComboBox { + Widget::define ComboBox combobox ArrowButton Entry ListBox + + Widget::tkinclude ComboBox frame :cmd \ + include {-relief -borderwidth -bd -background} \ + initialize {-relief sunken -borderwidth 2} + + Widget::bwinclude ComboBox Entry .e \ + remove {-relief -bd -borderwidth -bg} \ + rename {-background -entrybg} + + Widget::declare ComboBox { + {-height TkResource 0 0 listbox} + {-values String "" 0} + {-images String "" 0} + {-indents String "" 0} + {-modifycmd String "" 0} + {-postcommand String "" 0} + {-expand Enum none 0 {none tab}} + {-autocomplete Boolean 0 0} + {-autopost Boolean 0 0} + {-bwlistbox Boolean 0 0} + {-listboxwidth Int 0 0} + {-hottrack Boolean 0 0} + } + + Widget::addmap ComboBox ArrowButton .a { + -background {} -foreground {} -disabledforeground {} -state {} + } + + Widget::syncoptions ComboBox Entry .e {-text {}} + + ::bind BwComboBox <FocusIn> [list after idle {BWidget::refocus %W %W.e}] + ::bind BwComboBox <Destroy> [list ComboBox::_destroy %W] + + ::bind ListBoxHotTrack <Motion> { + %W selection clear 0 end + %W activate @%x,%y + %W selection set @%x,%y + } + + variable _index +} + + +# ComboBox::create -- +# +# Create a combobox widget with the given options. +# +# Arguments: +# path name of the new widget. +# args optional arguments to the widget. +# +# Results: +# path name of the new widget. + +proc ComboBox::create { path args } { + array set maps [list ComboBox {} :cmd {} .e {} .a {}] + array set maps [Widget::parseArgs ComboBox $args] + + eval [list frame $path] $maps(:cmd) \ + [list -highlightthickness 0 -takefocus 0 -class ComboBox] + Widget::initFromODB ComboBox $path $maps(ComboBox) + + bindtags $path [list $path BwComboBox [winfo toplevel $path] all] + + set entry [eval [list Entry::create $path.e] $maps(.e) \ + [list -relief flat -borderwidth 0 -takefocus 1]] + + ::bind $path.e <FocusOut> [list $path _focus_out] + ::bind $path <<TraverseIn>> [list $path _traverse_in] + + if {[Widget::cget $path -autocomplete]} { + ::bind $path.e <KeyRelease> [list $path _auto_complete %K] + } + + if {[Widget::cget $path -autopost]} { + ::bind $path.e <KeyRelease> +[list $path _auto_post %K] + } else { + ::bind $entry <Key-Up> [list ComboBox::_unmapliste $path] + ::bind $entry <Key-Down> [list ComboBox::_mapliste $path] + } + + if {[string equal [tk windowingsystem] "x11"]} { + set ipadx 0 + set width 11 + } else { + set ipadx 2 + set width 15 + } + set height [winfo reqheight $entry] + set arrow [eval [list ArrowButton::create $path.a] $maps(.a) \ + [list -width $width -height $height \ + -highlightthickness 0 -borderwidth 1 -takefocus 0 \ + -dir bottom -type button -ipadx $ipadx \ + -command [list ComboBox::_mapliste $path] \ + ]] + + pack $arrow -side right -fill y + pack $entry -side left -fill both -expand yes + + set editable [Widget::cget $path -editable] + Entry::configure $path.e -editable $editable + if {$editable} { + ::bind $entry <ButtonPress-1> [list ComboBox::_unmapliste $path] + } else { + ::bind $entry <ButtonPress-1> [list ArrowButton::invoke $path.a] + if { ![string equal [Widget::cget $path -state] "disabled"] } { + Entry::configure $path.e -takefocus 1 + } + } + + ::bind $path <ButtonPress-1> [list ComboBox::_unmapliste $path] + ::bind $entry <Control-Up> [list ComboBox::_modify_value $path previous] + ::bind $entry <Control-Down> [list ComboBox::_modify_value $path next] + ::bind $entry <Control-Prior> [list ComboBox::_modify_value $path first] + ::bind $entry <Control-Next> [list ComboBox::_modify_value $path last] + + if {$editable} { + set expand [Widget::cget $path -expand] + if {[string equal "tab" $expand]} { + # Expand entry value on Tab (from -values) + ::bind $entry <Tab> "[list ComboBox::_expand $path]; break" + } elseif {[string equal "auto" $expand]} { + # Expand entry value anytime (from -values) + #::bind $entry <Key> "[list ComboBox::_expand $path]; break" + } + } + + ## If we have images, we have to use a BWidget ListBox. + set bw [Widget::cget $path -bwlistbox] + if {[llength [Widget::cget $path -images]]} { + Widget::configure $path [list -bwlistbox 1] + } else { + Widget::configure $path [list -bwlistbox $bw] + } + + set ComboBox::_index($path) -1 + + return [Widget::create ComboBox $path] +} + + +# ComboBox::configure -- +# +# Configure subcommand for ComboBox widgets. Works like regular +# widget configure command. +# +# Arguments: +# path Name of the ComboBox widget. +# args Additional optional arguments: +# ?-option? +# ?-option value ...? +# +# Results: +# Depends on arguments. If no arguments are given, returns a complete +# list of configuration information. If one argument is given, returns +# the configuration information for that option. If more than one +# argument is given, returns nothing. + +proc ComboBox::configure { path args } { + set res [Widget::configure $path $args] + set entry $path.e + + + set list [list -images -values -bwlistbox -hottrack -autocomplete -autopost] + foreach {ci cv cb ch cac cap} [eval [linsert $list 0 Widget::hasChangedX $path]] { break } + + if { $ci } { + set images [Widget::cget $path -images] + if {[llength $images]} { + Widget::configure $path [list -bwlistbox 1] + } else { + Widget::configure $path [list -bwlistbox 0] + } + } + + ## If autocomplete toggled, turn bindings on/off + if { $cac } { + if {[Widget::cget $path -autocomplete]} { + ::bind $entry <KeyRelease> +[list $path _auto_complete %K] + } else { + set bindings [split [::bind $entry <KeyRelease>] \n] + if {[set idx [lsearch $bindings [list $path _auto_complete %K]]] != -1} { + ::bind $entry <KeyRelease> [join [lreplace $bindings $idx $idx] \n] + } + } + } + + ## If autopost toggled, turn bindings on/off + if { $cap } { + if {[Widget::cget $path -autopost]} { + ::bind $entry <KeyRelease> +[list $path _auto_post %K] + set bindings [split [::bind $entry <Key-Up>] \n] + if {[set idx [lsearch $bindings [list ComboBox::_unmapliste $path]]] != -1} { + ::bind $entry <Key-Up> [join [lreplace $bindings $idx $idx] \n] + } + set bindings [split [::bind $entry <Key-Down>] \n] + if {[set idx [lsearch $bindings [list ComboBox::_mapliste $path]]] != -1} { + ::bind $entry <Key-Down> [join [lreplace $bindings $idx $idx] \n] + } + } else { + set bindings [split [::bind $entry <KeyRelease>] \n] + if {[set idx [lsearch $bindings [list $path _auto_post %K]]] != -1} { + ::bind $entry <KeyRelease> [join [lreplace $bindings $idx $idx] \n] + } + ::bind $entry <Key-Up> +[list ComboBox::_unmapliste $path] + ::bind $entry <Key-Down> +[list ComboBox::_mapliste $path] + } + } + + set bw [Widget::cget $path -bwlistbox] + + ## If the images, bwlistbox, hottrack or values have changed, + ## destroy the shell so that it will re-create itself the next + ## time around. + if { $ci || $cb || $ch || ($bw && $cv) } { + destroy $path.shell + } + + set chgedit [Widget::hasChangedX $path -editable] + if {$chgedit} { + if {[Widget::cget $path -editable]} { + ::bind $entry <ButtonPress-1> [list ComboBox::_unmapliste $path] + Entry::configure $entry -editable true + } else { + ::bind $entry <ButtonPress-1> [list ArrowButton::invoke $path.a] + Entry::configure $entry -editable false + + # Make sure that non-editable comboboxes can still be tabbed to. + + if { ![string equal [Widget::cget $path -state] "disabled"] } { + Entry::configure $entry -takefocus 1 + } + } + } + + if {$chgedit || [Widget::hasChangedX $path -expand]} { + # Unset what we may have created. + ::bind $entry <Tab> {} + if {[Widget::cget $path -editable]} { + set expand [Widget::cget $path -expand] + if {[string equal "tab" $expand]} { + # Expand entry value on Tab (from -values) + ::bind $entry <Tab> "[list ComboBox::_expand $path]; break" + } elseif {[string equal "auto" $expand]} { + # Expand entry value anytime (from -values) + #::bind $entry <Key> "[list ComboBox::_expand $path]; break" + } + } + } + + # if state changed to normal and -editable false, the edit must take focus + if { [Widget::hasChangedX $path -state] \ + && ![string equal [Widget::cget $path -state] "disabled"] \ + && ![Widget::cget $path -editable] } { + Entry::configure $entry -takefocus 1 + } + + # if the dropdown listbox is shown, simply force the actual entry + # colors into it. If it is not shown, the next time the dropdown + # is shown it'll get the actual colors anyway + if {[winfo exists $path.shell.listb]} { + $path.shell.listb configure \ + -bg [Widget::cget $path -entrybg] \ + -fg [Widget::cget $path -foreground] \ + -selectbackground [Widget::cget $path -selectbackground] \ + -selectforeground [Widget::cget $path -selectforeground] + } + + return $res +} + + +# ---------------------------------------------------------------------------- +# Command ComboBox::cget +# ---------------------------------------------------------------------------- +proc ComboBox::cget { path option } { + return [Widget::cget $path $option] +} + + +# ---------------------------------------------------------------------------- +# Command ComboBox::setvalue +# ---------------------------------------------------------------------------- +proc ComboBox::setvalue { path index } { + variable _index + + set values [Widget::getMegawidgetOption $path -values] + set value [Entry::cget $path.e -text] + switch -- $index { + next { + if { [set idx [lsearch -exact $values $value]] != -1 } { + incr idx + } else { + set idx [lsearch -exact $values "$value*"] + } + } + previous { + if { [set idx [lsearch -exact $values $value]] != -1 } { + incr idx -1 + } else { + set idx [lsearch -exact $values "$value*"] + } + } + first { + set idx 0 + } + last { + set idx [expr {[llength $values]-1}] + } + default { + if { [string index $index 0] == "@" } { + set idx [string range $index 1 end] + if { ![string is integer -strict $idx] } { + return -code error "bad index \"$index\"" + } + } else { + return -code error "bad index \"$index\"" + } + } + } + if { $idx >= 0 && $idx < [llength $values] } { + set newval [lindex $values $idx] + set _index($path) $idx + Entry::configure $path.e -text $newval + return 1 + } + return 0 +} + + +proc ComboBox::icursor { path idx } { + return [$path.e icursor $idx] +} + + +proc ComboBox::get { path } { + return [$path.e get] +} + + +# ---------------------------------------------------------------------------- +# Command ComboBox::getvalue +# ---------------------------------------------------------------------------- +proc ComboBox::getvalue { path } { + variable _index + set values [Widget::getMegawidgetOption $path -values] + set value [Entry::cget $path.e -text] + # Check if an index was saved by the last setvalue operation + # If this index still matches it is returned + # This is necessary for the case when values is not unique + if { $_index($path) >= 0 \ + && $_index($path) < [llength $values] \ + && $value eq [lindex $values $_index($path)]} { + return $_index($path) + } + + return [lsearch -exact $values $value] +} + + +proc ComboBox::getlistbox { path } { + _create_popup $path + return $path.shell.listb +} + + +# ---------------------------------------------------------------------------- +# Command ComboBox::post +# ---------------------------------------------------------------------------- +proc ComboBox::post { path } { + _mapliste $path + return +} + + +proc ComboBox::unpost { path } { + _unmapliste $path + return +} + + +# ---------------------------------------------------------------------------- +# Command ComboBox::bind +# ---------------------------------------------------------------------------- +proc ComboBox::bind { path args } { + return [eval [list ::bind $path.e] $args] +} + + +proc ComboBox::insert { path idx args } { + upvar #0 [Widget::varForOption $path -values] values + + if {[Widget::cget $path -bwlistbox]} { + set l [$path getlistbox] + set i [eval [linsert $args 0 $l insert $idx #auto]] + set text [$l itemcget $i -text] + if {$idx == "end"} { + lappend values $text + } else { + set values [linsert $values $idx $text] + } + } else { + set values [eval [list linsert $values $idx] $args] + } +} + +# ---------------------------------------------------------------------------- +# Command ComboBox::clearvalue +# ---------------------------------------------------------------------------- +proc ComboBox::clearvalue { path } { + Entry::configure $path.e -text "" +} + +# ---------------------------------------------------------------------------- +# Command ComboBox::_create_popup +# ---------------------------------------------------------------------------- +proc ComboBox::_create_popup { path } { + set shell $path.shell + + if {[winfo exists $shell]} { return } + + set lval [Widget::cget $path -values] + set h [Widget::cget $path -height] + set bw [Widget::cget $path -bwlistbox] + + if { $h <= 0 } { + set len [llength $lval] + if { $len < 3 } { + set h 3 + } elseif { $len > 10 } { + set h 10 + } else { + set h $len + } + } + + if {[string equal [tk windowingsystem] "x11"]} { + set sbwidth 11 + } else { + set sbwidth 15 + } + + toplevel $shell -relief solid -bd 1 + wm withdraw $shell + wm overrideredirect $shell 1 + # these commands cause the combobox to behave strangely on OS X + if {! $Widget::_aqua } { + update idle + wm transient $shell [winfo toplevel $path] + catch { wm attributes $shell -topmost 1 } + } + + set sw [ScrolledWindow $shell.sw -managed 1 -size $sbwidth -ipad 0] + + if {$bw} { + set listb [ListBox $shell.listb \ + -relief flat -borderwidth 0 -highlightthickness 0 \ + -selectmode single -selectfill 1 -autofocus 0 -height $h \ + -font [Widget::cget $path -font] \ + -bg [Widget::cget $path -entrybg] \ + -fg [Widget::cget $path -foreground] \ + -selectbackground [Widget::cget $path -selectbackground] \ + -selectforeground [Widget::cget $path -selectforeground]] + + set values [Widget::cget $path -values] + set images [Widget::cget $path -images] + foreach value $values image $images { + $listb insert end #auto -text $value -image $image + } + $listb bindText <1> [list ComboBox::_select $path] + $listb bindImage <1> [list ComboBox::_select $path] + if {[Widget::cget $path -hottrack]} { + $listb bindText <Enter> [list $listb selection set] + $listb bindImage <Enter> [list $listb selection set] + } + } else { + set listb [listbox $shell.listb \ + -relief flat -borderwidth 0 -highlightthickness 0 \ + -exportselection false \ + -font [Widget::cget $path -font] \ + -height $h \ + -bg [Widget::cget $path -entrybg] \ + -fg [Widget::cget $path -foreground] \ + -selectbackground [Widget::cget $path -selectbackground] \ + -selectforeground [Widget::cget $path -selectforeground] \ + -listvariable [Widget::varForOption $path -values]] + ::bind $listb <ButtonRelease-1> [list ComboBox::_select $path @%x,%y] + + if {[Widget::cget $path -hottrack]} { + bindtags $listb [concat [bindtags $listb] ListBoxHotTrack] + } + } + pack $sw -fill both -expand yes + $sw setwidget $listb + + ::bind $listb <Return> "ComboBox::_select [list $path] \[$listb curselection\]" + ::bind $listb <Escape> [list ComboBox::_unmapliste $path] + ::bind $listb <FocusOut> [list ComboBox::_focus_out $path] +} + + +proc ComboBox::_recreate_popup { path } { + variable background + variable foreground + + set shell $path.shell + set lval [Widget::cget $path -values] + set h [Widget::cget $path -height] + set bw [Widget::cget $path -bwlistbox] + + if { $h <= 0 } { + set len [llength $lval] + if { $len < 3 } { + set h 3 + } elseif { $len > 10 } { + set h 10 + } else { + set h $len + } + } + + if { [string equal [tk windowingsystem] "x11"] } { + set sbwidth 11 + } else { + set sbwidth 15 + } + + _create_popup $path + + if {![Widget::cget $path -editable]} { + if {[info exists background]} { + $path.e configure -bg $background + $path.e configure -fg $foreground + unset background + unset foreground + } + } + + set listb $shell.listb + destroy $shell.sw + set sw [ScrolledWindow $shell.sw -managed 1 -size $sbwidth -ipad 0] + $listb configure \ + -height $h \ + -font [Widget::cget $path -font] \ + -bg [Widget::cget $path -entrybg] \ + -fg [Widget::cget $path -foreground] \ + -selectbackground [Widget::cget $path -selectbackground] \ + -selectforeground [Widget::cget $path -selectforeground] + pack $sw -fill both -expand yes + $sw setwidget $listb + raise $listb +} + + +# ---------------------------------------------------------------------------- +# Command ComboBox::_mapliste +# ---------------------------------------------------------------------------- +proc ComboBox::_mapliste { path } { + set listb $path.shell.listb + if {[winfo exists $path.shell] && + [string equal [wm state $path.shell] "normal"]} { + _unmapliste $path + return + } + + if { [Widget::cget $path -state] == "disabled" } { + return + } + if {[llength [set cmd [Widget::getMegawidgetOption $path -postcommand]]]} { + uplevel \#0 $cmd + } + if { ![llength [Widget::getMegawidgetOption $path -values]] } { + return + } + + _recreate_popup $path + + ArrowButton::configure $path.a -relief sunken + update + + set bw [Widget::cget $path -bwlistbox] + + $listb selection clear 0 end + set values [Widget::getMegawidgetOption $path -values] + set curval [Entry::cget $path.e -text] + if { [set idx [lsearch -exact $values $curval]] != -1 || + [set idx [lsearch -exact $values "$curval*"]] != -1 } { + if {$bw} { + set idx [$listb items $idx] + } else { + $listb activate $idx + } + $listb selection set $idx + $listb see $idx + } else { + set idx 0 + if {$bw} { + set idx [$listb items 0] + } else { + $listb activate $idx + } + $listb selection set $idx + $listb see $idx + } + + set width [Widget::cget $path -listboxwidth] + if {!$width} { set width [winfo width $path] } + BWidget::place $path.shell $width 0 below $path + wm deiconify $path.shell + raise $path.shell + BWidget::focus set $listb + if {! $Widget::_aqua } { + BWidget::grab global $path + } +} + + +# ---------------------------------------------------------------------------- +# Command ComboBox::_unmapliste +# ---------------------------------------------------------------------------- +proc ComboBox::_unmapliste { path {refocus 1} } { + # On aqua, state is zoomed, otherwise normal + if {[winfo exists $path.shell] && \ + ( [string equal [wm state $path.shell] "normal"] || + [string equal [wm state $path.shell] "zoomed"] ) } { + if {! $Widget::_aqua } { + BWidget::grab release $path + BWidget::focus release $path.shell.listb $refocus + # Update now because otherwise [focus -force...] makes the app hang! + if {$refocus} { + update + focus -force $path.e + } + } + wm withdraw $path.shell + ArrowButton::configure $path.a -relief raised + } +} + + +# ---------------------------------------------------------------------------- +# Command ComboBox::_select +# ---------------------------------------------------------------------------- +proc ComboBox::_select { path index } { + set index [$path.shell.listb index $index] + _unmapliste $path + if { $index != -1 } { + if { [setvalue $path @$index] } { + set cmd [Widget::getMegawidgetOption $path -modifycmd] + if {[llength $cmd]} { + uplevel \#0 $cmd + } + } + } + $path.e selection clear + if {[$path.e cget -exportselection]} { + $path.e selection range 0 end + } +} + + +# ---------------------------------------------------------------------------- +# Command ComboBox::_modify_value +# ---------------------------------------------------------------------------- +proc ComboBox::_modify_value { path direction } { + if {[setvalue $path $direction] + && [llength [set cmd [Widget::getMegawidgetOption $path -modifycmd]]]} { + uplevel \#0 $cmd + } +} + +# ---------------------------------------------------------------------------- +# Command ComboBox::_expand +# ---------------------------------------------------------------------------- +proc ComboBox::_expand {path} { + set values [Widget::getMegawidgetOption $path -values] + if {![llength $values]} { + bell + return 0 + } + + set found {} + set curval [Entry::cget $path.e -text] + set curlen [$path.e index insert] + if {$curlen < [string length $curval]} { + # we are somewhere in the middle of a string. + # if the full value matches some string in the listbox, + # reorder values to start matching after that string. + set idx [lsearch -exact $values $curval] + if {$idx >= 0} { + set values [concat [lrange $values [expr {$idx+1}] end] \ + [lrange $values 0 $idx]] + } + } + if {$curlen == 0} { + set found $values + } else { + foreach val $values { + if {[string equal -length $curlen $curval $val]} { + lappend found $val + } + } + } + if {[llength $found]} { + Entry::configure $path.e -text [lindex $found 0] + if {[llength $found] > 1} { + set best [_best_match $found [string range $curval 0 $curlen]] + set blen [string length $best] + $path.e icursor $blen + $path.e selection range $blen end + } + } else { + bell + } + return [llength $found] +} + +# best_match -- +# finds the best unique match in a list of names +# The extra $e in this argument allows us to limit the innermost loop a +# little further. +# Arguments: +# l list to find best unique match in +# e currently best known unique match +# Returns: +# longest unique match in the list +# +proc ComboBox::_best_match {l {e {}}} { + set ec [lindex $l 0] + if {[llength $l]>1} { + set e [string length $e]; incr e -1 + set ei [string length $ec]; incr ei -1 + foreach l $l { + while {$ei>=$e && [string first $ec $l]} { + set ec [string range $ec 0 [incr ei -1]] + } + } + } + return $ec +} +# possibly faster +#proc match {string1 string2} { +# set i 1 +# while {[string equal -length $i $string1 $string2]} { incr i } +# return [string range $string1 0 [expr {$i-2}]] +#} +#proc matchlist {list} { +# set list [lsort $list] +# return [match [lindex $list 0] [lindex $list end]] +#} + + +# ---------------------------------------------------------------------------- +# Command ComboBox::_traverse_in +# Called when widget receives keyboard focus due to keyboard traversal. +# ---------------------------------------------------------------------------- +proc ComboBox::_traverse_in { path } { + if {[$path.e selection present] != 1} { + # Autohighlight the selection, but not if one existed + $path.e selection range 0 end + } +} + + +# ---------------------------------------------------------------------------- +# Command ComboBox::_focus_out +# ---------------------------------------------------------------------------- +proc ComboBox::_focus_out { path } { + if {[string first $path [focus]] != 0} { + # we lost focus to some other app or window, so remove the listbox + return [_unmapliste $path 0] + } +} + +proc ComboBox::_auto_complete { path key } { + ## Any key string with more than one character and is not entirely + ## lower-case is considered a function key and is thus ignored. + if {[string length $key] > 1 && [string tolower $key] != $key} { return } + + set text [string map [list {[} {\[} {]} {\]}] [$path.e get]] + if {[string equal $text ""]} { return } + set values [Widget::cget $path -values] + set x [lsearch $values $text*] + if {$x < 0} { return } + + set idx [$path.e index insert] + $path.e configure -text [lindex $values $x] + $path.e icursor $idx + $path.e select range insert end +} + +proc ComboBox::_auto_post { path key } { + if {[string equal $key "Escape"] || [string equal $key "Return"]} { + _unmapliste $path + return + } + if {[catch {$path.shell.listb curselection} x] || $x == ""} { + if {[string equal $key "Up"]} { + _unmapliste $path + return + } + set x -1 + } + if {([string length $key] > 1 && [string tolower $key] != $key) && \ + [string equal $key "BackSpace"] != 0 && \ + [string equal $key "Up"] != 0 && \ + [string equal $key "Down"] != 0} { + return + } + + # post the listbox + _create_popup $path + set width [Widget::cget $path -listboxwidth] + if {!$width} { set width [winfo width $path] } + BWidget::place $path.shell $width 0 below $path + wm deiconify $path.shell + BWidget::grab release $path + BWidget::focus release $path.shell.listb 1 + focus -force $path.e + + set values [Widget::cget $path -values] + switch -- $key { + Up { + if {[incr x -1] < 0} { + set x 0 + } else { + Entry::configure $path.e -text [lindex $values $x] + } + } + Down { + if {[incr x] >= [llength $values]} { + set x [expr {[llength $values] - 1}] + } else { + Entry::configure $path.e -text [lindex $values $x] + } + } + default { + # auto-select within the listbox the item closest to the entry's value + set text [string map [list {[} {\[} {]} {\]}] [$path.e get]] + if {[string equal $text ""]} { + set x 0 + } else { + set x [lsearch $values $text*] + } + } + } + + if {$x >= 0} { + $path.shell.listb selection clear 0 end + $path.shell.listb selection set $x + $path.shell.listb see $x + } +} +# ------------------------------------------------------------------------------ +# Command ComboBox::_destroy +# ------------------------------------------------------------------------------ +proc ComboBox::_destroy { path } { + variable _index + Widget::destroy $path + unset _index($path) +} diff --git a/modules/tclsci/tcl/BWidget/dialog.tcl b/modules/tclsci/tcl/BWidget/dialog.tcl new file mode 100755 index 000000000..209e151f6 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/dialog.tcl @@ -0,0 +1,357 @@ +# ---------------------------------------------------------------------------- +# dialog.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: dialog.tcl,v 1.15.2.1 2010/08/04 13:07:59 oehhar Exp $ +# ---------------------------------------------------------------------------- +# Index of commands: +# - Dialog::create +# - Dialog::configure +# - Dialog::cget +# - Dialog::getframe +# - Dialog::add +# - Dialog::itemconfigure +# - Dialog::itemcget +# - Dialog::invoke +# - Dialog::setfocus +# - Dialog::enddialog +# - Dialog::draw +# - Dialog::withdraw +# - Dialog::_destroy +# ---------------------------------------------------------------------------- + +# JDC: added -transient and -place flag + +namespace eval Dialog { + Widget::define Dialog dialog ButtonBox + + Widget::bwinclude Dialog ButtonBox .bbox \ + remove {-orient} \ + initialize {-spacing 10 -padx 10} + + Widget::declare Dialog { + {-title String "" 0} + {-geometry String "" 0} + {-modal Enum local 0 {none local global}} + {-bitmap TkResource "" 1 label} + {-image TkResource "" 1 label} + {-separator Boolean 0 1} + {-cancel Int -1 0 "%d >= -1"} + {-parent String "" 0} + {-side Enum bottom 1 {bottom left top right}} + {-anchor Enum c 1 {n e w s c}} + {-class String Dialog 1} + {-transient Boolean 1 1} + {-place Enum center 0 {none center left right above below}} + } + + Widget::addmap Dialog "" :cmd {-background {}} + Widget::addmap Dialog "" .frame {-background {}} + + bind BwDialog <Destroy> [list Dialog::_destroy %W] + + variable _widget +} + + +# ---------------------------------------------------------------------------- +# Command Dialog::create +# ---------------------------------------------------------------------------- +proc Dialog::create { path args } { + global tcl_platform + variable _widget + + array set maps [list Dialog {} .bbox {}] + array set maps [Widget::parseArgs Dialog $args] + + # Check to see if the -class flag was specified + set dialogClass "Dialog" + array set dialogArgs $maps(Dialog) + if { [info exists dialogArgs(-class)] } { + set dialogClass $dialogArgs(-class) + } + + if { [string equal $tcl_platform(platform) "unix"] } { + set re raised + set bd 1 + } else { + set re flat + set bd 0 + } + toplevel $path -relief $re -borderwidth $bd -class $dialogClass + wm withdraw $path + + Widget::initFromODB Dialog $path $maps(Dialog) + + bindtags $path [list $path BwDialog all] + wm overrideredirect $path 1 + wm title $path [Widget::cget $path -title] + set parent [Widget::cget $path -parent] + if { ![winfo exists $parent] } { + set parent [winfo parent $path] + } + # JDC: made transient optional + if { [Widget::getoption $path -transient] } { + wm transient $path [winfo toplevel $parent] + } + + set side [Widget::cget $path -side] + if { [string equal $side "left"] || [string equal $side "right"] } { + set orient vertical + } else { + set orient horizontal + } + + set bbox [eval [list ButtonBox::create $path.bbox] $maps(.bbox) \ + -orient $orient] + set frame [frame $path.frame -relief flat -borderwidth 0] + set bg [Widget::cget $path -background] + $path configure -background $bg + $frame configure -background $bg + if { [set bitmap [Widget::getoption $path -image]] != "" } { + set label [label $path.label -image $bitmap -background $bg] + } elseif { [set bitmap [Widget::getoption $path -bitmap]] != "" } { + set label [label $path.label -bitmap $bitmap -background $bg] + } + if { [Widget::getoption $path -separator] } { + Separator::create $path.sep -orient $orient -background $bg + } + set _widget($path,realized) 0 + set _widget($path,nbut) 0 + + set cancel [Widget::getoption $path -cancel] + bind $path <Escape> [list ButtonBox::invoke $path.bbox $cancel] + if {$cancel != -1} { + wm protocol $path WM_DELETE_WINDOW [list ButtonBox::invoke $path.bbox $cancel] + } + bind $path <Return> [list ButtonBox::invoke $path.bbox default] + + return [Widget::create Dialog $path] +} + + +# ---------------------------------------------------------------------------- +# Command Dialog::configure +# ---------------------------------------------------------------------------- +proc Dialog::configure { path args } { + set res [Widget::configure $path $args] + + if { [Widget::hasChanged $path -title title] } { + wm title $path $title + } + if { [Widget::hasChanged $path -background bg] } { + if { [winfo exists $path.label] } { + $path.label configure -background $bg + } + if { [winfo exists $path.sep] } { + Separator::configure $path.sep -background $bg + } + } + if { [Widget::hasChanged $path -cancel cancel] } { + bind $path <Escape> [list ButtonBox::invoke $path.bbox $cancel] + if {$cancel == -1} { + wm protocol $path WM_DELETE_WINDOW "" + } else { + wm protocol $path WM_DELETE_WINDOW [list ButtonBox::invoke $path.bbox $cancel] + } + } + return $res +} + + +# ---------------------------------------------------------------------------- +# Command Dialog::cget +# ---------------------------------------------------------------------------- +proc Dialog::cget { path option } { + return [Widget::cget $path $option] +} + + +# ---------------------------------------------------------------------------- +# Command Dialog::getframe +# ---------------------------------------------------------------------------- +proc Dialog::getframe { path } { + return $path.frame +} + + +# ---------------------------------------------------------------------------- +# Command Dialog::add +# ---------------------------------------------------------------------------- +proc Dialog::add { path args } { + variable _widget + + if {[string equal $::tcl_platform(platform) "windows"] + && $::tk_version >= 8.4} { + set width -11 + } else { + set width 8 + } + set cmd [list ButtonBox::add $path.bbox -width $width \ + -command [list Dialog::enddialog $path $_widget($path,nbut)]] + set res [eval $cmd $args] + incr _widget($path,nbut) + return $res +} + + +# ---------------------------------------------------------------------------- +# Command Dialog::itemconfigure +# ---------------------------------------------------------------------------- +proc Dialog::itemconfigure { path index args } { + return [eval [list ButtonBox::itemconfigure $path.bbox $index] $args] +} + + +# ---------------------------------------------------------------------------- +# Command Dialog::itemcget +# ---------------------------------------------------------------------------- +proc Dialog::itemcget { path index option } { + return [ButtonBox::itemcget $path.bbox $index $option] +} + + +# ---------------------------------------------------------------------------- +# Command Dialog::invoke +# ---------------------------------------------------------------------------- +proc Dialog::invoke { path index } { + ButtonBox::invoke $path.bbox $index +} + + +# ---------------------------------------------------------------------------- +# Command Dialog::setfocus +# ---------------------------------------------------------------------------- +proc Dialog::setfocus { path index } { + ButtonBox::setfocus $path.bbox $index +} + + +# ---------------------------------------------------------------------------- +# Command Dialog::enddialog +# ---------------------------------------------------------------------------- +proc Dialog::enddialog { path result } { + variable _widget + + set _widget($path,result) $result +} + + +# ---------------------------------------------------------------------------- +# Command Dialog::draw +# ---------------------------------------------------------------------------- +proc Dialog::draw { path {focus ""} {overrideredirect 0} {geometry ""}} { + variable _widget + + set parent [Widget::getoption $path -parent] + if { !$_widget($path,realized) } { + set _widget($path,realized) 1 + if { [llength [winfo children $path.bbox]] } { + set side [Widget::getoption $path -side] + if {[string equal $side "left"] || [string equal $side "right"]} { + set pad -padx + set fill y + } else { + set pad -pady + set fill x + } + pack $path.bbox -side $side -padx 1m -pady 1m \ + -anchor [Widget::getoption $path -anchor] + if { [winfo exists $path.sep] } { + pack $path.sep -side $side -fill $fill $pad 2m + } + } + if { [winfo exists $path.label] } { + pack $path.label -side left -anchor n -padx 3m -pady 3m + } + pack $path.frame -padx 1m -pady 1m -fill both -expand yes + } + + set geom [Widget::getMegawidgetOption $path -geometry] + if { $geom != "" } { + wm geometry $path $geom + } + + if { [string equal $geometry ""] && ($geom == "") } { + set place [Widget::getoption $path -place] + if { ![string equal $place none] } { + if { [winfo exists $parent] } { + BWidget::place $path 0 0 $place $parent + } else { + BWidget::place $path 0 0 $place + } + } + } else { + if { $geom != "" } { + wm geometry $path $geom + } else { + wm geometry $path $geometry + } + } + update idletasks + wm overrideredirect $path $overrideredirect + wm deiconify $path + + # patch by Bastien Chevreux (bach@mwgdna.com) + # As seen on Windows systems *sigh* + # When the toplevel is withdrawn, the tkwait command will wait forever. + # So, check that we are not withdrawn + if {![winfo exists $parent] || \ + ([wm state [winfo toplevel $parent]] != "withdrawn")} { + tkwait visibility $path + } + BWidget::focus set $path + if { [winfo exists $focus] } { + focus -force $focus + } else { + ButtonBox::setfocus $path.bbox default + } + + if { [set grab [Widget::cget $path -modal]] != "none" } { + BWidget::grab $grab $path + if {[info exists _widget($path,result)]} { + unset _widget($path,result) + } + tkwait variable Dialog::_widget($path,result) + if { [info exists _widget($path,result)] } { + set res $_widget($path,result) + unset _widget($path,result) + } else { + set res -1 + } + withdraw $path + return $res + } + return "" +} + + +# ---------------------------------------------------------------------------- +# Command Dialog::withdraw +# ---------------------------------------------------------------------------- +proc Dialog::withdraw { path } { + BWidget::grab release $path + BWidget::focus release $path + if { [winfo exists $path] } { + wm withdraw $path + } +} + + +# ---------------------------------------------------------------------------- +# Command Dialog::_destroy +# ---------------------------------------------------------------------------- +proc Dialog::_destroy { path } { + variable _widget + + Dialog::enddialog $path -1 + + BWidget::grab release $path + BWidget::focus release $path + if {[info exists _widget($path,result)]} { + unset _widget($path,result) + } + unset _widget($path,realized) + unset _widget($path,nbut) + + Widget::destroy $path +} diff --git a/modules/tclsci/tcl/BWidget/dragsite.tcl b/modules/tclsci/tcl/BWidget/dragsite.tcl new file mode 100755 index 000000000..bb7b3e7e4 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/dragsite.tcl @@ -0,0 +1,197 @@ +# ------------------------------------------------------------------------------ +# dragsite.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: dragsite.tcl,v 1.8 2003/10/20 21:23:52 damonc Exp $ +# ------------------------------------------------------------------------------ +# Index of commands: +# - DragSite::include +# - DragSite::setdrag +# - DragSite::register +# - DragSite::_begin_drag +# - DragSite::_init_drag +# - DragSite::_end_drag +# - DragSite::_update_operation +# ---------------------------------------------------------------------------- + +namespace eval DragSite { + Widget::define DragSite dragsite -classonly + + Widget::declare DragSite [list \ + [list -dragevent Enum 1 0 [list 1 2 3]] \ + [list -draginitcmd String "" 0] \ + [list -dragendcmd String "" 0] \ + ] + + variable _topw ".drag" + variable _tabops + variable _state + variable _x0 + variable _y0 + + bind BwDrag1 <ButtonPress-1> {DragSite::_begin_drag press %W %s %X %Y} + bind BwDrag1 <B1-Motion> {DragSite::_begin_drag motion %W %s %X %Y} + bind BwDrag2 <ButtonPress-2> {DragSite::_begin_drag press %W %s %X %Y} + bind BwDrag2 <B2-Motion> {DragSite::_begin_drag motion %W %s %X %Y} + bind BwDrag3 <ButtonPress-3> {DragSite::_begin_drag press %W %s %X %Y} + bind BwDrag3 <B3-Motion> {DragSite::_begin_drag motion %W %s %X %Y} + + proc use {} {} +} + + +# ---------------------------------------------------------------------------- +# Command DragSite::include +# ---------------------------------------------------------------------------- +proc DragSite::include { class type event } { + set dragoptions [list \ + [list -dragenabled Boolean 0 0] \ + [list -draginitcmd String "" 0] \ + [list -dragendcmd String "" 0] \ + [list -dragtype String $type 0] \ + [list -dragevent Enum $event 0 [list 1 2 3]] \ + ] + Widget::declare $class $dragoptions +} + + +# ---------------------------------------------------------------------------- +# Command DragSite::setdrag +# Widget interface to register +# ---------------------------------------------------------------------------- +proc DragSite::setdrag { path subpath initcmd endcmd {force 0}} { + set cen [Widget::hasChanged $path -dragenabled en] + set cdragevt [Widget::hasChanged $path -dragevent dragevt] + if { $en } { + if { $force || $cen || $cdragevt } { + register $subpath \ + -draginitcmd $initcmd \ + -dragendcmd $endcmd \ + -dragevent $dragevt + } + } else { + register $subpath + } +} + + +# ---------------------------------------------------------------------------- +# Command DragSite::register +# ---------------------------------------------------------------------------- +proc DragSite::register { path args } { + upvar \#0 DragSite::$path drag + + if { [info exists drag] } { + bind $path $drag(evt) {} + unset drag + } + Widget::init DragSite .drag$path $args + set event [Widget::getMegawidgetOption .drag$path -dragevent] + set initcmd [Widget::getMegawidgetOption .drag$path -draginitcmd] + set endcmd [Widget::getMegawidgetOption .drag$path -dragendcmd] + set tags [bindtags $path] + set idx [lsearch $tags "BwDrag*"] + Widget::destroy .drag$path + if { $initcmd != "" } { + if { $idx != -1 } { + bindtags $path [lreplace $tags $idx $idx BwDrag$event] + } else { + bindtags $path [concat $tags BwDrag$event] + } + set drag(initcmd) $initcmd + set drag(endcmd) $endcmd + set drag(evt) $event + } elseif { $idx != -1 } { + bindtags $path [lreplace $tags $idx $idx] + } +} + + +# ---------------------------------------------------------------------------- +# Command DragSite::_begin_drag +# ---------------------------------------------------------------------------- +proc DragSite::_begin_drag { event source state X Y } { + variable _x0 + variable _y0 + variable _state + + switch -- $event { + press { + set _x0 $X + set _y0 $Y + set _state "press" + } + motion { + if { ![info exists _state] } { + # This is just extra protection. There seem to be + # rare cases where the motion comes before the press. + return + } + if { [string equal $_state "press"] } { + if { abs($_x0-$X) > 3 || abs($_y0-$Y) > 3 } { + set _state "done" + _init_drag $source $state $X $Y + } + } + } + } +} + + +# ---------------------------------------------------------------------------- +# Command DragSite::_init_drag +# ---------------------------------------------------------------------------- +proc DragSite::_init_drag { source state X Y } { + variable _topw + upvar \#0 DragSite::$source drag + + destroy $_topw + toplevel $_topw + wm withdraw $_topw + wm overrideredirect $_topw 1 + + set info [uplevel \#0 $drag(initcmd) [list $source $X $Y .drag]] + if { $info != "" } { + set type [lindex $info 0] + set ops [lindex $info 1] + set data [lindex $info 2] + + if { [winfo children $_topw] == "" } { + if { [string equal $type "BITMAP"] || [string equal $type "IMAGE"] } { + label $_topw.l -image [Bitmap::get dragicon] -relief flat -bd 0 + } else { + label $_topw.l -image [Bitmap::get dragfile] -relief flat -bd 0 + } + pack $_topw.l + } + wm geometry $_topw +[expr {$X+1}]+[expr {$Y+1}] + wm deiconify $_topw + if {[catch {tkwait visibility $_topw}]} { + return + } + BWidget::grab set $_topw + BWidget::focus set $_topw + + bindtags $_topw [list $_topw DragTop] + DropSite::_init_drag $_topw $drag(evt) $source $state $X $Y $type $ops $data + } else { + destroy $_topw + } +} + + +# ---------------------------------------------------------------------------- +# Command DragSite::_end_drag +# ---------------------------------------------------------------------------- +proc DragSite::_end_drag { source target op type data result } { + variable _topw + upvar \#0 DragSite::$source drag + + BWidget::grab release $_topw + BWidget::focus release $_topw + destroy $_topw + if { $drag(endcmd) != "" } { + uplevel \#0 $drag(endcmd) [list $source $target $op $type $data $result] + } +} + + diff --git a/modules/tclsci/tcl/BWidget/dropsite.tcl b/modules/tclsci/tcl/BWidget/dropsite.tcl new file mode 100755 index 000000000..06412f54e --- /dev/null +++ b/modules/tclsci/tcl/BWidget/dropsite.tcl @@ -0,0 +1,456 @@ +# ------------------------------------------------------------------------------ +# dropsite.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: dropsite.tcl,v 1.8 2009/06/30 16:17:37 oehhar Exp $ +# ------------------------------------------------------------------------------ +# Index of commands: +# - DropSite::include +# - DropSite::setdrop +# - DropSite::register +# - DropSite::setcursor +# - DropSite::setoperation +# - DropSite::_update_operation +# - DropSite::_compute_operation +# - DropSite::_draw_operation +# - DropSite::_init_drag +# - DropSite::_motion +# - DropSite::_release +# ---------------------------------------------------------------------------- + + +namespace eval DropSite { + Widget::define DropSite dropsite -classonly + + Widget::declare DropSite [list \ + [list -dropovercmd String "" 0] \ + [list -dropcmd String "" 0] \ + [list -droptypes String "" 0] \ + ] + + proc use {} {} + + variable _top ".drag" + variable _opw ".drag.\#op" + variable _target "" + variable _status 0 + variable _tabops + variable _defops + variable _source + variable _type + variable _data + variable _evt + # key win unix + # shift 1 | 1 -> 1 + # control 4 | 4 -> 4 + # alt 8 | 16 -> 24 + # meta | 64 -> 88 + + array set _tabops { + mod,none 0 + mod,shift 1 + mod,control 4 + mod,alt 24 + ops,copy 1 + ops,move 1 + ops,link 1 + } + + if { $tcl_platform(platform) == "unix" } { + set _tabops(mod,alt) 8 + } else { + set _tabops(mod,alt) 16 + } + array set _defops \ + [list \ + copy,mod shift \ + move,mod control \ + link,mod alt \ + copy,img @[file join $::BWIDGET::LIBRARY "images" "opcopy.xbm"] \ + move,img @[file join $::BWIDGET::LIBRARY "images" "opmove.xbm"] \ + link,img @[file join $::BWIDGET::LIBRARY "images" "oplink.xbm"]] + + bind DragTop <KeyPress-Shift_L> {DropSite::_update_operation [expr %s | 1]} + bind DragTop <KeyPress-Shift_R> {DropSite::_update_operation [expr %s | 1]} + bind DragTop <KeyPress-Control_L> {DropSite::_update_operation [expr %s | 4]} + bind DragTop <KeyPress-Control_R> {DropSite::_update_operation [expr %s | 4]} + if { $tcl_platform(platform) == "unix" } { + bind DragTop <KeyPress-Alt_L> {DropSite::_update_operation [expr %s | 8]} + bind DragTop <KeyPress-Alt_R> {DropSite::_update_operation [expr %s | 8]} + } else { + bind DragTop <KeyPress-Alt_L> {DropSite::_update_operation [expr %s | 16]} + bind DragTop <KeyPress-Alt_R> {DropSite::_update_operation [expr %s | 16]} + } + + bind DragTop <KeyRelease-Shift_L> {DropSite::_update_operation [expr %s & ~1]} + bind DragTop <KeyRelease-Shift_R> {DropSite::_update_operation [expr %s & ~1]} + bind DragTop <KeyRelease-Control_L> {DropSite::_update_operation [expr %s & ~4]} + bind DragTop <KeyRelease-Control_R> {DropSite::_update_operation [expr %s & ~4]} + if { $tcl_platform(platform) == "unix" } { + bind DragTop <KeyRelease-Alt_L> {DropSite::_update_operation [expr %s & ~8]} + bind DragTop <KeyRelease-Alt_R> {DropSite::_update_operation [expr %s & ~8]} + } else { + bind DragTop <KeyRelease-Alt_L> {DropSite::_update_operation [expr %s & ~16]} + bind DragTop <KeyRelease-Alt_R> {DropSite::_update_operation [expr %s & ~16]} + } +} + + +# ---------------------------------------------------------------------------- +# Command DropSite::include +# ---------------------------------------------------------------------------- +proc DropSite::include { class types } { + set dropoptions [list \ + [list -dropenabled Boolean 0 0] \ + [list -dropovercmd String "" 0] \ + [list -dropcmd String "" 0] \ + [list -droptypes String $types 0] \ + ] + Widget::declare $class $dropoptions +} + + +# ---------------------------------------------------------------------------- +# Command DropSite::setdrop +# Widget interface to register +# ---------------------------------------------------------------------------- +proc DropSite::setdrop { path subpath dropover drop {force 0}} { + set cen [Widget::hasChanged $path -dropenabled en] + set ctypes [Widget::hasChanged $path -droptypes types] + if { $en } { + if { $force || $cen || $ctypes } { + register $subpath \ + -droptypes $types \ + -dropcmd $drop \ + -dropovercmd $dropover + } + } else { + register $subpath + } +} + + +# ---------------------------------------------------------------------------- +# Command DropSite::register +# ---------------------------------------------------------------------------- +proc DropSite::register { path args } { + variable _tabops + variable _defops + upvar \#0 DropSite::$path drop + + Widget::init DropSite .drop$path $args + if { [info exists drop] } { + unset drop + } + set dropcmd [Widget::getMegawidgetOption .drop$path -dropcmd] + set types [Widget::getMegawidgetOption .drop$path -droptypes] + set overcmd [Widget::getMegawidgetOption .drop$path -dropovercmd] + Widget::destroy .drop$path + if { $dropcmd != "" && $types != "" } { + set drop(dropcmd) $dropcmd + set drop(overcmd) $overcmd + foreach {type ops} $types { + set drop($type,ops) {} + set masklist {} + foreach {descop lmod} $ops { + if { ![llength $descop] || [llength $descop] > 3 } { + return -code error "invalid operation description \"$descop\"" + } + foreach {subop baseop imgop} $descop { + set subop [string trim $subop] + if { ![string length $subop] } { + return -code error "sub operation is empty" + } + if { ![string length $baseop] } { + set baseop $subop + } + if { [info exists drop($type,ops,$subop)] } { + return -code error "operation \"$subop\" already defined" + } + if { ![info exists _tabops(ops,$baseop)] } { + return -code error "invalid base operation \"$baseop\"" + } + if { ![string equal $subop $baseop] && + [info exists _tabops(ops,$subop)] } { + return -code error "sub operation \"$subop\" is a base operation" + } + if { ![string length $imgop] } { + set imgop $_defops($baseop,img) + } + } + if { [string equal $lmod "program"] } { + set drop($type,ops,$subop) $baseop + set drop($type,img,$subop) $imgop + } else { + if { ![string length $lmod] } { + set lmod $_defops($baseop,mod) + } + set mask 0 + foreach mod $lmod { + if { ![info exists _tabops(mod,$mod)] } { + return -code error "invalid modifier \"$mod\"" + } + set mask [expr {$mask | $_tabops(mod,$mod)}] + } + if { ($mask == 0) != ([string equal $subop "default"]) } { + return -code error "sub operation default can only be used with modifier \"none\"" + } + set drop($type,mod,$mask) $subop + set drop($type,ops,$subop) $baseop + set drop($type,img,$subop) $imgop + lappend masklist $mask + } + } + if { ![info exists drop($type,mod,0)] } { + set drop($type,mod,0) default + set drop($type,ops,default) copy + set drop($type,img,default) $_defops(copy,img) + lappend masklist 0 + } + set drop($type,ops,force) copy + set drop($type,img,force) $_defops(copy,img) + foreach mask [lsort -integer -decreasing $masklist] { + lappend drop($type,ops) $mask $drop($type,mod,$mask) + } + } + } +} + + +# ---------------------------------------------------------------------------- +# Command DropSite::setcursor +# ---------------------------------------------------------------------------- +proc DropSite::setcursor { cursor } { + catch {.drag configure -cursor $cursor} +} + + +# ---------------------------------------------------------------------------- +# Command DropSite::setoperation +# ---------------------------------------------------------------------------- +proc DropSite::setoperation { op } { + variable _curop + variable _dragops + variable _target + variable _type + upvar \#0 DropSite::$_target drop + + if { [info exist drop($_type,ops,$op)] && + $_dragops($drop($_type,ops,$op)) } { + set _curop $op + } else { + # force to a copy operation + set _curop force + } +} + + +# ---------------------------------------------------------------------------- +# Command DropSite::_init_drag +# ---------------------------------------------------------------------------- +proc DropSite::_init_drag { top evt source state X Y type ops data } { + variable _top + variable _source + variable _type + variable _data + variable _target + variable _status + variable _state + variable _dragops + variable _opw + variable _evt + + if {[info exists _dragops]} { + unset _dragops + } + array set _dragops {copy 1 move 0 link 0} + foreach op $ops { + set _dragops($op) 1 + } + set _target "" + set _status 0 + set _top $top + set _source $source + set _type $type + set _data $data + + label $_opw -relief flat -bd 0 -highlightthickness 0 \ + -foreground black -background white + + bind $top <ButtonRelease-$evt> {DropSite::_release %X %Y} + bind $top <B$evt-Motion> {DropSite::_motion %X %Y} + bind $top <Motion> {DropSite::_release %X %Y} + set _state $state + set _evt $evt + _motion $X $Y +} + + +# ---------------------------------------------------------------------------- +# Command DropSite::_update_operation +# ---------------------------------------------------------------------------- +proc DropSite::_update_operation { state } { + variable _top + variable _status + variable _state + + if { $_status & 3 } { + set _state $state + _motion [winfo pointerx $_top] [winfo pointery $_top] + } +} + + +# ---------------------------------------------------------------------------- +# Command DropSite::_compute_operation +# ---------------------------------------------------------------------------- +proc DropSite::_compute_operation { target state type } { + variable _curop + variable _dragops + upvar \#0 DropSite::$target drop + + foreach {mask op} $drop($type,ops) { + if { ($state & $mask) == $mask } { + if { $_dragops($drop($type,ops,$op)) } { + set _curop $op + return + } + } + } + set _curop force +} + + +# ---------------------------------------------------------------------------- +# Command DropSite::_draw_operation +# ---------------------------------------------------------------------------- +proc DropSite::_draw_operation { target type } { + variable _opw + variable _curop + variable _dragops + variable _tabops + variable _status + + upvar \#0 DropSite::$target drop + + if { !($_status & 1) } { + catch {place forget $_opw} + return + } + + if { 0 } { + if { ![info exist drop($type,ops,$_curop)] || + !$_dragops($drop($type,ops,$_curop)) } { + # force to a copy operation + set _curop copy + catch { + $_opw configure -bitmap $_tabops(img,copy) + place $_opw -relx 1 -rely 1 -anchor se + } + } + } elseif { [string equal $_curop "default"] } { + catch {place forget $_opw} + } else { + catch { + $_opw configure -bitmap $drop($type,img,$_curop) + place $_opw -relx 1 -rely 1 -anchor se + } + } +} + + +# ---------------------------------------------------------------------------- +# Command DropSite::_motion +# ---------------------------------------------------------------------------- +proc DropSite::_motion { X Y } { + variable _top + variable _target + variable _status + variable _state + variable _curop + variable _type + variable _data + variable _source + variable _evt + + set script [bind $_top <B$_evt-Motion>] + bind $_top <B$_evt-Motion> {} + bind $_top <Motion> {} + wm geometry $_top "+[expr {$X+1}]+[expr {$Y+1}]" + update + if { ![winfo exists $_top] } { + return + } + set path [winfo containing $X $Y] + if { ![string equal $path $_target] } { + # path != current target + if { $_status & 2 } { + # current target is valid and has recall status + # generate leave event + upvar \#0 DropSite::$_target drop + uplevel \#0 $drop(overcmd) [list $_target $_source leave $X $Y $_curop $_type $_data] + } + set _target $path + upvar \#0 DropSite::$_target drop + if { [info exists drop($_type,ops)] } { + # path is a valid target + _compute_operation $_target $_state $_type + if { $drop(overcmd) != "" } { + set arg [list $_target $_source enter $X $Y $_curop $_type $_data] + set _status [uplevel \#0 $drop(overcmd) $arg] + } else { + set _status 1 + catch {$_top configure -cursor based_arrow_down} + } + _draw_operation $_target $_type + update + catch { + bind $_top <B$_evt-Motion> {DropSite::_motion %X %Y} + bind $_top <Motion> {DropSite::_release %X %Y} + } + return + } else { + set _status 0 + catch {$_top configure -cursor dot} + _draw_operation "" "" + } + } elseif { $_status & 2 } { + upvar \#0 DropSite::$_target drop + _compute_operation $_target $_state $_type + set arg [list $_target $_source motion $X $Y $_curop $_type $_data] + set _status [uplevel \#0 $drop(overcmd) $arg] + _draw_operation $_target $_type + } + update + catch { + bind $_top <B$_evt-Motion> {DropSite::_motion %X %Y} + bind $_top <Motion> {DropSite::_release %X %Y} + } +} + + + +# ---------------------------------------------------------------------------- +# Command DropSite::_release +# ---------------------------------------------------------------------------- +proc DropSite::_release { X Y } { + variable _target + variable _status + variable _curop + variable _source + variable _type + variable _data + + if { $_status & 1 } { + upvar \#0 DropSite::$_target drop + + set res [uplevel \#0 $drop(dropcmd) [list $_target $_source $X $Y $_curop $_type $_data]] + DragSite::_end_drag $_source $_target $drop($_type,ops,$_curop) $_type $_data $res + } else { + if { $_status & 2 } { + # notify leave event + upvar \#0 DropSite::$_target drop + uplevel \#0 $drop(overcmd) [list $_target $_source leave $X $Y $_curop $_type $_data] + } + DragSite::_end_drag $_source "" "" $_type $_data 0 + } +} diff --git a/modules/tclsci/tcl/BWidget/dynhelp.tcl b/modules/tclsci/tcl/BWidget/dynhelp.tcl new file mode 100755 index 000000000..937499224 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/dynhelp.tcl @@ -0,0 +1,793 @@ +# ---------------------------------------------------------------------------- +# dynhelp.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: dynhelp.tcl,v 1.20.2.1 2009/08/12 07:20:21 oehhar Exp $ +# ---------------------------------------------------------------------------- +# Index of commands: +# - DynamicHelp::configure +# - DynamicHelp::include +# - DynamicHelp::sethelp +# - DynamicHelp::register +# - DynamicHelp::_motion_balloon +# - DynamicHelp::_motion_info +# - DynamicHelp::_leave_info +# - DynamicHelp::_menu_info +# - DynamicHelp::_show_help +# - DynamicHelp::_init +# ---------------------------------------------------------------------------- + +namespace eval DynamicHelp { + Widget::define DynamicHelp dynhelp -classonly + + if {$::tcl_version >= 8.5} { + set fontdefault TkTooltipFont + } elseif {$Widget::_aqua} { + set fontdefault {helvetica 11} + } else { + set fontdefault {helvetica 8} + } + + Widget::declare DynamicHelp [list\ + {-foreground TkResource black 0 label}\ + {-topbackground TkResource black 0 {label -foreground}}\ + {-background TkResource "#FFFFC0" 0 label}\ + {-borderwidth TkResource 1 0 label}\ + {-justify TkResource left 0 label}\ + [list -font TkResource $fontdefault 0 label]\ + {-delay Int 600 0 "%d >= 100 & %d <= 2000"}\ + {-state Enum "normal" 0 {normal disabled}}\ + {-padx TkResource 1 0 label}\ + {-pady TkResource 1 0 label}\ + {-bd Synonym -borderwidth}\ + {-bg Synonym -background}\ + {-fg Synonym -foreground}\ + {-topbg Synonym -topbackground}\ + ] + + proc use {} {} + + variable _registered + variable _canvases + variable _texts + + variable _top ".help_shell" + variable _id "" + variable _delay 600 + variable _current_balloon "" + variable _current_variable "" + variable _saved + + Widget::init DynamicHelp $_top {} + + bind BwHelpBalloon <Enter> {DynamicHelp::_motion_balloon enter %W %X %Y} + bind BwHelpBalloon <Motion> {DynamicHelp::_motion_balloon motion %W %X %Y} + bind BwHelpBalloon <Leave> {DynamicHelp::_motion_balloon leave %W %X %Y} + bind BwHelpBalloon <Button> {DynamicHelp::_motion_balloon button %W %X %Y} + bind BwHelpBalloon <Destroy> {DynamicHelp::_unset_help %W} + + bind BwHelpVariable <Enter> {DynamicHelp::_motion_info %W} + bind BwHelpVariable <Leave> {DynamicHelp::_leave_info %W} + bind BwHelpVariable <Destroy> {DynamicHelp::_unset_help %W} + + bind BwHelpMenu <<MenuSelect>> {DynamicHelp::_menu_info select %W} + bind BwHelpMenu <Unmap> {DynamicHelp::_menu_info unmap %W} + bind BwHelpMenu <Destroy> {DynamicHelp::_unset_help %W} +} + + +# ---------------------------------------------------------------------------- +# Command DynamicHelp::configure +# ---------------------------------------------------------------------------- +proc DynamicHelp::configure { args } { + variable _top + variable _delay + + set res [Widget::configure $_top $args] + if { [Widget::hasChanged $_top -delay val] } { + set _delay $val + } + + return $res +} + + +# ---------------------------------------------------------------------------- +# Command DynamicHelp::include +# ---------------------------------------------------------------------------- +proc DynamicHelp::include { class type } { + set helpoptions [list \ + [list -helptext String "" 0] \ + [list -helpvar String "" 0] \ + [list -helpcmd String "" 0] \ + [list -helptype Enum $type 0 [list balloon variable]] \ + ] + Widget::declare $class $helpoptions +} + + +# ---------------------------------------------------------------------------- +# Command DynamicHelp::sethelp +# ---------------------------------------------------------------------------- +proc DynamicHelp::sethelp { path subpath {force 0}} { + foreach {ctype ctext cvar} [Widget::hasChangedX $path \ + -helptype -helptext -helpvar] break + if { $force || $ctype || $ctext || $cvar } { + set htype [Widget::cget $path -helptype] + switch $htype { + balloon { + return [register $subpath balloon \ + [Widget::cget $path -helptext]] + } + variable { + return [register $subpath variable \ + [Widget::cget $path -helpvar] \ + [Widget::cget $path -helptext]] + } + } + return [register $subpath $htype] + } +} + +# ---------------------------------------------------------------------------- +# Command DynamicHelp::register +# +# DynamicHelp::register path balloon ?itemOrTag? text +# DynamicHelp::register path variable ?itemOrTag? text varName +# DynamicHelp::register path menu varName +# DynamicHelp::register path menuentry index text +# ---------------------------------------------------------------------------- +proc DynamicHelp::register { path type args } { + variable _registered + + set len [llength $args] + if {$type == "balloon" && $len > 1} { + switch -exact -- [winfo class $path] { + "Canvas" { set type canvasBalloon } + "Text" - + "Ctext" { set type textBalloon } + } + } + if {$type == "variable" && $len > 2} { + switch -exact -- [winfo class $path] { + "Canvas" { set type canvasVariable } + "Text" - + "Ctext" { set type textVariable } + } + } + + if { ![winfo exists $path] } { + _unset_help $path + return 0 + } + + switch $type { + balloon { + set text [lindex $args 0] + if {$text == ""} { + if {[info exists _registered($path,balloon)]} { + unset _registered($path,balloon) + } + return 0 + } + + _add_balloon $path $text + } + + canvasBalloon { + set tagOrItem [lindex $args 0] + set text [lindex $args 1] + if {$text == ""} { + if {[info exists _registered($path,$tagOrItem,balloon)]} { + unset _registered($path,$tagOrItem,balloon) + } + return 0 + } + + _add_canvas_balloon $path $text $tagOrItem + } + + textBalloon { + set tagOrItem [lindex $args 0] + set text [lindex $args 1] + if {$text == ""} { + if {[info exists _registered($path,$tagOrItem,balloon)]} { + unset _registered($path,$tagOrItem,balloon) + } + return 0 + } + + _add_text_balloon $path $text $tagOrItem + } + + variable { + set var [lindex $args 0] + set text [lindex $args 1] + if {$text == "" || $var == ""} { + if {[info exists _registered($path,variable)]} { + unset _registered($path,variable) + } + return 0 + } + + _add_variable $path $text $var + } + + canvasVariable { + set tagOrItem [lindex $args 0] + set var [lindex $args 1] + set text [lindex $args 2] + if {$text == "" || $var == ""} { + if {[info exists _registered($path,$tagOrItem,variable)]} { + unset _registered($path,$tagOrItem,variable) + } + return 0 + } + + _add_canvas_variable $path $text $var $tagOrItem + } + + textVariable { + set tagOrItem [lindex $args 0] + set var [lindex $args 1] + set text [lindex $args 2] + if {$text == "" || $var == ""} { + if {[info exists _registered($path,$tagOrItem,variable)]} { + unset _registered($path,$tagOrItem,variable) + } + return 0 + } + + _add_text_variable $path $text $var $tagOrItem + } + + menu { + set var [lindex $args 0] + if {$var == ""} { + set cpath [BWidget::clonename $path] + if {[winfo exists $cpath]} { set path $cpath } + if {[info exists _registered($path)]} { + unset _registered($path) + } + return 0 + } + + _add_menu $path $var + } + + menuentry { + set cpath [BWidget::clonename $path] + if { [winfo exists $cpath] } { set path $cpath } + if {![info exists _registered($path)]} { return 0 } + + set text [lindex $args 1] + set index [lindex $args 0] + if {$text == "" || $index == ""} { + set idx [lsearch $_registered($path) [list $index *]] + set _registered($path) [lreplace $_registered($path) $idx $idx] + return 0 + } + + _add_menuentry $path $text $index + } + + default { + _unset_help $path + return 0 + } + } + + return 1 +} + + +proc DynamicHelp::add { path args } { + variable _registered + + array set data { + -type balloon + -text "" + -item "" + -index -1 + -command "" + -variable "" + } + if {[winfo exists $path] && [winfo class $path] == "Menu"} { + set data(-type) menu + } + array set data $args + + set item $path + + switch -- $data(-type) { + "balloon" { + if {$data(-item) != ""} { + switch -exact -- [winfo class $path] { + "Canvas" { + _add_canvas_balloon $path $data(-text) $data(-item) + set item $path,$data(-item) + } + "Text" - + "Ctext" { + _add_text_balloon $path $data(-text) $data(-item) + set item $path,$data(-item) + } + default { + _add_balloon $path $data(-text) + } + } + } else { + _add_balloon $path $data(-text) + } + + if {$data(-variable) != ""} { + set _registered($item,balloonVar) $data(-variable) + } + } + + "variable" { + set var $data(-variable) + if {$data(-item) != ""} { + switch -exact -- [winfo class $path] { + "Canvas" { + _add_canvas_variable $path $data(-text) $var $data(-item) + set item $path,$data(-item) + } + "Text" - + "Ctext" { + _add_text_variable $path $data(-text) $var $data(-item) + set item $path,$data(-item) + } + default { + _add_variable $path $data(-text) $var + } + } + } else { + _add_variable $path $data(-text) $var + } + } + + "menu" { + if {$data(-index) != -1} { + set cpath [BWidget::clonename $path] + if { [winfo exists $cpath] } { set path $cpath } + if {![info exists _registered($path)]} { return 0 } + _add_menuentry $path $data(-text) $data(-index) + set item $path,$data(-index) + } else { + _add_menu $path $data(-variable) + } + } + + default { + return 0 + } + } + + if {$data(-command) != ""} {set _registered($item,command) $data(-command)} + + return 1 +} + + +proc DynamicHelp::delete { path } { + _unset_help $path +} + + +proc DynamicHelp::_add_bind_tag { path tag } { + set evt [bindtags $path] + set idx [lsearch $evt $tag] + set evt [lreplace $evt $idx $idx] + lappend evt $tag + bindtags $path $evt +} + + +proc DynamicHelp::_add_balloon { path text } { + variable _registered + set _registered($path,balloon) $text + _add_bind_tag $path BwHelpBalloon +} + + +proc DynamicHelp::_add_canvas_balloon { path text tagOrItem } { + variable _canvases + variable _registered + + set _registered($path,$tagOrItem,balloon) $text + + if {![info exists _canvases($path,balloon)]} { + ## This canvas doesn't have the bindings yet. + + _add_bind_tag $path BwHelpBalloon + + $path bind BwHelpBalloon <Enter> \ + {DynamicHelp::_motion_balloon enter %W %X %Y 1} + $path bind BwHelpBalloon <Motion> \ + {DynamicHelp::_motion_balloon motion %W %X %Y 1} + $path bind BwHelpBalloon <Leave> \ + {DynamicHelp::_motion_balloon leave %W %X %Y 1} + $path bind BwHelpBalloon <Button> \ + {DynamicHelp::_motion_balloon button %W %X %Y 1} + + set _canvases($path,balloon) 1 + } + + $path addtag BwHelpBalloon withtag $tagOrItem +} + + +proc DynamicHelp::_add_text_balloon { path text tagOrItem } { + variable _texts + variable _registered + + set _registered($path,$tagOrItem,balloon) $text + + if { ![info exists _texts($path,$tagOrItem,balloon)] } { + $path tag bind $tagOrItem <Enter> \ + [list DynamicHelp::_motion_balloon enter $path %X %Y 0 1] + $path tag bind $tagOrItem <Motion> \ + [list DynamicHelp::_motion_balloon motion $path %X %Y 0 1] + $path tag bind $tagOrItem <Leave> \ + [list DynamicHelp::_motion_balloon leave $path %X %Y 0 1] + $path tag bind $tagOrItem <Button> \ + [list DynamicHelp::_motion_balloon button $path %X %Y 0 1] + + set _texts($path,$tagOrItem,balloon) 1 + } +} + + +proc DynamicHelp::_add_variable { path text varName } { + variable _registered + set _registered($path,variable) [list $varName $text] + _add_bind_tag $path BwHelpVariable +} + + +proc DynamicHelp::_add_canvas_variable { path text varName tagOrItem } { + variable _canvases + variable _registered + + set _registered($path,$tagOrItem,variable) [list $varName $text] + + if {![info exists _canvases($path,variable)]} { + ## This canvas doesn't have the bindings yet. + + _add_bind_tag $path BwHelpVariable + + $path bind BwHelpVariable <Enter> \ + {DynamicHelp::_motion_info %W 1} + $path bind BwHelpVariable <Motion> \ + {DynamicHelp::_motion_info %W 1} + $path bind BwHelpVariable <Leave> \ + {DynamicHelp::_leave_info %W 1} + + set _canvases($path,variable) 1 + } + + $path addtag BwHelpVariable withtag $tagOrItem +} + + +proc DynamicHelp::_add_text_variable { path text varName tagOrItem } { + variable _texts + variable _registered + + set _registered($path,$tagOrItem,variable) [list $varName $text] + + if {![info exists _texts($path,$tagOrItem,variable)]} { + + $path tag bind $tagOrItem <Enter> \ + [list DynamicHelp::_motion_info $path 0 1] + $path tag bind $tagOrItem <Motion> \ + [list DynamicHelp::_motion_info $path 0 1] + $path tag bind $tagOrItem <Leave> \ + [list DynamicHelp::_leave_info $path 0 1] + + set _texts($path,$tagOrItem,variable) 1 + } +} + + +proc DynamicHelp::_add_menu { path varName } { + variable _registered + + set cpath [BWidget::clonename $path] + if { [winfo exists $cpath] } { set path $cpath } + + set _registered($path) [list $varName] + _add_bind_tag $path BwHelpMenu +} + + +proc DynamicHelp::_add_menuentry { path text index } { + variable _registered + + set idx [lsearch $_registered($path) [list $index *]] + set list [list $index $text] + if { $idx == -1 } { + lappend _registered($path) $list + } else { + set _registered($path) \ + [lreplace $_registered($path) $idx $idx $list] + } +} + + +# ---------------------------------------------------------------------------- +# Command DynamicHelp::_motion_balloon +# ---------------------------------------------------------------------------- +proc DynamicHelp::_motion_balloon { type path x y {isCanvasItem 0} {isTextItem 0} } { + variable _top + variable _id + variable _delay + variable _current_balloon + + set w $path + if {$isCanvasItem} { + set path [_get_canvas_path $path balloon] + } elseif {$isTextItem} { + set path [_get_text_path $path balloon] + } + + if { $_current_balloon != $path && $type == "enter" } { + set _current_balloon $path + set type "motion" + destroy $_top + } + if { $_current_balloon == $path } { + if { $_id != "" } { + after cancel $_id + set _id "" + } + if { $type == "motion" } { + if { ![winfo exists $_top] } { + set cmd [list DynamicHelp::_show_help $path $w $x $y] + set _id [after $_delay $cmd] + } + # Bug 923942 proposes to destroy on motion to remove dynhelp on motion. + # this might be an optional behaviour in future versions + } else { + destroy $_top + set _current_balloon "" + } + } +} + + +# ---------------------------------------------------------------------------- +# Command DynamicHelp::_motion_info +# ---------------------------------------------------------------------------- +proc DynamicHelp::_motion_info { path {isCanvasItem 0} {isTextItem 0} } { + variable _saved + variable _registered + variable _current_variable + + if {$isCanvasItem} { + set path [_get_canvas_path $path variable] + } elseif {$isTextItem} { + set path [_get_text_path $path variable] + } + + if { $_current_variable != $path + && [info exists _registered($path,variable)] } { + + set varName [lindex $_registered($path,variable) 0] + if {![info exists _saved]} { set _saved [GlobalVar::getvar $varName] } + set string [lindex $_registered($path,variable) 1] + if {[info exists _registered($path,command)]} { + set string [uplevel #0 $_registered($path,command)] + } + GlobalVar::setvar $varName $string + set _current_variable $path + } +} + + +# ---------------------------------------------------------------------------- +# Command DynamicHelp::_leave_info +# Leave event may be called twice (in case of pointer grab) +# ---------------------------------------------------------------------------- +proc DynamicHelp::_leave_info { path {isCanvasItem 0} {isTextItem 0} } { + variable _saved + variable _registered + variable _current_variable + + if {$isCanvasItem} { + set path [_get_canvas_path $path variable] + } elseif {$isTextItem} { + set path [_get_text_path $path variable] + } + + if { [string equal $_current_variable $path] \ + && [info exists _registered($path,variable)] } { + set varName [lindex $_registered($path,variable) 0] + GlobalVar::setvar $varName $_saved + unset _saved + set _current_variable "" + } +} + + +# ---------------------------------------------------------------------------- +# Command DynamicHelp::_menu_info +# ---------------------------------------------------------------------------- +# We have to check for unmap event on Unix. On Windows, unmap +# is not delivered, but <<MenuSelect>> is triggered appropriately when menu +# is unmapped. +proc DynamicHelp::_menu_info { event path } { + variable _registered + + if { [info exists _registered($path)] } { + set index [$path index active] + set varName [lindex $_registered($path) 0] + if { ![string equal $event "unmap"] && + ![string equal $index "none"] && + [set idx [lsearch $_registered($path) [list $index *]]] != -1 } { + set string [lindex [lindex $_registered($path) $idx] 1] + if {[info exists _registered($path,$index,command)]} { + set string [uplevel #0 $_registered($path,$index,command)] + } + GlobalVar::setvar $varName $string + } else { + GlobalVar::setvar $varName "" + } + } +} + + +# ---------------------------------------------------------------------------- +# Command DynamicHelp::_show_help +# ---------------------------------------------------------------------------- +proc DynamicHelp::_show_help { path w x y } { + variable _top + variable _registered + variable _id + variable _delay + + if { [Widget::getoption $_top -state] == "disabled" } { return } + + if { [info exists _registered($path,balloon)] } { + destroy $_top + + set string $_registered($path,balloon) + + if {[info exists _registered($path,balloonVar)]} { + upvar #0 $_registered($path,balloonVar) var + if {[info exists var]} { set string $var } + } + + if {[info exists _registered($path,command)]} { + set string [uplevel #0 $_registered($path,command)] + } + + if {$string == ""} { return } + + toplevel $_top -relief flat \ + -bg [Widget::getoption $_top -topbackground] \ + -bd [Widget::getoption $_top -borderwidth] \ + -screen [winfo screen $w] + + wm withdraw $_top + if { $Widget::_aqua } { + ::tk::unsupported::MacWindowStyle style $_top help none + } else { + wm overrideredirect $_top 1 + } + + catch { wm attributes $_top -topmost 1 } + + label $_top.label -text $string \ + -relief flat -bd 0 -highlightthickness 0 \ + -padx [Widget::getoption $_top -padx] \ + -pady [Widget::getoption $_top -pady] \ + -foreground [Widget::getoption $_top -foreground] \ + -background [Widget::getoption $_top -background] \ + -font [Widget::getoption $_top -font] \ + -justify [Widget::getoption $_top -justify] + + + pack $_top.label -side left + update idletasks + + if {![winfo exists $_top]} {return} + + set scrwidth [winfo vrootwidth .] + set scrheight [winfo vrootheight .] + set width [winfo reqwidth $_top] + set height [winfo reqheight $_top] + + # On windows multi screen configurations, coordinates may get outside + # the main screen. We suppose that all screens have the same size + # because it is not possible to query the size of the other screens. + + set screenx [expr {$x % $scrwidth} ] + set screeny [expr {$y % $scrheight} ] + + # Increment the required size by the deplacement from the passed point + incr width 8 + incr height 12 + + if { $screenx+$width > $scrwidth } { + set x [expr {$x + ($scrwidth - $screenx) - ($width - 8)}] + } else { + incr x 8 + } + if { $screeny+$height > $scrheight } { + set y [expr {$y - $height}] + } else { + incr y 12 + } + + wm geometry $_top "+$x+$y" + update idletasks + + if {![winfo exists $_top]} { return } + wm deiconify $_top + raise $_top + } +} + +# ---------------------------------------------------------------------------- +# Command DynamicHelp::_unset_help +# ---------------------------------------------------------------------------- +proc DynamicHelp::_unset_help { path } { + variable _canvases + variable _texts + variable _registered + variable _top + variable _current_balloon + + if {[info exists _registered($path)]} { unset _registered($path) } + if {[winfo exists $path]} { + set cpath [BWidget::clonename $path] + if {[info exists _registered($cpath)]} { unset _registered($cpath) } + } + array unset _canvases $path,* + array unset _texts $path,* + array unset _registered $path,* + if {[string equal $path $_current_balloon]} {destroy $_top} +} + +# ---------------------------------------------------------------------------- +# Command DynamicHelp::_get_canvas_path +# ---------------------------------------------------------------------------- +proc DynamicHelp::_get_canvas_path { path type {item ""} } { + variable _registered + + if {$item == ""} { set item [$path find withtag current] } + + ## Check the tags related to this item for the one that + ## represents our text. If we have text specific to this + ## item or for 'all' items, they override any other tags. + eval [list lappend tags $item all] [$path itemcget $item -tags] + foreach tag $tags { + set check $path,$tag + if {![info exists _registered($check,$type)]} { continue } + return $check + } + + return $path +} + +# ---------------------------------------------------------------------------- +# Command DynamicHelp::_get_text_path +# ---------------------------------------------------------------------------- +proc DynamicHelp::_get_text_path { path type {item ""} } { + variable _registered + + if {$item == ""} { set item [$path tag names current] } + + ## Check the tags related to this item for the one that + ## represents our text. If we have text specific to this + ## item or for 'all' items, they override any other tags. + eval [list lappend tags $item all] $item + foreach tag $tags { + set check $path,$tag + if {![info exists _registered($check,$type)]} { continue } + return $check + } + + return $path +} diff --git a/modules/tclsci/tcl/BWidget/entry.tcl b/modules/tclsci/tcl/BWidget/entry.tcl new file mode 100755 index 000000000..ebf308f48 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/entry.tcl @@ -0,0 +1,472 @@ +# ------------------------------------------------------------------------------ +# entry.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: entry.tcl,v 1.22 2009/06/10 08:48:06 oehhar Exp $ +# ------------------------------------------------------------------------------ +# Index of commands: +# - Entry::create +# - Entry::configure +# - Entry::cget +# - Entry::_destroy +# - Entry::_init_drag_cmd +# - Entry::_end_drag_cmd +# - Entry::_drop_cmd +# - Entry::_over_cmd +# - Entry::_auto_scroll +# - Entry::_scroll +# ------------------------------------------------------------------------------ + +namespace eval Entry { + Widget::define Entry entry DragSite DropSite DynamicHelp + + # Note: -textvariable is pulled off of the tk entry and put onto the + # BW Entry so that we avoid the TkResource test for it, which screws up + # the existance/non-existance bits of the -textvariable. + Widget::tkinclude Entry entry :cmd \ + remove { -state -background -foreground -textvariable + -disabledforeground -disabledbackground } + + set declare [list \ + [list -background TkResource "" 0 entry] \ + [list -foreground TkResource "" 0 entry] \ + [list -state Enum normal 0 [list normal disabled]] \ + [list -text String "" 0] \ + [list -textvariable String "" 0] \ + [list -editable Boolean 1 0] \ + [list -command String "" 0] \ + [list -relief TkResource "" 0 entry] \ + [list -borderwidth TkResource "" 0 entry] \ + [list -fg Synonym -foreground] \ + [list -bg Synonym -background] \ + [list -bd Synonym -borderwidth] \ + ] + + if {![package vsatisfies [package provide Tk] 8.4]} { + ## If we're not running version 8.4 or higher, get our + ## disabled resources from the button widget. + lappend declare [list -disabledforeground TkResource "" 0 button] + lappend declare [list -disabledbackground TkResource "" 0 \ + {button -background}] + } else { + lappend declare [list -disabledforeground TkResource "" 0 entry] + lappend declare [list -disabledbackground TkResource "" 0 entry] + } + + Widget::declare Entry $declare + Widget::addmap Entry "" :cmd { -textvariable {} } + + DynamicHelp::include Entry balloon + DragSite::include Entry "" 3 + DropSite::include Entry { + TEXT {move {}} + FGCOLOR {move {}} + BGCOLOR {move {}} + COLOR {move {}} + } + + foreach event [bind Entry] { + bind BwEntry $event [bind Entry $event] + } + + # Copy is kind of a special event. It should be enabled when the + # widget is editable but not disabled, and not when the widget is disabled. + # To make this a bit easier to manage, we will handle it separately. + + bind BwEntry <<Copy>> {} + bind BwEditableEntry <<Copy>> [bind Entry <<Copy>>] + + bind BwEntry <Return> [list Entry::invoke %W] + bind BwEntry <Destroy> [list Entry::_destroy %W] + bind BwDisabledEntry <Destroy> [list Entry::_destroy %W] +} + + +# ------------------------------------------------------------------------------ +# Command Entry::create +# ------------------------------------------------------------------------------ +proc Entry::create { path args } { + variable $path + upvar 0 $path data + + array set maps [list Entry {} :cmd {}] + array set maps [Widget::parseArgs Entry $args] + + set data(afterid) "" + eval [list entry $path] $maps(:cmd) + Widget::initFromODB Entry $path $maps(Entry) + set state [Widget::getMegawidgetOption $path -state] + set editable [Widget::getMegawidgetOption $path -editable] + set text [Widget::getMegawidgetOption $path -text] + if { $editable && [string equal $state "normal"] } { + bindtags $path [list $path BwEntry [winfo toplevel $path] all] + $path configure -takefocus 1 -insertontime 600 + } else { + bindtags $path [list $path BwDisabledEntry [winfo toplevel $path] all] + $path configure -takefocus 0 -insertontime 0 + } + if { $editable == 0 } { + $path configure -cursor left_ptr + } + if { [string equal $state "disabled"] } { + $path configure \ + -foreground [Widget::getMegawidgetOption $path -disabledforeground] \ + -background [Widget::getMegawidgetOption $path -disabledbackground] + } else { + $path configure \ + -foreground [Widget::getMegawidgetOption $path -foreground] \ + -background [Widget::getMegawidgetOption $path -background] + bindtags $path [linsert [bindtags $path] 2 BwEditableEntry] + } + if { [string length $text] } { + set varName [$path cget -textvariable] + if { ![string equal $varName ""] } { + uplevel \#0 [list set $varName [Widget::cget $path -text]] + } else { + set validateState [$path cget -validate] + $path configure -validate none + $path delete 0 end + $path configure -validate $validateState + $path insert 0 [Widget::getMegawidgetOption $path -text] + } + } + + DragSite::setdrag $path $path Entry::_init_drag_cmd Entry::_end_drag_cmd 1 + DropSite::setdrop $path $path Entry::_over_cmd Entry::_drop_cmd 1 + DynamicHelp::sethelp $path $path 1 + + Widget::create Entry $path + proc ::$path { cmd args } \ + "return \[Entry::_path_command [list $path] \$cmd \$args\]" + return $path +} + + +# ------------------------------------------------------------------------------ +# Command Entry::configure +# ------------------------------------------------------------------------------ +proc Entry::configure { path args } { + # Cheat by setting the -text value to the current contents of the entry + # This might be better hidden behind a function in ::Widget. + set Widget::Entry::${path}:opt(-text) [$path:cmd get] + + set res [Widget::configure $path $args] + + # Extract the modified bits that we are interested in. + set vars [list chstate cheditable chfg chdfg chbg chdbg chtext] + set opts [list -state -editable -foreground -disabledforeground \ + -background -disabledbackground -text] + foreach $vars [eval [linsert $opts 0 Widget::hasChangedX $path]] { break } + + if { $chstate || $cheditable } { + set state [Widget::getMegawidgetOption $path -state] + set editable [Widget::getMegawidgetOption $path -editable] + set btags [bindtags $path] + if { $editable && [string equal $state "normal"] } { + set idx [lsearch $btags BwDisabledEntry] + if { $idx != -1 } { + bindtags $path [lreplace $btags $idx $idx BwEntry] + } + $path:cmd configure -takefocus 1 -insertontime 600 + } else { + set idx [lsearch $btags BwEntry] + if { $idx != -1 } { + bindtags $path [lreplace $btags $idx $idx BwDisabledEntry] + } + $path:cmd configure -takefocus 0 -insertontime 0 + if { [string equal [focus] $path] } { + focus . + } + } + } + + if { $chstate || $chfg || $chdfg || $chbg || $chdbg } { + set state [Widget::getMegawidgetOption $path -state] + if { [string equal $state "disabled"] } { + $path:cmd configure \ + -fg [Widget::cget $path -disabledforeground] \ + -bg [Widget::cget $path -disabledbackground] + } else { + $path:cmd configure \ + -fg [Widget::cget $path -foreground] \ + -bg [Widget::cget $path -background] + } + } + if { $chstate } { + if { [string equal $state "disabled"] } { + set idx [lsearch -exact [bindtags $path] BwEditableEntry] + if { $idx != -1 } { + bindtags $path [lreplace [bindtags $path] $idx $idx] + } + } else { + set idx [expr {[lsearch [bindtags $path] Bw*Entry] + 1}] + bindtags $path [linsert [bindtags $path] $idx BwEditableEntry] + } + } + + if { $cheditable } { + if { $editable } { + $path:cmd configure -cursor xterm + } else { + $path:cmd configure -cursor left_ptr + } + } + + if { $chtext } { + # Oh my lordee-ba-goordee + # Do some magic to prevent multiple validation command firings. + # If there is a textvariable, set that to the right value; if not, + # disable validation, delete the old text, enable, then set the text. + set varName [$path:cmd cget -textvariable] + if { ![string equal $varName ""] } { + uplevel \#0 [list set $varName \ + [Widget::getMegawidgetOption $path -text]] + } else { + set validateState [$path:cmd cget -validate] + $path:cmd configure -validate none + $path:cmd delete 0 end + $path:cmd configure -validate $validateState + $path:cmd insert 0 [Widget::getMegawidgetOption $path -text] + } + } + + DragSite::setdrag $path $path Entry::_init_drag_cmd Entry::_end_drag_cmd + DropSite::setdrop $path $path Entry::_over_cmd Entry::_drop_cmd + DynamicHelp::sethelp $path $path + + return $res +} + + +# ------------------------------------------------------------------------------ +# Command Entry::cget +# ------------------------------------------------------------------------------ +proc Entry::cget { path option } { + if { [string equal "-text" $option] } { + return [$path:cmd get] + } + Widget::cget $path $option +} + + +# ------------------------------------------------------------------------------ +# Command Entry::invoke +# ------------------------------------------------------------------------------ +proc Entry::invoke { path } { + if {[llength [set cmd [Widget::getMegawidgetOption $path -command]]]} { + uplevel \#0 $cmd + } +} + + +# ------------------------------------------------------------------------------ +# Command Entry::_path_command +# ------------------------------------------------------------------------------ +proc Entry::_path_command { path cmd larg } { + switch -exact -- $cmd { + configure - cget - invoke { + return [eval [linsert $larg 0 Entry::$cmd $path]] + } + default { + return [eval [linsert $larg 0 $path:cmd $cmd]] + } + } +} + + +# ------------------------------------------------------------------------------ +# Command Entry::_init_drag_cmd +# ------------------------------------------------------------------------------ +proc Entry::_init_drag_cmd { path X Y top } { + variable $path + upvar 0 $path data + + if {[llength [set cmd [Widget::getoption $path -draginitcmd]]]} { + return [uplevel \#0 $cmd [list $path $X $Y $top]] + } + set type [Widget::getoption $path -dragtype] + if { $type == "" } { + set type "TEXT" + } + if { [set drag [$path get]] != "" } { + if { [$path:cmd selection present] } { + set idx [$path:cmd index @[expr {$X-[winfo rootx $path]}]] + set sel0 [$path:cmd index sel.first] + set sel1 [expr {[$path:cmd index sel.last]-1}] + if { $idx >= $sel0 && $idx <= $sel1 } { + set drag [string range $drag $sel0 $sel1] + set data(dragstart) $sel0 + set data(dragend) [expr {$sel1+1}] + if { ![Widget::getoption $path -editable] || + [Widget::getoption $path -state] == "disabled" } { + return [list $type {copy} $drag] + } else { + return [list $type {copy move} $drag] + } + } + } else { + set data(dragstart) 0 + set data(dragend) end + if { ![Widget::getoption $path -editable] || + [Widget::getoption $path -state] == "disabled" } { + return [list $type {copy} $drag] + } else { + return [list $type {copy move} $drag] + } + } + } +} + + +# ------------------------------------------------------------------------------ +# Command Entry::_end_drag_cmd +# ------------------------------------------------------------------------------ +proc Entry::_end_drag_cmd { path target op type dnddata result } { + variable $path + upvar 0 $path data + + if {[llength [set cmd [Widget::getoption $path -dragendcmd]]]} { + return [uplevel \#0 $cmd [list $path $target $op $type $dnddata $result]] + } + if { $result && $op == "move" && $path != $target } { + $path:cmd delete $data(dragstart) $data(dragend) + } +} + + +# ------------------------------------------------------------------------------ +# Command Entry::_drop_cmd +# ------------------------------------------------------------------------------ +proc Entry::_drop_cmd { path source X Y op type dnddata } { + variable $path + upvar 0 $path data + + if { $data(afterid) != "" } { + after cancel $data(afterid) + set data(afterid) "" + } + if {[llength [set cmd [Widget::getoption $path -dropcmd]]]} { + set idx [$path:cmd index @[expr {$X-[winfo rootx $path]}]] + return [uplevel \#0 $cmd [list $path $source $idx $op $type $dnddata]] + } + if { $type == "COLOR" || $type == "FGCOLOR" } { + configure $path -foreground $dnddata + } elseif { $type == "BGCOLOR" } { + configure $path -background $dnddata + } else { + $path:cmd icursor @[expr {$X-[winfo rootx $path]}] + if { $op == "move" && $path == $source } { + $path:cmd delete $data(dragstart) $data(dragend) + } + set sel0 [$path index insert] + $path:cmd insert insert $dnddata + set sel1 [$path index insert] + $path:cmd selection range $sel0 $sel1 + } + return 1 +} + + +# ------------------------------------------------------------------------------ +# Command Entry::_over_cmd +# ------------------------------------------------------------------------------ +proc Entry::_over_cmd { path source event X Y op type dnddata } { + variable $path + upvar 0 $path data + + set x [expr {$X-[winfo rootx $path]}] + if { [string equal $event "leave"] } { + if { [string length $data(afterid)] } { + after cancel $data(afterid) + set data(afterid) "" + } + } elseif { [_auto_scroll $path $x] } { + return 2 + } + + if {[llength [set cmd [Widget::getoption $path -dropovercmd]]]} { + set x [expr {$X-[winfo rootx $path]}] + set idx [$path:cmd index @$x] + set res [uplevel \#0 $cmd [list $path $source $event $idx $op $type $dnddata]] + return $res + } + + if { [string equal $type "COLOR"] || + [string equal $type "FGCOLOR"] || + [string equal $type "BGCOLOR"] } { + DropSite::setcursor based_arrow_down + return 1 + } + if { [Widget::getoption $path -editable] + && [string equal [Widget::getoption $path -state] "normal"] } { + if { ![string equal $event "leave"] } { + $path:cmd selection clear + $path:cmd icursor @$x + DropSite::setcursor based_arrow_down + return 3 + } + } + DropSite::setcursor dot + return 0 +} + + +# ------------------------------------------------------------------------------ +# Command Entry::_auto_scroll +# ------------------------------------------------------------------------------ +proc Entry::_auto_scroll { path x } { + variable $path + upvar 0 $path data + + set xmax [winfo width $path] + if { $x <= 10 && [$path:cmd index @0] > 0 } { + if { $data(afterid) == "" } { + set data(afterid) [after 100 [list Entry::_scroll $path -1 $x $xmax]] + DropSite::setcursor sb_left_arrow + } + return 1 + } else { + if { $x >= $xmax-10 && [$path:cmd index @$xmax] < [$path:cmd index end] } { + if { $data(afterid) == "" } { + set data(afterid) [after 100 [list Entry::_scroll $path 1 $x $xmax]] + DropSite::setcursor sb_right_arrow + } + return 1 + } else { + if { $data(afterid) != "" } { + after cancel $data(afterid) + set data(afterid) "" + } + } + } + return 0 +} + + +# ------------------------------------------------------------------------------ +# Command Entry::_scroll +# ------------------------------------------------------------------------------ +proc Entry::_scroll { path dir x xmax } { + variable $path + upvar 0 $path data + + $path:cmd xview scroll $dir units + $path:cmd icursor @$x + if { ($dir == -1 && [$path:cmd index @0] > 0) || + ($dir == 1 && [$path:cmd index @$xmax] < [$path:cmd index end]) } { + set data(afterid) [after 100 [list Entry::_scroll $path $dir $x $xmax]] + } else { + set data(afterid) "" + DropSite::setcursor dot + } +} + + +# ------------------------------------------------------------------------------ +# Command Entry::_destroy +# ------------------------------------------------------------------------------ +proc Entry::_destroy { path } { + variable $path + upvar 0 $path data + Widget::destroy $path + unset data +} diff --git a/modules/tclsci/tcl/BWidget/font.tcl b/modules/tclsci/tcl/BWidget/font.tcl new file mode 100755 index 000000000..e9238a286 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/font.tcl @@ -0,0 +1,566 @@ +# ---------------------------------------------------------------------------- +# font.tcl +# This file is part of Unifix BWidget Toolkit +# ---------------------------------------------------------------------------- +# Index of commands: +# - SelectFont::create +# - SelectFont::configure +# - SelectFont::cget +# - SelectFont::_draw +# - SelectFont::_destroy +# - SelectFont::_modstyle +# - SelectFont::_update +# - SelectFont::_getfont +# - SelectFont::_init +# ---------------------------------------------------------------------------- + +namespace eval SelectFont { + Widget::define SelectFont font Dialog LabelFrame ScrolledWindow + + Widget::declare SelectFont { + {-title String "Font selection" 0} + {-parent String "" 0} + {-background TkResource "" 0 frame} + + {-type Enum dialog 0 {dialog toolbar}} + {-font TkResource "" 0 label} + {-initialcolor String "" 0} + {-families String "all" 1} + {-querysystem Boolean 1 0} + {-nosizes Boolean 0 1} + {-styles String "bold italic underline overstrike" 1} + {-command String "" 0} + {-sampletext String "Sample Text" 0} + {-bg Synonym -background} + } + + variable _families + variable _styleOff + array set _styleOff [list bold normal italic roman] + variable _sizes {4 5 6 7 8 9 10 11 12 13 14 15 16 \ + 17 18 19 20 21 22 23 24} + + # Set up preset lists of fonts, so the user can avoid the painfully slow + # loadfont process if desired. + if { [string equal $::tcl_platform(platform) "windows"] } { + set presetVariable [list \ + 7x14 \ + Arial \ + {Arial Narrow} \ + {Lucida Sans} \ + {MS Sans Serif} \ + {MS Serif} \ + {Times New Roman} \ + ] + set presetFixed [list \ + 6x13 \ + {Courier New} \ + FixedSys \ + Terminal \ + ] + set presetAll [list \ + 6x13 \ + 7x14 \ + Arial \ + {Arial Narrow} \ + {Courier New} \ + FixedSys \ + {Lucida Sans} \ + {MS Sans Serif} \ + {MS Serif} \ + Terminal \ + {Times New Roman} \ + ] + } else { + set presetVariable [list \ + helvetica \ + lucida \ + lucidabright \ + {times new roman} \ + ] + set presetFixed [list \ + courier \ + fixed \ + {lucida typewriter} \ + screen \ + serif \ + terminal \ + ] + set presetAll [list \ + courier \ + fixed \ + helvetica \ + lucida \ + lucidabright \ + {lucida typewriter} \ + screen \ + serif \ + terminal \ + {times new roman} \ + ] + } + array set _families [list \ + presetvariable $presetVariable \ + presetfixed $presetFixed \ + presetall $presetAll \ + ] + + variable _widget +} + + +# ---------------------------------------------------------------------------- +# Command SelectFont::create +# ---------------------------------------------------------------------------- +proc SelectFont::create { path args } { + variable _families + variable _sizes + variable $path + upvar 0 $path data + + # Initialize the internal rep of the widget options + Widget::init SelectFont "$path#SelectFont" $args + + if { [Widget::getoption "$path#SelectFont" -querysystem] } { + loadfont [Widget::getoption "$path#SelectFont" -families] + } + + set bg [Widget::getoption "$path#SelectFont" -background] + set _styles [Widget::getoption "$path#SelectFont" -styles] + if { [Widget::getoption "$path#SelectFont" -type] == "dialog" } { + Dialog::create $path -modal local -anchor e -default 0 -cancel 1 \ + -background $bg \ + -title [Widget::getoption "$path#SelectFont" -title] \ + -parent [Widget::getoption "$path#SelectFont" -parent] + + set frame [Dialog::getframe $path] + set topf [frame $frame.topf -relief flat -borderwidth 0 -background $bg] + + set labf1 [LabelFrame::create $topf.labf1 -text "Font" -name font \ + -side top -anchor w -relief flat -background $bg] + set sw [ScrolledWindow::create [LabelFrame::getframe $labf1].sw \ + -background $bg] + set lbf [listbox $sw.lb \ + -height 5 -width 25 -exportselection false -selectmode browse] + ScrolledWindow::setwidget $sw $lbf + LabelFrame::configure $labf1 -focus $lbf + if { [Widget::getoption "$path#SelectFont" -querysystem] } { + set fam [Widget::getoption "$path#SelectFont" -families] + } else { + set fam "preset" + append fam [Widget::getoption "$path#SelectFont" -families] + } + eval [list $lbf insert end] $_families($fam) + set script "set [list SelectFont::${path}(family)] \[%W curselection\];\ + SelectFont::_update [list $path]" + bind $lbf <ButtonRelease-1> $script + bind $lbf <space> $script + bind $lbf <1> [list focus %W] + bind $lbf <Up> $script + bind $lbf <Down> $script + pack $sw -fill both -expand yes + + set labf2 [LabelFrame::create $topf.labf2 -text "Size" -name size \ + -side top -anchor w -relief flat -background $bg] + set sw [ScrolledWindow::create [LabelFrame::getframe $labf2].sw \ + -scrollbar vertical -background $bg] + set lbs [listbox $sw.lb \ + -height 5 -width 6 -exportselection false -selectmode browse] + ScrolledWindow::setwidget $sw $lbs + LabelFrame::configure $labf2 -focus $lbs + eval [list $lbs insert end] $_sizes + set script "set [list SelectFont::${path}(size)] \[%W curselection\];\ + SelectFont::_update [list $path]" + bind $lbs <ButtonRelease-1> $script + bind $lbs <space> $script + bind $lbs <1> [list focus %W] + bind $lbs <Up> $script + bind $lbs <Down> $script + pack $sw -fill both -expand yes + + set labf3 [LabelFrame::create $topf.labf3 -text "Style" -name style \ + -side top -anchor w -relief sunken -bd 1 -background $bg] + set subf [LabelFrame::getframe $labf3] + foreach st $_styles { + set name [lindex [BWidget::getname $st] 0] + if { $name == "" } { + set name [string toupper $name 0] + } + checkbutton $subf.$st -text $name \ + -variable SelectFont::$path\($st\) \ + -background $bg \ + -command [list SelectFont::_update $path] + bind $subf.$st <Return> break + pack $subf.$st -anchor w + } + LabelFrame::configure $labf3 -focus $subf.[lindex $_styles 0] + + pack $labf1 -side left -anchor n -fill both -expand yes + if { ![Widget::getoption "$path#SelectFont" -nosizes] } { + pack $labf2 -side left -anchor n -fill both -expand yes -padx 8 + } + pack $labf3 -side left -anchor n -fill both -expand yes + + set botf [frame $frame.botf -width 100 -height 50 \ + -bg white -bd 0 -relief flat \ + -highlightthickness 1 -takefocus 0 \ + -highlightbackground black \ + -highlightcolor black] + + set lab [label $botf.label \ + -background white -foreground black \ + -borderwidth 0 -takefocus 0 -highlightthickness 0 \ + -text [Widget::getoption "$path#SelectFont" -sampletext]] + place $lab -relx 0.5 -rely 0.5 -anchor c + + pack $topf -pady 4 -fill both -expand yes + + if { [Widget::getoption "$path#SelectFont" -initialcolor] != ""} { + set thecolor [Widget::getoption "$path#SelectFont" -initialcolor] + set colf [frame $frame.colf] + + set frc [frame $colf.frame -width 50 -height 20 -bg $thecolor -bd 0 -relief flat\ + -highlightthickness 1 -takefocus 0 \ + -highlightbackground black \ + -highlightcolor black] + + set script "set [list SelectFont::${path}(fontcolor)] \[tk_chooseColor -parent $colf.button -initialcolor \[set [list SelectFont::${path}(fontcolor)]\]\];\ + SelectFont::_update [list $path]" + + set but [button $colf.button -command $script \ + -text "Color..."] + + $lab configure -foreground $thecolor + $frc configure -bg $thecolor + + pack $but -side left + pack $frc -side left -padx 5 + + set data(frc) $frc + set data(fontcolor) $thecolor + + pack $colf -pady 4 -fill x -expand true + + } else { + set data(fontcolor) -1 + } + pack $botf -pady 4 -fill x + + Dialog::add $path -name ok + Dialog::add $path -name cancel + + set data(label) $lab + set data(lbf) $lbf + set data(lbs) $lbs + + _getfont $path + + Widget::create SelectFont $path 0 + + return [_draw $path] + } else { + if { [Widget::getoption "$path#SelectFont" -querysystem] } { + set fams [Widget::getoption "$path#SelectFont" -families] + } else { + set fams "preset" + append fams [Widget::getoption "$path#SelectFont" -families] + } + if {[Widget::theme]} { + ttk::frame $path + set lbf [ttk::combobox $path.font \ + -takefocus 0 -exportselection 0 \ + -values $_families($fams) \ + -textvariable SelectFont::${path}(family) \ + -state readonly] + set lbs [ttk::combobox $path.size \ + -takefocus 0 -exportselection 0 \ + -width 4 \ + -values $_sizes \ + -textvariable SelectFont::${path}(size) \ + -state readonly] + bind $lbf <<ComboboxSelected>> [list SelectFont::_update $path] + bind $lbs <<ComboboxSelected>> [list SelectFont::_update $path] + } else { + frame $path -background $bg + set lbf [ComboBox::create $path.font \ + -highlightthickness 0 -takefocus 0 -background $bg \ + -values $_families($fams) \ + -textvariable SelectFont::$path\(family\) \ + -editable 0 \ + -modifycmd [list SelectFont::_update $path]] + set lbs [ComboBox::create $path.size \ + -highlightthickness 0 -takefocus 0 -background $bg \ + -width 4 \ + -values $_sizes \ + -textvariable SelectFont::$path\(size\) \ + -editable 0 \ + -modifycmd [list SelectFont::_update $path]] + } + bind $path <Destroy> [list SelectFont::_destroy $path] + pack $lbf -side left -anchor w + pack $lbs -side left -anchor w -padx 4 + foreach st $_styles { + if {$::Widget::_theme} { + ttk::checkbutton $path.$st -takefocus 0 \ + -style BWSlim.Toolbutton \ + -image [Bitmap::get $st] \ + -variable SelectFont::${path}($st) \ + -command [list SelectFont::_update $path] + } else { + button $path.$st \ + -highlightthickness 0 -takefocus 0 -padx 0 -pady 0 \ + -background $bg \ + -image [Bitmap::get $st] \ + -command [list SelectFont::_modstyle $path $st] + } + pack $path.$st -side left -anchor w + } + set data(label) "" + set data(lbf) $lbf + set data(lbs) $lbs + _getfont $path + + return [Widget::create SelectFont $path] + } + + return $path +} + + +# ---------------------------------------------------------------------------- +# Command SelectFont::configure +# ---------------------------------------------------------------------------- +proc SelectFont::configure { path args } { + set _styles [Widget::getoption "$path#SelectFont" -styles] + + set res [Widget::configure "$path#SelectFont" $args] + + if { [Widget::hasChanged "$path#SelectFont" -font font] } { + _getfont $path + } + if { [Widget::hasChanged "$path#SelectFont" -background bg] } { + switch -- [Widget::getoption "$path#SelectFont" -type] { + dialog { + Dialog::configure $path -background $bg + set topf [Dialog::getframe $path].topf + $topf configure -background $bg + foreach labf {labf1 labf2} { + LabelFrame::configure $topf.$labf -background $bg + set subf [LabelFrame::getframe $topf.$labf] + ScrolledWindow::configure $subf.sw -background $bg + $subf.sw.lb configure -background $bg + } + LabelFrame::configure $topf.labf3 -background $bg + set subf [LabelFrame::getframe $topf.labf3] + foreach w [winfo children $subf] { + $w configure -background $bg + } + } + toolbar { + $path configure -background $bg + ComboBox::configure $path.font -background $bg + ComboBox::configure $path.size -background $bg + foreach st $_styles { + $path.$st configure -background $bg + } + } + } + } + return $res +} + + +# ---------------------------------------------------------------------------- +# Command SelectFont::cget +# ---------------------------------------------------------------------------- +proc SelectFont::cget { path option } { + return [Widget::cget "$path#SelectFont" $option] +} + + +# ---------------------------------------------------------------------------- +# Command SelectFont::loadfont +# ---------------------------------------------------------------------------- +proc SelectFont::loadfont {{which all}} { + variable _families + + # initialize families + if {![info exists _families(all)]} { + set _families(all) [lsort -dictionary [font families]] + } + if {[regexp {fixed|variable} $which] \ + && ![info exists _families($which)]} { + # initialize families + set _families(fixed) {} + set _families(variable) {} + foreach family $_families(all) { + if { [font metrics [list $family] -fixed] } { + lappend _families(fixed) $family + } else { + lappend _families(variable) $family + } + } + } + return +} + + +# ---------------------------------------------------------------------------- +# Command SelectFont::_draw +# ---------------------------------------------------------------------------- +proc SelectFont::_draw { path } { + variable $path + upvar 0 $path data + + $data(lbf) selection clear 0 end + $data(lbf) selection set $data(family) + $data(lbf) activate $data(family) + $data(lbf) see $data(family) + $data(lbs) selection clear 0 end + $data(lbs) selection set $data(size) + $data(lbs) activate $data(size) + $data(lbs) see $data(size) + _update $path + + if { [Dialog::draw $path] == 0 } { + set result [Widget::getoption "$path#SelectFont" -font] + set color $data(fontcolor) + + if { $color == "" } { + set color #000000 + } + + } else { + set result "" + if {$data(fontcolor) == -1} { + set color -1 + } else { + set color "" + } + } + unset data + Widget::destroy "$path#SelectFont" + destroy $path + if { $color != -1 } { + return [list $result $color] + } else { + return $result + } +} + + +# ---------------------------------------------------------------------------- +# Command SelectFont::_modstyle +# ---------------------------------------------------------------------------- +proc SelectFont::_modstyle { path style } { + variable $path + upvar 0 $path data + + $path.$style configure -relief [expr {$data($style) ? "raised" : "sunken"}] + set data($style) [expr {!$data($style)}] + _update $path +} + + +# ---------------------------------------------------------------------------- +# Command SelectFont::_update +# ---------------------------------------------------------------------------- +proc SelectFont::_update { path } { + variable _families + variable _sizes + variable _styleOff + variable $path + upvar 0 $path data + + set type [Widget::getoption "$path#SelectFont" -type] + set _styles [Widget::getoption "$path#SelectFont" -styles] + if { [Widget::getoption "$path#SelectFont" -querysystem] } { + set fams [Widget::getoption "$path#SelectFont" -families] + } else { + set fams "preset" + append fams [Widget::getoption "$path#SelectFont" -families] + } + if { $type == "dialog" } { + set curs [$path:cmd cget -cursor] + $path:cmd configure -cursor watch + } + if { [Widget::getoption "$path#SelectFont" -type] == "dialog" } { + set font [list [lindex $_families($fams) $data(family)] \ + [lindex $_sizes $data(size)]] + } else { + set font [list $data(family) $data(size)] + } + foreach st $_styles { + if { $data($st) } { + lappend font $st + } elseif {[info exists _styleOff($st)]} { + # This adds the default bold/italic value to a font + #lappend font $_styleOff($st) + } + } + Widget::setoption "$path#SelectFont" -font $font + if { $type == "dialog" } { + $data(label) configure -font $font + $path:cmd configure -cursor $curs + if { ($data(fontcolor) != "") && ($data(fontcolor) != -1) } { + $data(label) configure -foreground $data(fontcolor) + $data(frc) configure -bg $data(fontcolor) + } elseif { $data(fontcolor) == "" } { + #If no color is selected, restore previous one + set data(fontcolor) [$data(label) cget -foreground] + + } + } elseif { [set cmd [Widget::getoption "$path#SelectFont" -command]] != "" } { + uplevel \#0 $cmd + } +} + + +# ---------------------------------------------------------------------------- +# Command SelectFont::_getfont +# ---------------------------------------------------------------------------- +proc SelectFont::_getfont { path } { + variable _families + variable _sizes + variable $path + upvar 0 $path data + + array set font [font actual [Widget::getoption "$path#SelectFont" -font]] + set data(bold) [expr {![string equal $font(-weight) "normal"]}] + set data(italic) [expr {![string equal $font(-slant) "roman"]}] + set data(underline) $font(-underline) + set data(overstrike) $font(-overstrike) + set _styles [Widget::getoption "$path#SelectFont" -styles] + if { [Widget::getoption "$path#SelectFont" -querysystem] } { + set fams [Widget::getoption "$path#SelectFont" -families] + } else { + set fams "preset" + append fams [Widget::getoption "$path#SelectFont" -families] + } + if { [Widget::getoption "$path#SelectFont" -type] == "dialog" } { + set idxf [lsearch $_families($fams) $font(-family)] + set idxs [lsearch $_sizes $font(-size)] + set data(family) [expr {$idxf >= 0 ? $idxf : 0}] + set data(size) [expr {$idxs >= 0 ? $idxs : 0}] + } else { + set data(family) $font(-family) + set data(size) $font(-size) + if {![Widget::theme]} { + foreach st $_styles { + $path.$st configure \ + -relief [expr {$data($st) ? "sunken":"raised"}] + } + } + } +} + + +# ---------------------------------------------------------------------------- +# Command SelectFont::_destroy +# ---------------------------------------------------------------------------- +proc SelectFont::_destroy { path } { + variable $path + upvar 0 $path data + unset data + Widget::destroy "$path#SelectFont" +} diff --git a/modules/tclsci/tcl/BWidget/images/bold.gif b/modules/tclsci/tcl/BWidget/images/bold.gif Binary files differnew file mode 100755 index 000000000..ddfe700d3 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/bold.gif diff --git a/modules/tclsci/tcl/BWidget/images/copy.gif b/modules/tclsci/tcl/BWidget/images/copy.gif Binary files differnew file mode 100755 index 000000000..362e72795 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/copy.gif diff --git a/modules/tclsci/tcl/BWidget/images/cut.gif b/modules/tclsci/tcl/BWidget/images/cut.gif Binary files differnew file mode 100755 index 000000000..988965c07 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/cut.gif diff --git a/modules/tclsci/tcl/BWidget/images/dragfile.gif b/modules/tclsci/tcl/BWidget/images/dragfile.gif Binary files differnew file mode 100755 index 000000000..a04b6db3e --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/dragfile.gif diff --git a/modules/tclsci/tcl/BWidget/images/dragicon.gif b/modules/tclsci/tcl/BWidget/images/dragicon.gif Binary files differnew file mode 100755 index 000000000..6ec0e55eb --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/dragicon.gif diff --git a/modules/tclsci/tcl/BWidget/images/error.gif b/modules/tclsci/tcl/BWidget/images/error.gif Binary files differnew file mode 100755 index 000000000..a4ed2e9d3 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/error.gif diff --git a/modules/tclsci/tcl/BWidget/images/file.gif b/modules/tclsci/tcl/BWidget/images/file.gif Binary files differnew file mode 100755 index 000000000..c64635ce2 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/file.gif diff --git a/modules/tclsci/tcl/BWidget/images/folder.gif b/modules/tclsci/tcl/BWidget/images/folder.gif Binary files differnew file mode 100755 index 000000000..262aed56c --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/folder.gif diff --git a/modules/tclsci/tcl/BWidget/images/hourglass.gif b/modules/tclsci/tcl/BWidget/images/hourglass.gif Binary files differnew file mode 100755 index 000000000..bac625a3e --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/hourglass.gif diff --git a/modules/tclsci/tcl/BWidget/images/info.gif b/modules/tclsci/tcl/BWidget/images/info.gif Binary files differnew file mode 100755 index 000000000..0286c268d --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/info.gif diff --git a/modules/tclsci/tcl/BWidget/images/italic.gif b/modules/tclsci/tcl/BWidget/images/italic.gif Binary files differnew file mode 100755 index 000000000..cf44c94a5 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/italic.gif diff --git a/modules/tclsci/tcl/BWidget/images/minus.xbm b/modules/tclsci/tcl/BWidget/images/minus.xbm new file mode 100755 index 000000000..5b848cd46 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/minus.xbm @@ -0,0 +1,5 @@ +#define minus_width 9 +#define minus_height 9 +static char minus_bits[] = { + 0xff,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x7d,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0xff,0x01}; diff --git a/modules/tclsci/tcl/BWidget/images/new.gif b/modules/tclsci/tcl/BWidget/images/new.gif Binary files differnew file mode 100755 index 000000000..74eb0a5c9 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/new.gif diff --git a/modules/tclsci/tcl/BWidget/images/opcopy.xbm b/modules/tclsci/tcl/BWidget/images/opcopy.xbm new file mode 100755 index 000000000..b4cce8538 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/opcopy.xbm @@ -0,0 +1,5 @@ +#define opcopy_width 11 +#define opcopy_height 11 +static char opcopy_bits[] = { + 0xff,0xff,0x01,0xfc,0x21,0xfc,0x21,0xfc,0x21,0xfc,0xfd,0xfd,0x21,0xfc,0x21, + 0xfc,0x21,0xfc,0x01,0xfc,0xff,0xff}; diff --git a/modules/tclsci/tcl/BWidget/images/open.gif b/modules/tclsci/tcl/BWidget/images/open.gif Binary files differnew file mode 100755 index 000000000..d344541c9 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/open.gif diff --git a/modules/tclsci/tcl/BWidget/images/openfold.gif b/modules/tclsci/tcl/BWidget/images/openfold.gif Binary files differnew file mode 100755 index 000000000..fc8adc589 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/openfold.gif diff --git a/modules/tclsci/tcl/BWidget/images/oplink.xbm b/modules/tclsci/tcl/BWidget/images/oplink.xbm new file mode 100755 index 000000000..cdc3acd65 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/oplink.xbm @@ -0,0 +1,5 @@ +#define oplink_width 11 +#define oplink_height 11 +static char oplink_bits[] = { + 0xff,0xff,0x01,0xfc,0xf1,0xfc,0xe1,0xfc,0xf1,0xfc,0xb9,0xfc,0x19,0xfc,0x09, + 0xfc,0x11,0xfc,0x01,0xfc,0xff,0xff}; diff --git a/modules/tclsci/tcl/BWidget/images/opmove.xbm b/modules/tclsci/tcl/BWidget/images/opmove.xbm new file mode 100755 index 000000000..68f81a8d3 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/opmove.xbm @@ -0,0 +1,5 @@ +#define opmove_width 11 +#define opmove_height 11 +static char opmove_bits[] = { + 0xff,0xff,0x01,0xfc,0x01,0xfc,0x51,0xfc,0x89,0xfc,0xfd,0xfd,0x89,0xfc,0x51, + 0xfc,0x01,0xfc,0x01,0xfc,0xff,0xff}; diff --git a/modules/tclsci/tcl/BWidget/images/overstrike.gif b/modules/tclsci/tcl/BWidget/images/overstrike.gif Binary files differnew file mode 100755 index 000000000..c06413e8f --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/overstrike.gif diff --git a/modules/tclsci/tcl/BWidget/images/palette.gif b/modules/tclsci/tcl/BWidget/images/palette.gif Binary files differnew file mode 100755 index 000000000..b41ff24f4 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/palette.gif diff --git a/modules/tclsci/tcl/BWidget/images/passwd.gif b/modules/tclsci/tcl/BWidget/images/passwd.gif Binary files differnew file mode 100755 index 000000000..7536cd851 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/passwd.gif diff --git a/modules/tclsci/tcl/BWidget/images/paste.gif b/modules/tclsci/tcl/BWidget/images/paste.gif Binary files differnew file mode 100755 index 000000000..f55d355d6 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/paste.gif diff --git a/modules/tclsci/tcl/BWidget/images/plus.xbm b/modules/tclsci/tcl/BWidget/images/plus.xbm new file mode 100755 index 000000000..4b307b875 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/plus.xbm @@ -0,0 +1,5 @@ +#define plus_width 9 +#define plus_height 9 +static char plus_bits[] = { + 0xff,0x01,0x01,0x01,0x11,0x01,0x11,0x01,0x7d,0x01,0x11,0x01,0x11,0x01,0x01, + 0x01,0xff,0x01}; diff --git a/modules/tclsci/tcl/BWidget/images/print.gif b/modules/tclsci/tcl/BWidget/images/print.gif Binary files differnew file mode 100755 index 000000000..d8c750f06 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/print.gif diff --git a/modules/tclsci/tcl/BWidget/images/question.gif b/modules/tclsci/tcl/BWidget/images/question.gif Binary files differnew file mode 100755 index 000000000..c6522fe38 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/question.gif diff --git a/modules/tclsci/tcl/BWidget/images/redo.gif b/modules/tclsci/tcl/BWidget/images/redo.gif Binary files differnew file mode 100755 index 000000000..becbd7cb8 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/redo.gif diff --git a/modules/tclsci/tcl/BWidget/images/save.gif b/modules/tclsci/tcl/BWidget/images/save.gif Binary files differnew file mode 100755 index 000000000..17a747905 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/save.gif diff --git a/modules/tclsci/tcl/BWidget/images/target.xbm b/modules/tclsci/tcl/BWidget/images/target.xbm new file mode 100755 index 000000000..ec2a943d8 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/target.xbm @@ -0,0 +1,9 @@ +#define target_width 24 +#define target_height 24 +static unsigned char target_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0xe0, 0x03, 0x3e, 0xe0, 0x03, 0x3e, 0xe0, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/modules/tclsci/tcl/BWidget/images/underline.gif b/modules/tclsci/tcl/BWidget/images/underline.gif Binary files differnew file mode 100755 index 000000000..53ac2e587 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/underline.gif diff --git a/modules/tclsci/tcl/BWidget/images/undo.gif b/modules/tclsci/tcl/BWidget/images/undo.gif Binary files differnew file mode 100755 index 000000000..6041810b3 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/undo.gif diff --git a/modules/tclsci/tcl/BWidget/images/warning.gif b/modules/tclsci/tcl/BWidget/images/warning.gif Binary files differnew file mode 100755 index 000000000..c78eee99b --- /dev/null +++ b/modules/tclsci/tcl/BWidget/images/warning.gif diff --git a/modules/tclsci/tcl/BWidget/init.tcl b/modules/tclsci/tcl/BWidget/init.tcl new file mode 100755 index 000000000..eba5a16f4 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/init.tcl @@ -0,0 +1,54 @@ +namespace eval Widget {} +proc Widget::_opt_defaults {{prio widgetDefault}} { + if {$::tcl_version >= 8.4} { + set plat [tk windowingsystem] + } else { + set plat $::tcl_platform(platform) + } + switch -exact $plat { + "aqua" { + } + "win32" - + "windows" { + #option add *Listbox.background SystemWindow $prio + option add *ListBox.background SystemWindow $prio + #option add *Button.padY 0 $prio + option add *ButtonBox.padY 0 $prio + option add *Dialog.padY 0 $prio + option add *Dialog.anchor e $prio + } + "x11" - + default { + option add *Scrollbar.width 12 $prio + option add *Scrollbar.borderWidth 1 $prio + option add *Dialog.separator 1 $prio + option add *MainFrame.relief raised $prio + option add *MainFrame.separator none $prio + } + } +} +Widget::_opt_defaults + +# Try to load lang file corresponding to current msgcat locale +proc Widget::_opt_lang {} { + set langfile [file join $::BWIDGET::LIBRARY "lang" "en.rc"] + if {0 != [llength [info commands ::msgcat::mcpreferences]]} { + foreach lang [::msgcat::mcpreferences] { + set l [file join $::BWIDGET::LIBRARY "lang" "$lang.rc"] + if {[file readable $l]} { + set langfile $l + break + } + } + } + option read $langfile +} +Widget::_opt_lang + +## Add a TraverseIn binding to standard Tk widgets to handle some of +## the BWidget-specific things we do. +bind Entry <<TraverseIn>> { %W selection range 0 end; %W icursor end } +bind Spinbox <<TraverseIn>> { %W selection range 0 end; %W icursor end } + +bind all <Key-Tab> { Widget::traverseTo [Widget::focusNext %W] } +bind all <<PrevWindow>> { Widget::traverseTo [Widget::focusPrev %W] } diff --git a/modules/tclsci/tcl/BWidget/label.tcl b/modules/tclsci/tcl/BWidget/label.tcl new file mode 100755 index 000000000..b15ab017a --- /dev/null +++ b/modules/tclsci/tcl/BWidget/label.tcl @@ -0,0 +1,329 @@ +# ------------------------------------------------------------------------------ +# label.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: label.tcl,v 1.10.2.2 2010/11/21 19:35:48 oehhar Exp $ +# ------------------------------------------------------------------------------ +# Index of commands: +# - Label::create +# - Label::configure +# - Label::cget +# - Label::setfocus +# - Label::_drag_cmd +# - Label::_drop_cmd +# - Label::_over_cmd +# ------------------------------------------------------------------------------ + +namespace eval Label { + Widget::define Label label DragSite DropSite DynamicHelp + + if {$::Widget::_theme} { + Widget::tkinclude Label label .l \ + remove { -foreground -text -textvariable -underline -state} + } else { + Widget::tkinclude Label label .l \ + remove { -foreground -text -textvariable -underline } + } + + Widget::declare Label { + {-name String "" 0} + {-text String "" 0} + {-textvariable String "" 0} + {-underline Int -1 0 "%d >= -1"} + {-focus String "" 0} + {-foreground TkResource "" 0 label} + {-disabledforeground TkResource "" 0 button} + {-state Enum normal 0 {normal disabled}} + + {-fg Synonym -foreground} + } + + DynamicHelp::include Label balloon + DragSite::include Label "" 1 + DropSite::include Label { + TEXT {move {}} + IMAGE {move {}} + BITMAP {move {}} + FGCOLOR {move {}} + BGCOLOR {move {}} + COLOR {move {}} + } + + Widget::syncoptions Label "" .l {-text {} -underline {}} + + bind BwLabel <FocusIn> [list Label::setfocus %W] + bind BwLabel <Destroy> [list Label::_destroy %W] +} + + +# ------------------------------------------------------------------------------ +# Command Label::create +# ------------------------------------------------------------------------------ +proc Label::create { path args } { + array set maps [list Label {} .l {}] + array set maps [Widget::parseArgs Label $args] + frame $path -class Label -borderwidth 0 -highlightthickness 0 -relief flat -padx 0 -pady 0 + Widget::initFromODB Label $path $maps(Label) + + if {$::Widget::_theme} { + eval [list ttk::label $path.l] $maps(.l) + } else { + eval [list label $path.l] $maps(.l) + } + + if {$::Widget::_theme} { + if { [Widget::cget $path -state] != "normal" } { + $path.l state disabled + } + } else { + if { [Widget::cget $path -state] == "normal" } { + set fg [Widget::cget $path -foreground] + } else { + set fg [Widget::cget $path -disabledforeground] + } + $path.l configure -foreground $fg + } + + set var [Widget::cget $path -textvariable] + if { $var == "" && + [Widget::cget $path -image] == "" && + ($::Widget::_theme || [Widget::cget $path -bitmap] == "")} { + set desc [BWidget::getname [Widget::cget $path -name]] + if { $desc != "" } { + set text [lindex $desc 0] + set under [lindex $desc 1] + } else { + set text [Widget::cget $path -text] + set under [Widget::cget $path -underline] + } + } else { + set under -1 + set text "" + } + + $path.l configure -text $text -textvariable $var \ + -underline $under + + set accel [string tolower [string index $text $under]] + if { $accel != "" } { + bind [winfo toplevel $path] <Alt-$accel> "Label::setfocus $path" + } + + bindtags $path [list BwLabel [winfo toplevel $path] all] + bindtags $path.l [list $path.l $path Label [winfo toplevel $path] all] + pack $path.l -expand yes -fill both + + set dragendcmd [Widget::cget $path -dragendcmd] + DragSite::setdrag $path $path.l Label::_init_drag_cmd $dragendcmd 1 + DropSite::setdrop $path $path.l Label::_over_cmd Label::_drop_cmd 1 + DynamicHelp::sethelp $path $path.l 1 + + return [Widget::create Label $path] +} + + +# ------------------------------------------------------------------------------ +# Command Label::configure +# ------------------------------------------------------------------------------ +proc Label::configure { path args } { + set oldunder [$path.l cget -underline] + if { $oldunder != -1 } { + set oldaccel [string tolower [string index [$path.l cget -text] $oldunder]] + } else { + set oldaccel "" + } + set res [Widget::configure $path $args] + + set cfg [Widget::hasChanged $path -foreground fg] + set cst [Widget::hasChanged $path -state state] + + if {$::Widget::_theme} { + if { $cfg } { + $path.l configure -fg $fg + } + if { $cst } { + if { $state == "normal" } { + $path.l state !disabled + } else { + $path.l state disabled + } + } + } else { + set cdfg [Widget::hasChanged $path -disabledforeground dfg] + if { $cst || $cfg || $cdfg } { + if { $state == "normal" } { + $path.l configure -fg $fg + } else { + $path.l configure -fg $dfg + } + } + } + + set cv [Widget::hasChanged $path -textvariable var] + set cb [Widget::hasChanged $path -image img] + if {$::Widget::_theme} { + set ci 0 + set bmp "" + } else { + set ci [Widget::hasChanged $path -bitmap bmp] + } + set cn [Widget::hasChanged $path -name name] + set ct [Widget::hasChanged $path -text text] + set cu [Widget::hasChanged $path -underline under] + + if { $cv || $cb || $ci || $cn || $ct || $cu } { + if { $var == "" && $img == "" && $bmp == "" } { + set desc [BWidget::getname $name] + if { $desc != "" } { + set text [lindex $desc 0] + set under [lindex $desc 1] + } + } else { + set under -1 + set text "" + } + set top [winfo toplevel $path] + if { $oldaccel != "" } { + bind $top <Alt-$oldaccel> {} + } + set accel [string tolower [string index $text $under]] + if { $accel != "" } { + bind $top <Alt-$accel> [list Label::setfocus $path] + } + $path.l configure -text $text -underline $under -textvariable $var + } + + set force [Widget::hasChanged $path -dragendcmd dragend] + DragSite::setdrag $path $path.l Label::_init_drag_cmd $dragend $force + DropSite::setdrop $path $path.l Label::_over_cmd Label::_drop_cmd + DynamicHelp::sethelp $path $path.l + + return $res +} + + +# ------------------------------------------------------------------------------ +# Command Label::cget +# ------------------------------------------------------------------------------ +proc Label::cget { path option } { + return [Widget::cget $path $option] +} + + +# ---------------------------------------------------------------------------- +# Command Label::identify +# ---------------------------------------------------------------------------- +proc Label::identify { path args } { + eval $path.l identify $args +} + + +# ---------------------------------------------------------------------------- +# Command Label::instate +# ---------------------------------------------------------------------------- +proc Label::instate { path args } { + eval $path.l instate $args +} + + +# ---------------------------------------------------------------------------- +# Command Label::state +# ---------------------------------------------------------------------------- +proc Label::state { path args } { + eval $path.l state $args +} + + +# ------------------------------------------------------------------------------ +# Command Label::setfocus +# ------------------------------------------------------------------------------ +proc Label::setfocus { path } { + if { [string equal [Widget::cget $path -state] "normal"] } { + set w [Widget::cget $path -focus] + if { [winfo exists $w] && [Widget::focusOK $w] } { + focus $w + } + } +} + + +# ------------------------------------------------------------------------------ +# Command Label::_init_drag_cmd +# ------------------------------------------------------------------------------ +proc Label::_init_drag_cmd { path X Y top } { + set path [winfo parent $path] + if { [set cmd [Widget::cget $path -draginitcmd]] != "" } { + return [uplevel \#0 $cmd [list $path $X $Y $top]] + } + if { [set data [$path.l cget -image]] != "" } { + set type "IMAGE" + pack [label $top.l -image $data] + } elseif { [set data [$path.l cget -bitmap]] != "" } { + set type "BITMAP" + pack [label $top.l -bitmap $data] + } else { + set data [$path.l cget -text] + set type "TEXT" + } + set usertype [Widget::getoption $path -dragtype] + if { $usertype != "" } { + set type $usertype + } + return [list $type {copy} $data] +} + + +# ------------------------------------------------------------------------------ +# Command Label::_drop_cmd +# ------------------------------------------------------------------------------ +proc Label::_drop_cmd { path source X Y op type data } { + set path [winfo parent $path] + if { [set cmd [Widget::cget $path -dropcmd]] != "" } { + return [uplevel \#0 $cmd [list $path $source $X $Y $op $type $data]] + } + if { $type == "COLOR" || $type == "FGCOLOR" } { + configure $path -foreground $data + } elseif { $type == "BGCOLOR" } { + configure $path -background $data + } else { + set text "" + set image "" + set bitmap "" + switch -- $type { + IMAGE {set image $data} + BITMAP {set bitmap $data} + default { + set text $data + if { [set var [$path.l cget -textvariable]] != "" } { + configure $path -image "" -bitmap "" + GlobalVar::setvar $var $data + return + } + } + } + configure $path -text $text -image $image -bitmap $bitmap + } + return 1 +} + + +# ------------------------------------------------------------------------------ +# Command Label::_over_cmd +# ------------------------------------------------------------------------------ +proc Label::_over_cmd { path source event X Y op type data } { + set path [winfo parent $path] + if { [set cmd [Widget::cget $path -dropovercmd]] != "" } { + return [uplevel \#0 $cmd [list $path $source $event $X $Y $op $type $data]] + } + if { [Widget::getoption $path -state] == "normal" || + $type == "COLOR" || $type == "FGCOLOR" || $type == "BGCOLOR" } { + DropSite::setcursor based_arrow_down + return 1 + } + DropSite::setcursor dot + return 0 +} + + +proc Label::_destroy { path } { + Widget::destroy $path +} diff --git a/modules/tclsci/tcl/BWidget/labelentry.tcl b/modules/tclsci/tcl/BWidget/labelentry.tcl new file mode 100755 index 000000000..0e1718c6d --- /dev/null +++ b/modules/tclsci/tcl/BWidget/labelentry.tcl @@ -0,0 +1,100 @@ +# ------------------------------------------------------------------------------ +# labelentry.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: labelentry.tcl,v 1.6 2003/10/20 21:23:52 damonc Exp $ +# ------------------------------------------------------------------------------ +# Index of commands: +# - LabelEntry::create +# - LabelEntry::configure +# - LabelEntry::cget +# - LabelEntry::bind +# ------------------------------------------------------------------------------ + +namespace eval LabelEntry { + Widget::define LabelEntry labelentry Entry LabelFrame + + Widget::bwinclude LabelEntry LabelFrame .labf \ + remove {-relief -borderwidth -focus} \ + rename {-text -label} \ + prefix {label -justify -width -anchor -height -font -textvariable} + + Widget::bwinclude LabelEntry Entry .e \ + remove {-fg -bg} \ + rename {-foreground -entryfg -background -entrybg} + + Widget::addmap LabelEntry "" :cmd {-background {}} + + Widget::syncoptions LabelEntry Entry .e {-text {}} + Widget::syncoptions LabelEntry LabelFrame .labf {-label -text -underline {}} + + ::bind BwLabelEntry <FocusIn> [list focus %W.labf] + ::bind BwLabelEntry <Destroy> [list LabelEntry::_destroy %W] +} + + +# ------------------------------------------------------------------------------ +# Command LabelEntry::create +# ------------------------------------------------------------------------------ +proc LabelEntry::create { path args } { + array set maps [list LabelEntry {} :cmd {} .labf {} .e {}] + array set maps [Widget::parseArgs LabelEntry $args] + + eval [list frame $path] $maps(:cmd) -class LabelEntry \ + -relief flat -bd 0 -highlightthickness 0 -takefocus 0 + Widget::initFromODB LabelEntry $path $maps(LabelEntry) + + set labf [eval [list LabelFrame::create $path.labf] $maps(.labf) \ + [list -relief flat -borderwidth 0 -focus $path.e]] + set subf [LabelFrame::getframe $labf] + set entry [eval [list Entry::create $path.e] $maps(.e)] + + pack $entry -in $subf -fill both -expand yes + pack $labf -fill both -expand yes + + bindtags $path [list $path BwLabelEntry [winfo toplevel $path] all] + + return [Widget::create LabelEntry $path] +} + + +# ------------------------------------------------------------------------------ +# Command LabelEntry::configure +# ------------------------------------------------------------------------------ +proc LabelEntry::configure { path args } { + return [Widget::configure $path $args] +} + + +# ------------------------------------------------------------------------------ +# Command LabelEntry::cget +# ------------------------------------------------------------------------------ +proc LabelEntry::cget { path option } { + return [Widget::cget $path $option] +} + + +# ------------------------------------------------------------------------------ +# Command LabelEntry::bind +# ------------------------------------------------------------------------------ +proc LabelEntry::bind { path args } { + return [eval [list ::bind $path.e] $args] +} + + +#------------------------------------------------------------------------------ +# Command LabelEntry::_path_command +#------------------------------------------------------------------------------ +proc LabelEntry::_path_command { path cmd larg } { + if { [string equal $cmd "configure"] || + [string equal $cmd "cget"] || + [string equal $cmd "bind"] } { + return [eval [list LabelEntry::$cmd $path] $larg] + } else { + return [eval [list $path.e:cmd $cmd] $larg] + } +} + + +proc LabelEntry::_destroy { path } { + Widget::destroy $path +} diff --git a/modules/tclsci/tcl/BWidget/labelframe.tcl b/modules/tclsci/tcl/BWidget/labelframe.tcl new file mode 100755 index 000000000..7769ffdb2 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/labelframe.tcl @@ -0,0 +1,160 @@ +# ------------------------------------------------------------------------------ +# labelframe.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: labelframe.tcl,v 1.6 2003/10/20 21:23:52 damonc Exp $ +# ------------------------------------------------------------------------------ +# Index of commands: +# - LabelFrame::create +# - LabelFrame::getframe +# - LabelFrame::configure +# - LabelFrame::cget +# - LabelFrame::align +# ------------------------------------------------------------------------------ + +namespace eval LabelFrame { + Widget::define LabelFrame labelframe Label + + Widget::bwinclude LabelFrame Label .l \ + remove { + -highlightthickness -highlightcolor -highlightbackground + -takefocus -relief -borderwidth + -cursor + -dragenabled -draginitcmd -dragendcmd -dragevent -dragtype + -dropenabled -droptypes -dropovercmd -dropcmd} \ + initialize {-anchor w} + + Widget::declare LabelFrame { + {-relief TkResource flat 0 frame} + {-borderwidth TkResource 0 0 frame} + {-side Enum left 1 {left right top bottom}} + {-bd Synonym -borderwidth} + } + + Widget::addmap LabelFrame "" :cmd {-background {}} + Widget::addmap LabelFrame "" .f {-background {} -relief {} -borderwidth {}} + + Widget::syncoptions LabelFrame Label .l {-text {} -underline {}} + + bind BwLabelFrame <FocusIn> [list Label::setfocus %W.l] + bind BwLabelFrame <Destroy> [list LabelFrame::_destroy %W] +} + + +# ---------------------------------------------------------------------------- +# Command LabelFrame::create +# ---------------------------------------------------------------------------- +proc LabelFrame::create { path args } { + Widget::init LabelFrame $path $args + + set path [eval [list frame $path] [Widget::subcget $path :cmd] \ + -relief flat -bd 0 -takefocus 0 -highlightthickness 0 \ + -class LabelFrame] + + set label [eval [list Label::create $path.l] [Widget::subcget $path .l] \ + -takefocus 0 -highlightthickness 0 -relief flat \ + -borderwidth 0 -dropenabled 0 -dragenabled 0] + set frame [eval [list frame $path.f] [Widget::subcget $path .f] \ + -highlightthickness 0 -takefocus 0] + + switch [Widget::getoption $path -side] { + left {set packopt "-side left"} + right {set packopt "-side right"} + top {set packopt "-side top -fill x"} + bottom {set packopt "-side bottom -fill x"} + } + + eval [list pack $label] $packopt + pack $frame -fill both -expand yes + + bindtags $path [list $path BwLabelFrame [winfo toplevel $path] all] + + return [Widget::create LabelFrame $path] +} + + +# ---------------------------------------------------------------------------- +# Command LabelFrame::getframe +# ---------------------------------------------------------------------------- +proc LabelFrame::getframe { path } { + return $path.f +} + + +# ---------------------------------------------------------------------------- +# Command LabelFrame::configure +# ---------------------------------------------------------------------------- +proc LabelFrame::configure { path args } { + return [Widget::configure $path $args] +} + + +# ---------------------------------------------------------------------------- +# Command LabelFrame::cget +# ---------------------------------------------------------------------------- +proc LabelFrame::cget { path option } { + return [Widget::cget $path $option] +} + + +# ---------------------------------------------------------------------------- +# Command LabelFrame::align +# This command align label of all widget given by args of class LabelFrame +# (or "derived") by setting their width to the max one +1 +# ---------------------------------------------------------------------------- +proc LabelFrame::align { args } { + set maxlen 0 + set wlist {} + foreach wl $args { + foreach w $wl { + if { ![info exists Widget::_class($w)] } { + continue + } + set class $Widget::_class($w) + if { [string equal $class "LabelFrame"] } { + set textopt -text + set widthopt -width + } else { + upvar 0 Widget::${class}::map classmap + set textopt "" + set widthopt "" + set notdone 2 + foreach {option lmap} [array get classmap] { + foreach {subpath subclass realopt} $lmap { + if { [string equal $subclass "LabelFrame"] } { + if { [string equal $realopt "-text"] } { + set textopt $option + incr notdone -1 + break + } + if { [string equal $realopt "-width"] } { + set widthopt $option + incr notdone -1 + break + } + } + } + if { !$notdone } { + break + } + } + if { $notdone } { + continue + } + } + set len [string length [$w cget $textopt]] + if { $len > $maxlen } { + set maxlen $len + } + lappend wlist $w $widthopt + } + } + incr maxlen + foreach {w widthopt} $wlist { + $w configure $widthopt $maxlen + } +} + + +proc LabelFrame::_destroy { path } { + Widget::destroy $path +} diff --git a/modules/tclsci/tcl/BWidget/lang/da.rc b/modules/tclsci/tcl/BWidget/lang/da.rc new file mode 100755 index 000000000..09e9fdde5 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/lang/da.rc @@ -0,0 +1,52 @@ +! ----------------------------------------------------------------------------- +! da.rc +! This file is part of Unifix BWidget Toolkit +! Definition of Danish resources +! ----------------------------------------------------------------------------- + + +! --- symbolic names of buttons ----------------------------------------------- + +*abortName: &Annullér +*retryName: P&røv igen +*ignoreName: &Ignorer +*okName: &OK +*cancelName: &Cancel +*yesName: &Ja +*noName: &Nej + + +! --- symbolic names of label of SelectFont dialog ---------------------------- + +*boldName: Fed +*italicName: Kursiv +*underlineName: Understreg +*overstrikeName: Overstreg +*fontName: &Font +*sizeName: &Størrelse +*styleName: St&il + +! --- symbolic names of label of PasswdDlg dialog ----------------------------- + +*loginName: &Brugernavn +*passwordName: &Password + + +! --- resource for SelectFont dialog ------------------------------------------ + +*SelectFont.title: Font-valg +*SelectFont.sampletext: Eksempeltekst æøå + + +! --- resource for MessageDlg dialog ------------------------------------------ + +*MessageDlg.noneTitle: Besked +*MessageDlg.infoTitle: Information +*MessageDlg.questionTitle: Spørgsmål +*MessageDlg.warningTitle: Advarsel +*MessageDlg.errorTitle: Fejl + + +! --- resource for PasswdDlg dialog ------------------------------------------- + +*PasswdDlg.title: Indtast brugernavn og password diff --git a/modules/tclsci/tcl/BWidget/lang/de.rc b/modules/tclsci/tcl/BWidget/lang/de.rc new file mode 100755 index 000000000..541e9eda7 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/lang/de.rc @@ -0,0 +1,52 @@ +! ------------------------------------------------------------------------------ +! de.rc +! This file is part of Unifix BWidget Toolkit +! Definition of german resources +! ------------------------------------------------------------------------------ + + +! --- symbolic names of buttons ------------------------------------------------ + +*abortName: &Abbrechen +*retryName: &Wiederholen +*ignoreName: &Ignorieren +*okName: &OK +*cancelName: &Abbrechen +*yesName: &Ja +*noName: &Nein + + +! --- symbolic names of label of SelectFont dialog ---------------------------- + +*boldName: Fett +*italicName: Kursiv +*underlineName: Unterstrichen +*overstrikeName: Durchgestrichen +*fontName: &Schriftart +*sizeName: S&chriftgrad +*styleName: Sc&hriftschnitt + +! --- symbolic names of label of PasswdDlg dialog ----------------------------- + +*loginName: &Login +*passwordName: &Password + + +! --- resource for SelectFont dialog ------------------------------------------ + +*SelectFont.title: Schrift Auswahl +*SelectFont.sampletext: Beispieltext + + +! --- resource for MessageDlg dialog ------------------------------------------ + +*MessageDlg.noneTitle: Meldung +*MessageDlg.infoTitle: Hinweis +*MessageDlg.questionTitle: Frage +*MessageDlg.warningTitle: Warnung +*MessageDlg.errorTitle: Fehler + + +! --- resource for PasswdDlg dialog ------------------------------------------- + +*PasswdDlg.title: Enter login and password diff --git a/modules/tclsci/tcl/BWidget/lang/en.rc b/modules/tclsci/tcl/BWidget/lang/en.rc new file mode 100755 index 000000000..760f07b82 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/lang/en.rc @@ -0,0 +1,52 @@ +! ------------------------------------------------------------------------------ +! en.rc +! This file is part of Unifix BWidget Toolkit +! Definition of english resources +! ------------------------------------------------------------------------------ + + +! --- symbolic names of buttons ------------------------------------------------ + +*abortName: &Abort +*retryName: &Retry +*ignoreName: &Ignore +*okName: &OK +*cancelName: &Cancel +*yesName: &Yes +*noName: &No + + +! --- symbolic names of label of SelectFont dialog ---------------------------- + +*boldName: Bold +*italicName: Italic +*underlineName: Underline +*overstrikeName: Overstrike +*fontName: &Font +*sizeName: &Size +*styleName: St&yle + + +! --- symbolic names of label of PasswdDlg dialog ----------------------------- + +*loginName: &Login +*passwordName: &Password + + +! --- resource for SelectFont dialog ------------------------------------------ + +*SelectFont.title: Font selection +*SelectFont.sampletext: Sample text + + +! --- resource for MessageDlg dialog ------------------------------------------ + +*MessageDlg.noneTitle: Message +*MessageDlg.infoTitle: Information +*MessageDlg.questionTitle: Question +*MessageDlg.warningTitle: Warning +*MessageDlg.errorTitle: Error + +! --- resource for PasswdDlg dialog ------------------------------------------- + +*PasswdDlg.title: Enter login and password diff --git a/modules/tclsci/tcl/BWidget/lang/es.rc b/modules/tclsci/tcl/BWidget/lang/es.rc new file mode 100755 index 000000000..65e589705 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/lang/es.rc @@ -0,0 +1,53 @@ +! ------------------------------------------------------------------------------ +! es.rc +! This file is part of Unifix BWidget Toolkit +! Definition of spanish resources +! daniel@rawbyte.com +! ------------------------------------------------------------------------------ + + +! --- symbolic names of buttons ------------------------------------------------ + +*abortName: A&bortar +*retryName: &Reintentar +*ignoreName: &Ignorar +*okName: &OK +*cancelName: &Anular +*yesName: &Sí +*noName: &No + +! --- symbolic names of label of SelectFont dialog ---------------------------- + +*boldName: &Negrita +*italicName: &Cursiva +*underlineName: &Subrayado +*overstrikeName: &Tachado +*fontName: &Fuente +*sizeName: &Tamaño +*styleName: &Estilo + + +! --- symbolic names of label of PasswdDlg dialog ----------------------------- + +*loginName: Nombre de &usuario +*passwordName: &Contraseña + +! --- resource for SelectFont dialog ------------------------------------------ + +*SelectFont.title: Selección de fuente +*SelectFont.sampletext: Texto de Ejemplo + + +! --- resource for MessageDlg dialog ------------------------------------------ + +*MessageDlg.noneTitle: Indicación +*MessageDlg.infoTitle: Información +*MessageDlg.questionTitle: Pregunta +*MessageDlg.warningTitle: Atención +*MessageDlg.errorTitle: Error + + +! --- resource for PasswdDlg dialog ------------------------------------------- + +*PasswdDlg.title: Introduzca su nombre de usuario y contraseña + diff --git a/modules/tclsci/tcl/BWidget/lang/fr.rc b/modules/tclsci/tcl/BWidget/lang/fr.rc new file mode 100755 index 000000000..03edeb72a --- /dev/null +++ b/modules/tclsci/tcl/BWidget/lang/fr.rc @@ -0,0 +1,52 @@ +! ------------------------------------------------------------------------------ +! fr.rc +! This file is part of Unifix BWidget Toolkit +! Definition of french resources +! ------------------------------------------------------------------------------ + + +! --- symbolic names of buttons ------------------------------------------------ + +*abortName: A&bandonner +*retryName: &Réessayer +*ignoreName: &Ignorer +*okName: &OK +*cancelName: &Annuler +*yesName: &Oui +*noName: &Non + +! --- symbolic names of label of SelectFont dialog ---------------------------- + +*boldName: &Gras +*italicName: &Italique +*underlineName: &Souligné +*overstrikeName: &Barré +*fontName: &Police +*sizeName: &Taille +*styleName: St&yle + + +! --- symbolic names of label of PasswdDlg dialog ----------------------------- + +*loginName: Nom de l'&utilisateur +*passwordName: Mot de &passe + + +! --- resource for SelectFont dialog ------------------------------------------ + +*SelectFont.title: Sélection d'une police +*SelectFont.sampletext: Texte d'exemple + + +! --- resource for MessageDlg dialog ------------------------------------------ + +*MessageDlg.noneTitle: Message +*MessageDlg.infoTitle: Information +*MessageDlg.questionTitle: Question +*MessageDlg.warningTitle: Attention +*MessageDlg.errorTitle: Erreur + + +! --- resource for PasswdDlg dialog ------------------------------------------- + +*PasswdDlg.title: Entrez le login et le mot de passe diff --git a/modules/tclsci/tcl/BWidget/lang/hu.rc b/modules/tclsci/tcl/BWidget/lang/hu.rc new file mode 100755 index 000000000..806b6555b --- /dev/null +++ b/modules/tclsci/tcl/BWidget/lang/hu.rc @@ -0,0 +1,52 @@ +! ------------------------------------------------------------------------------ +! hu.rc +! This file is part of Unifix BWidget Toolkit +! Definition of english resources +! ------------------------------------------------------------------------------ + + +! --- symbolic names of buttons ------------------------------------------------ + +*abortName: &MegszakÃtás +*retryName: Új&ra +*ignoreName: &Kihagyás +*okName: &OK +*cancelName: Még&sem +*yesName: &Igen +*noName: &Nem + + +! --- symbolic names of label of SelectFont dialog ---------------------------- + +*boldName: Félkövér +*italicName: DÅ‘lt +*underlineName: Aláhúzott +*overstrikeName: FelülÃrás +*fontName: &BetűtÃpus +*sizeName: &Méret +*styleName: S&tÃlus + + +! --- symbolic names of label of PasswdDlg dialog ----------------------------- + +*loginName: &Felhasználónév +*passwordName: &Jelszó + + +! --- resource for SelectFont dialog ------------------------------------------ + +*SelectFont.title: BetűtÃpus kiválasztása +*SelectFont.sampletext: Példaszöveg + + +! --- resource for MessageDlg dialog ------------------------------------------ + +*MessageDlg.noneTitle: Ãœzenet +*MessageDlg.infoTitle: Információ +*MessageDlg.questionTitle: Kérdés +*MessageDlg.warningTitle: Figyelmeztetés +*MessageDlg.errorTitle: Hiba + +! --- resource for PasswdDlg dialog ------------------------------------------- + +*PasswdDlg.title: Add meg a felhasználónevet és a jelszót diff --git a/modules/tclsci/tcl/BWidget/lang/nl.rc b/modules/tclsci/tcl/BWidget/lang/nl.rc new file mode 100755 index 000000000..fc5a22581 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/lang/nl.rc @@ -0,0 +1,52 @@ +! ------------------------------------------------------------------------------ +! nl.rc +! This file is part of Unifix BWidget Toolkit +! Definition of Dutch resources +! ------------------------------------------------------------------------------ + + +! --- symbolic names of buttons ------------------------------------------------ + +*abortName: Af&breken +*retryName: Opnie&uw proberen +*ignoreName: N&egeren +*okName: &OK +*cancelName: &Annuleren +*yesName: &Ja +*noName: &Nee + + +! --- symbolic names of label of SelectFont dialog ---------------------------- + +*boldName: Vet +*italicName: Cursief +*underlineName: Onderstrepen +*overstrikeName: Doorhalen +*fontName: &Lettertype +*sizeName: &Grootte +*styleName: &Stijl + + +! --- symbolic names of label of PasswdDlg dialog ----------------------------- + +*loginName: &Inlognaam +*passwordName: &Wachtwoord + + +! --- resource for SelectFont dialog ------------------------------------------ + +*SelectFont.title: Lettertypeselectie +*SelectFont.sampletext: Voorbeeldtekst + + +! --- resource for MessageDlg dialog ------------------------------------------ + +*MessageDlg.noneTitle: Bericht +*MessageDlg.infoTitle: Informatie +*MessageDlg.questionTitle: Vraag +*MessageDlg.warningTitle: Waarschuwing +*MessageDlg.errorTitle: Fout + +! --- resource for PasswdDlg dialog ------------------------------------------- + +*PasswdDlg.title: Voer inlognaam en wachtwoord in diff --git a/modules/tclsci/tcl/BWidget/lang/no.rc b/modules/tclsci/tcl/BWidget/lang/no.rc new file mode 100755 index 000000000..8ba8558f6 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/lang/no.rc @@ -0,0 +1,52 @@ +! ------------------------------------------------------------------------------
+! no.rc
+! This file is part of Unifix BWidget Toolkit
+! Definition of norwegian resources
+! ------------------------------------------------------------------------------
+
+
+! --- symbolic names of buttons ------------------------------------------------
+
+*abortName: &Om
+*retryName: &Prøv igjen
+*ignoreName: &Ignore
+*okName: &OK
+*cancelName: &Avbryt
+*yesName: &Ja
+*noName: &Nei
+
+
+! --- symbolic names of label of SelectFont dialog ----------------------------
+
+*boldName: Halvfet
+*italicName: Kursiv
+*underlineName: Understreking
+*overstrikeName: Overstryke
+*fontName: &Skrift
+*sizeName: &Størrelse
+*styleName: St&il
+
+
+! --- symbolic names of label of PasswdDlg dialog -----------------------------
+
+*loginName: &Logg inn
+*passwordName: &Passord
+
+
+! --- resource for SelectFont dialog ------------------------------------------
+
+*SelectFont.title: Skriftvalg
+*SelectFont.sampletext: Prøve tekst
+
+
+! --- resource for MessageDlg dialog ------------------------------------------
+
+*MessageDlg.noneTitle: Melding
+*MessageDlg.infoTitle: Informasjon
+*MessageDlg.questionTitle: Spørsmål
+*MessageDlg.warningTitle: Advarsel
+*MessageDlg.errorTitle: Feil
+
+! --- resource for PasswdDlg dialog -------------------------------------------
+
+*PasswdDlg.title: Skriv inn logginn og passord
diff --git a/modules/tclsci/tcl/BWidget/lang/pl.rc b/modules/tclsci/tcl/BWidget/lang/pl.rc new file mode 100755 index 000000000..887b0f9b1 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/lang/pl.rc @@ -0,0 +1,104 @@ +! ------------------------------------------------------------------------------ + +! pl.rc + +! This file is part of Unifix BWidget Toolkit + +! Definition of english resources + +! ------------------------------------------------------------------------------ + + + + + +! --- symbolic names of buttons ------------------------------------------------ + + + +*abortName: &Porzuć + +*retryName: P&onów + +*ignoreName: &Ignoruj + +*okName: &OK + +*cancelName: &Anyluj + +*yesName: &Tak + +*noName: &Nie + + + + + +! --- symbolic names of label of SelectFont dialog ---------------------------- + + + +*boldName: Pogrubiona + +*italicName: Kursywa + +*underlineName: Podkreślenie + +*overstrikeName: Przekreślenie + +*fontName: &Czcionka: + +*sizeName: &Rozmiar: + +*styleName: St&yl czcionki: + + + + + +! --- symbolic names of label of PasswdDlg dialog ----------------------------- + + + +*loginName: &Login + +*passwordName: &Hasło + + + + + +! --- resource for SelectFont dialog ------------------------------------------ + + + +*SelectFont.title: Wybór czcionki + +*SelectFont.sampletext: Przykładowy tekst + + + + + +! --- resource for MessageDlg dialog ------------------------------------------ + + + +*MessageDlg.noneTitle: Wiadomość + +*MessageDlg.infoTitle: Informacja + +*MessageDlg.questionTitle: Pytanie + +*MessageDlg.warningTitle: Ostrzeżenie + +*MessageDlg.errorTitle: Błąd + + + +! --- resource for PasswdDlg dialog ------------------------------------------- + + + +*PasswdDlg.title: Wpisz login i hasło + diff --git a/modules/tclsci/tcl/BWidget/listbox.tcl b/modules/tclsci/tcl/BWidget/listbox.tcl new file mode 100755 index 000000000..2e454095d --- /dev/null +++ b/modules/tclsci/tcl/BWidget/listbox.tcl @@ -0,0 +1,1726 @@ +# ---------------------------------------------------------------------------- +# listbox.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: listbox.tcl,v 1.29.2.3 2010/05/12 08:12:34 oehhar Exp $ +# ---------------------------------------------------------------------------- +# Index of commands: +# - ListBox::create +# - ListBox::configure +# - ListBox::cget +# - ListBox::insert +# - ListBox::itemconfigure +# - ListBox::itemcget +# - ListBox::bindText +# - ListBox::bindImage +# - ListBox::delete +# - ListBox::move +# - ListBox::reorder +# - ListBox::selection +# - ListBox::exists +# - ListBox::index +# - ListBox::item - deprecated +# - ListBox::items +# - ListBox::see +# - ListBox::edit +# - ListBox::xview +# - ListBox::yview +# - ListBox::_update_edit_size +# - ListBox::_destroy +# - ListBox::_see +# - ListBox::_update_scrollregion +# - ListBox::_draw_item +# - ListBox::_redraw_items +# - ListBox::_redraw_selection +# - ListBox::_redraw_listbox +# - ListBox::_redraw_idle +# - ListBox::_resize +# - ListBox::_init_drag_cmd +# - ListBox::_drop_cmd +# - ListBox::_over_cmd +# - ListBox::_auto_scroll +# - ListBox::_scroll +# ---------------------------------------------------------------------------- + +namespace eval ListBox { + Widget::define ListBox listbox DragSite DropSite DynamicHelp + + namespace eval Item { + Widget::declare ListBox::Item { + {-indent Int 0 0 "%d >= 0"} + {-text String "" 0} + {-font String "" 0} + {-foreground String "" 0} + {-image TkResource "" 0 label} + {-window String "" 0} + {-data String "" 0} + + {-fill Synonym -foreground} + {-fg Synonym -foreground} + } + } + + DynamicHelp::include ListBox::Item balloon + + Widget::tkinclude ListBox canvas .c \ + remove { + -insertwidth -insertbackground -insertborderwidth -insertofftime + -insertontime -selectborderwidth -closeenough -confine -scrollregion + -xscrollincrement -yscrollincrement -width -height + } \ + initialize { + -relief sunken -borderwidth 2 -takefocus 1 + -highlightthickness 1 -width 200 + } + + DragSite::include ListBox "LISTBOX_ITEM" 1 + DropSite::include ListBox { + LISTBOX_ITEM {copy {} move {}} + } + + Widget::declare ListBox { + {-deltax Int 10 0 "%d >= 0"} + {-deltay Int 15 0 "%d >= 0"} + {-padx Int 20 0 "%d >= 0"} + {-foreground TkResource "" 0 listbox} + {-background TkResource "" 0 listbox} + {-selectbackground TkResource "" 0 listbox} + {-selectforeground TkResource "" 0 listbox} + {-font TkResource "" 0 listbox} + {-width TkResource "" 0 listbox} + {-height TkResource "" 0 listbox} + {-redraw Boolean 1 0} + {-multicolumn Boolean 0 0} + {-dropovermode Flag "wpi" 0 "wpi"} + {-selectmode Enum none 0 {none single multiple}} + {-fg Synonym -foreground} + {-bg Synonym -background} + {-dropcmd String "ListBox::_drag_and_drop" 0} + {-autofocus Boolean 1 1} + {-selectfill Boolean 0 1} + } + + Widget::addmap ListBox "" .c {-deltay -yscrollincrement} + + bind ListBox <FocusIn> [list after idle {BWidget::refocus %W %W.c}] + bind ListBox <Destroy> [list ListBox::_destroy %W] + bind ListBox <Configure> [list ListBox::_resize %W] + bind ListBoxFocus <1> [list focus %W] + bind ListBox <Key-Up> [list ListBox::_keyboard_navigation %W -1] + bind ListBox <Key-Down> [list ListBox::_keyboard_navigation %W 1] + + variable _edit +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::create +# ---------------------------------------------------------------------------- +proc ListBox::create { path args } { + Widget::init ListBox $path $args + + variable $path + upvar 0 $path data + + frame $path -class ListBox -bd 0 -highlightthickness 0 -relief flat \ + -takefocus 0 + # For 8.4+ we don't want to inherit the padding + catch {$path configure -padx 0 -pady 0} + # widget informations + set data(nrows) -1 + + # items informations + set data(items) {} + set data(selitems) {} + + # update informations + set data(upd,level) 0 + set data(upd,afterid) "" + set data(upd,level) 0 + set data(upd,delete) {} + + # drag and drop informations + set data(dnd,scroll) "" + set data(dnd,afterid) "" + set data(dnd,item) "" + + eval [list canvas $path.c] [Widget::subcget $path .c] \ + [list -xscrollincrement 8] + pack $path.c -expand yes -fill both + + DragSite::setdrag $path $path.c ListBox::_init_drag_cmd \ + [Widget::cget $path -dragendcmd] 1 + DropSite::setdrop $path $path.c ListBox::_over_cmd ListBox::_drop_cmd 1 + + Widget::create ListBox $path + + set w [Widget::cget $path -width] + set h [Widget::cget $path -height] + set dy [Widget::cget $path -deltay] + $path.c configure -width [expr {$w*8}] -height [expr {$h*$dy}] + + # Insert $path into the canvas bindings, so that anyone binding + # directly onto the widget will see their bindings activated when + # the canvas has focus. + set bindtags [bindtags $path.c] + set bindtags [linsert $bindtags 1 $path] + # Let any click within the canvas focus on the canvas so that + # MouseWheel scroll events will be properly handled by the canvas. + if {[Widget::cget $path -autofocus]} { + lappend bindtags ListBoxFocus + BWidget::bindMouseWheel $path.c + } + bindtags $path.c $bindtags + + # Add slightly modified up/down bindings to the canvas, in case + # it gets the focus (like with -autofocus). + bind $path.c <Key-Up> {ListBox::_keyboard_navigation [winfo parent %W] -1} + bind $path.c <Key-Down> {ListBox::_keyboard_navigation [winfo parent %W] 1} + + _configureSelectmode $path [Widget::getoption $path -selectmode] + + return $path +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_configureSelectmode +# ---------------------------------------------------------------------------- +# Configure the selectmode +proc ListBox::_configureSelectmode { path selectmode {previous none} } { + # clear current binding + switch -exact -- $previous { + single { + $path _bindText <Button-1> "" + $path _bindImage <Button-1> "" + } + multiple { + $path _bindText <ButtonRelease-1> "" + $path _bindText <Shift-ButtonRelease-1> "" + $path _bindText <Control-ButtonRelease-1> "" + + $path _bindImage <ButtonRelease-1> "" + $path _bindImage <Shift-ButtonRelease-1> "" + $path _bindImage <Control-ButtonRelease-1> "" + } + } + # set new bindings + switch -exact -- $selectmode { + single { + $path _bindText <Button-1> [list ListBox::_mouse_select $path set] + $path _bindImage <Button-1> [list ListBox::_mouse_select $path set] + if {1 < [llength [ListBox::selection $path get]]} { + ListBox::selection $path clear + } + } + multiple { + set cmd ListBox::_multiple_select + $path _bindText <ButtonRelease-1> [list $cmd $path n %x %y] + $path _bindText <Shift-ButtonRelease-1> [list $cmd $path s %x %y] + $path _bindText <Control-ButtonRelease-1> [list $cmd $path c %x %y] + + $path _bindImage <ButtonRelease-1> [list $cmd $path n %x %y] + $path _bindImage <Shift-ButtonRelease-1> [list $cmd $path s %x %y] + $path _bindImage <Control-ButtonRelease-1> [list $cmd $path c %x %y] + } + default { + if {0 < [llength [ListBox::selection $path get]]} { + ListBox::selection $path clear + } + } + } +} +# ---------------------------------------------------------------------------- +# Command ListBox::configure +# ---------------------------------------------------------------------------- +proc ListBox::configure { path args } { + set selectmodePrevious [Widget::getoption $path -selectmode] + set res [Widget::configure $path $args] + + if { [Widget::hasChanged $path -selectmode selectmode] } { + _configureSelectmode $path $selectmode $selectmodePrevious + } + + set ch1 [expr {[Widget::hasChanged $path -deltay dy] | + [Widget::hasChanged $path -padx val] | + [Widget::hasChanged $path -multicolumn val]}] + + set ch2 [expr {[Widget::hasChanged $path -selectbackground val] | + [Widget::hasChanged $path -selectforeground val]}] + + set redraw 0 + if { [Widget::hasChanged $path -height h] } { + $path.c configure -height [expr {$h*$dy}] + set redraw 1 + } + if { [Widget::hasChanged $path -width w] } { + $path.c configure -width [expr {$w*8}] + set redraw 1 + } + + if { [Widget::hasChanged $path -background bg] } { + $path.c itemconfigure box -fill $bg + } + + if { !$redraw } { + if { $ch1 } { + _redraw_idle $path 2 + } elseif { $ch2 } { + _redraw_idle $path 1 + } + } + + if { [Widget::hasChanged $path -redraw bool] && $bool } { + variable $path + upvar 0 $path data + set lvl $data(upd,level) + set data(upd,level) 0 + _redraw_idle $path $lvl + } + set force [Widget::hasChanged $path -dragendcmd dragend] + DragSite::setdrag $path $path.c ListBox::_init_drag_cmd $dragend $force + DropSite::setdrop $path $path.c ListBox::_over_cmd ListBox::_drop_cmd + + return $res +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::cget +# ---------------------------------------------------------------------------- +proc ListBox::cget { path option } { + return [Widget::cget $path $option] +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::insert +# ---------------------------------------------------------------------------- +proc ListBox::insert { path index item args } { + variable $path + upvar 0 $path data + + set item [Widget::nextIndex $path $item] + + if {[info exists data(exists,$item)]} { + return -code error "item \"$item\" already exists" + } + + Widget::init ListBox::Item $path.$item $args + + set data(items) [linsert $data(items) $index $item] + set data(exists,$item) 1 + set data(upd,create,$item) $item + + _redraw_idle $path 2 + return $item +} + +# Bastien Chevreux (bach@mwgdna.com) +# The multipleinsert command performs inserts several items at once into +# the list. It is faster than calling insert multiple times as it uses the +# Widget::copyinit command for initializing all items after the 1st. The +# speedup factor is between 2 and 3 for typical usage, but could be higher +# for inserts with many options. +# +# Syntax: path and index are as in the insert command +# args is a list of even numbered elements where the 1st of each pair +# corresponds to the item of 'insert' and the second to args of 'insert'. +# ---------------------------------------------------------------------------- +# Command ListBox::multipleinsert +# ---------------------------------------------------------------------------- +proc ListBox::multipleinsert { path index args } { + variable $path + upvar 0 $path data + + # If we got only one list as arg, take the first element as args + # This enables callers to use + # $list multipleinsert index $thelist + # instead of + # eval $list multipleinsert index $thelist + + if {[llength $args] == 1} { + set args [lindex $args 0] + } + + set count 0 + foreach {item iargs} $args { + if {[info exists data(exists,$item)]} { + return -code error "item \"$item\" already exists" + } + + if {$count==0} { + Widget::init ListBox::Item $path.$item $iargs + set firstpath $path.$item + } else { + Widget::copyinit ListBox::Item $firstpath $path.$item $iargs + } + + set data(items) [linsert $data(items) $index $item] + set data(exists,$item) 1 + set data(upd,create,$item) $item + + incr count + } + + _redraw_idle $path 2 + return $item +} + +# ---------------------------------------------------------------------------- +# Command ListBox::itemconfigure +# ---------------------------------------------------------------------------- +proc ListBox::itemconfigure { path item args } { + variable $path + upvar 0 $path data + + if { [lsearch -exact $data(items) $item] == -1 } { + return -code error "item \"$item\" does not exist" + } + + set oldind [Widget::getoption $path.$item -indent] + + set res [Widget::configure $path.$item $args] + set chind [Widget::hasChanged $path.$item -indent indent] + set chw [Widget::hasChanged $path.$item -window win] + set chi [Widget::hasChanged $path.$item -image img] + set cht [Widget::hasChanged $path.$item -text txt] + set chf [Widget::hasChanged $path.$item -font fnt] + set chfg [Widget::hasChanged $path.$item -foreground fg] + set idn [$path.c find withtag n:$item] + + _set_help $path $item + + if { $idn == "" } { + # item is not drawn yet + _redraw_idle $path 2 + return $res + } + + set oldb [$path.c bbox $idn] + set coords [$path.c coords $idn] + set padx [Widget::getoption $path -padx] + set x0 [expr {[lindex $coords 0]-$padx-$oldind+$indent}] + set y0 [lindex $coords 1] + if { $chw || $chi } { + # -window or -image modified + set idi [$path.c find withtag i:$item] + set type [lindex [$path.c gettags $idi] 0] + if { [string length $win] } { + if { [string equal $type "win"] } { + $path.c itemconfigure $idi -window $win + } else { + $path.c delete $idi + $path.c create window $x0 $y0 -window $win -anchor w \ + -tags [list win i:$item] + } + } elseif { [string length $img] } { + if { [string equal $type "img"] } { + $path.c itemconfigure $idi -image $img + } else { + $path.c delete $idi + $path.c create image $x0 $y0 -image $img -anchor w \ + -tags [list img imgbind i:$item] + } + } else { + $path.c delete $idi + } + } + + if { $cht || $chf || $chfg } { + # -text or -font modified, or -foreground modified + set fnt [_getoption $path $item -font] + set fg [_getoption $path $item -foreground] + $path.c itemconfigure $idn -text $txt -font $fnt -fill $fg + _redraw_idle $path 1 + } + + if { $chind } { + # -indent modified + $path.c coords $idn [expr {$x0+$padx}] $y0 + $path.c coords i:$item $x0 $y0 + _redraw_idle $path 1 + } + + if { [Widget::getoption $path -multicolumn] && ($cht || $chf || $chind) } { + set bbox [$path.c bbox $idn] + if { [lindex $bbox 2] > [lindex $oldb 2] } { + _redraw_idle $path 2 + } + } + + return $res +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::itemcget +# ---------------------------------------------------------------------------- +proc ListBox::itemcget { path item option } { + return [Widget::cget $path.$item $option] +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_bindText +# ---------------------------------------------------------------------------- +proc ListBox::_bindText { path event script {tag click} } { + if { $script != "" } { + set map [list %W $path] + set script [string map $map $script] + append script " \[ListBox::_get_current [list $path]\]" + } + $path.c bind $tag $event $script +} + +# ---------------------------------------------------------------------------- +# Command ListBox::bindText +# ---------------------------------------------------------------------------- +proc ListBox::bindText { path event script } { + _bindText $path $event $script clickbind +} + +# ---------------------------------------------------------------------------- +# Command ListBox::_bindImage +# ---------------------------------------------------------------------------- +proc ListBox::_bindImage { path event script {tag img} } { + if { $script != "" } { + set map [list %W $path] + set script [string map $map $script] + append script " \[ListBox::_get_current [list $path]\]" + } + $path.c bind $tag $event $script +} + +# ---------------------------------------------------------------------------- +# Command ListBox::bindImage +# ---------------------------------------------------------------------------- +proc ListBox::bindImage { path event script } { + _bindImage $path $event $script imgbind +} + +# ---------------------------------------------------------------------------- +# Command ListBox::delete +# ---------------------------------------------------------------------------- +proc ListBox::delete { path args } { + variable $path + upvar 0 $path data + Widget::getVariable $path help + + foreach litems $args { + foreach item $litems { + set idx [lsearch -exact $data(items) $item] + if { $idx != -1 } { + set data(items) [lreplace $data(items) $idx $idx] + array unset help $item + Widget::destroy $path.$item + if { [info exists data(exists,$item)] } { + unset data(exists,$item) + } + if { [info exists data(upd,create,$item)] } { + unset data(upd,create,$item) + } else { + lappend data(upd,delete) $item + } + } + } + } + + set sel $data(selitems) + set data(selitems) {} + eval [list selection $path set] $sel + _redraw_idle $path 2 +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::move +# ---------------------------------------------------------------------------- +proc ListBox::move { path item index } { + variable $path + upvar 0 $path data + + if { [set idx [lsearch -exact $data(items) $item]] == -1 } { + return -code error "item \"$item\" does not exist" + } + + set data(items) [linsert [lreplace $data(items) $idx $idx] $index $item] + + _redraw_idle $path 2 +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::reorder +# ---------------------------------------------------------------------------- +proc ListBox::reorder { path neworder } { + variable $path + upvar 0 $path data + + set data(items) [BWidget::lreorder $data(items) $neworder] + _redraw_idle $path 2 +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::selection +# ---------------------------------------------------------------------------- +proc ListBox::selection { path cmd args } { + variable $path + upvar 0 $path data + + switch -- $cmd { + set { + set data(selitems) {} + foreach item $args { + if { [lsearch -exact $data(selitems) $item] == -1 } { + if { [lsearch -exact $data(items) $item] != -1 } { + lappend data(selitems) $item + } + } + } + } + add { + foreach item $args { + if { [lsearch -exact $data(selitems) $item] == -1 } { + if { [lsearch -exact $data(items) $item] != -1 } { + lappend data(selitems) $item + } + } + } + } + remove { + foreach item $args { + if { [set idx [lsearch -exact $data(selitems) $item]] != -1 } { + set data(selitems) [lreplace $data(selitems) $idx $idx] + } + } + } + clear { + set data(selitems) {} + } + get { + return $data(selitems) + } + includes { + return [expr {[lsearch -exact $data(selitems) $args] != -1}] + } + default { + return + } + } + + _redraw_idle $path 1 +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::exists +# ---------------------------------------------------------------------------- +proc ListBox::exists { path item } { + variable $path + upvar 0 $path data + + return [expr {[lsearch -exact $data(items) $item] != -1}] +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::index +# ---------------------------------------------------------------------------- +proc ListBox::index { path item } { + variable $path + upvar 0 $path data + if {[string equal $item "active"]} { return [$path selection get] } + return [lsearch -exact $data(items) $item] +} + + +# ---------------------------------------------------------------------------- +# ListBox::find +# Returns the item given a position. +# findInfo @x,y ?confine? +# lineNumber +# ---------------------------------------------------------------------------- +proc ListBox::find {path findInfo {confine ""}} { + variable $path + upvar 0 $path widgetData + + if {[regexp -- {^@([0-9]+),([0-9]+)$} $findInfo match x y]} { + set x [$path.c canvasx $x] + set y [$path.c canvasy $y] + } elseif {[regexp -- {^[0-9]+$} $findInfo lineNumber]} { + set dy [Widget::getoption $path -deltay] + set y [expr {$dy*($lineNumber+0.5)}] + set confine "" + } else { + return -code error "invalid find spec \"$findInfo\"" + } + + set found 0 + set xi 0 + foreach xs $widgetData(xlist) { + if {$x <= $xs} { + foreach id [$path.c find overlapping $xi $y $xs $y] { + set ltags [$path.c gettags $id] + set item [lindex $ltags 0] + if { [string equal $item "item"] || + [string equal $item "img"] || + [string equal $item "win"] } { + # item is the label or image/window of the node + set item [string range [lindex $ltags 1] 2 end] + set found 1 + break + } + } + break + } + set xi $xs + } + + if {$found} { + if {[string equal $confine "confine"]} { + # test if x stand inside node bbox + set xi [expr {[lindex [$path.c coords n:$item] 0]-[Widget::getoption $path -padx]}] + set xs [lindex [$path.c bbox n:$item] 2] + if {$x >= $xi && $x <= $xs} { + return $item + } + } else { + return $item + } + } + return "" +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::item - deprecated +# ---------------------------------------------------------------------------- +proc ListBox::item { path first {last ""} } { + variable $path + upvar 0 $path data + + if { ![string length $last] } { + return [lindex $data(items) $first] + } else { + return [lrange $data(items) $first $last] + } +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::items +# ---------------------------------------------------------------------------- +proc ListBox::items { path {first ""} {last ""}} { + variable $path + upvar 0 $path data + + if { ![string length $first] } { + return $data(items) + } + + if { ![string length $last] } { + return [lindex $data(items) $first] + } else { + return [lrange $data(items) $first $last] + } +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::see +# ---------------------------------------------------------------------------- +proc ListBox::see { path item } { + variable $path + upvar 0 $path data + + if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } { + after cancel $data(upd,afterid) + _redraw_listbox $path + } + set idn [$path.c find withtag n:$item] + if { $idn != "" } { + set idi [$path.c find withtag i:$item] + if { $idi == "" } { set idi $idn } + ListBox::_see $path $idn right + ListBox::_see $path $idi left + } +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::edit +# ---------------------------------------------------------------------------- +proc ListBox::edit { path item text {verifycmd ""} {clickres 0} {select 1}} { + variable _edit + variable $path + upvar 0 $path data + + if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } { + after cancel $data(upd,afterid) + _redraw_listbox $path + } + set idn [$path.c find withtag n:$item] + if { $idn != "" } { + ListBox::_see $path $idn right + ListBox::_see $path $idn left + + set oldfg [$path.c itemcget $idn -fill] + set sbg [Widget::getoption $path -selectbackground] + set coords [$path.c coords $idn] + set x [lindex $coords 0] + set y [lindex $coords 1] + set bd [expr {[$path.c cget -borderwidth]+[$path.c cget -highlightthickness]}] + set w [expr {[winfo width $path] - 2*$bd}] + set wmax [expr {[$path.c canvasx $w]-$x}] + + $path.c itemconfigure $idn -fill [Widget::getoption $path -background] + $path.c itemconfigure s:$item -fill {} -outline {} + + set _edit(text) $text + set _edit(wait) 0 + + set frame [frame $path.edit \ + -relief flat -borderwidth 0 -highlightthickness 0 \ + -background [Widget::getoption $path -background]] + set ent [entry $frame.edit \ + -width 0 \ + -relief solid \ + -borderwidth 1 \ + -highlightthickness 0 \ + -foreground [_getoption $path $item -foreground] \ + -background [Widget::getoption $path -background] \ + -selectforeground [Widget::getoption $path -selectforeground] \ + -selectbackground $sbg \ + -font [_getoption $path $item -font] \ + -textvariable ListBox::_edit(text)] + pack $ent -ipadx 8 -anchor w + + set idw [$path.c create window $x $y -window $frame -anchor w] + trace variable ListBox::_edit(text) w [list ListBox::_update_edit_size $path $ent $idw $wmax] + tkwait visibility $ent + grab $frame + BWidget::focus set $ent + _update_edit_size $path $ent $idw $wmax + update + if { $select } { + $ent selection range 0 end + $ent icursor end + $ent xview end + } + + bindtags $ent [list $ent Entry] + bind $ent <Escape> {set ListBox::_edit(wait) 0} + bind $ent <Return> {set ListBox::_edit(wait) 1} + if { $clickres == 0 || $clickres == 1 } { + bind $frame <Button> [list set ListBox::_edit(wait) $clickres] + } + + set ok 0 + while { !$ok } { + tkwait variable ListBox::_edit(wait) + if { !$_edit(wait) || [llength $verifycmd]==0 || + [uplevel \#0 $verifycmd [list $_edit(text)]] } { + set ok 1 + } + } + trace vdelete ListBox::_edit(text) w [list ListBox::_update_edit_size $path $ent $idw $wmax] + grab release $frame + BWidget::focus release $ent + destroy $frame + $path.c delete $idw + $path.c itemconfigure $idn -fill $oldfg + $path.c itemconfigure s:$item -fill $sbg -outline $sbg + + if { $_edit(wait) } { + return $_edit(text) + } + } + return "" +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::xview +# ---------------------------------------------------------------------------- +proc ListBox::xview { path args } { + return [eval [linsert $args 0 $path.c xview]] +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::yview +# ---------------------------------------------------------------------------- +proc ListBox::yview { path args } { + return [eval [linsert $args 0 $path.c yview]] +} + + +proc ListBox::getcanvas { path } { + return $path.c +} + + +proc ListBox::curselection { path } { + return [$path selection get] +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_update_edit_size +# ---------------------------------------------------------------------------- +proc ListBox::_update_edit_size { path entry idw wmax args } { + set entw [winfo reqwidth $entry] + if { $entw >= $wmax } { + $path.c itemconfigure $idw -width $wmax + } else { + $path.c itemconfigure $idw -width 0 + } +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_getoption +# Returns the value of option for node. If empty, returned value is those +# of the ListBox. +# ---------------------------------------------------------------------------- +proc ListBox::_getoption { path item option } { + set value [Widget::getoption $path.$item $option] + if {![string length $value]} { + set value [Widget::getoption $path $option] + } + return $value +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_destroy +# ---------------------------------------------------------------------------- +proc ListBox::_destroy { path } { + variable $path + upvar 0 $path data + + if { $data(upd,afterid) != "" } { + after cancel $data(upd,afterid) + } + if { $data(dnd,afterid) != "" } { + after cancel $data(dnd,afterid) + } + foreach item $data(items) { + Widget::destroy $path.$item + } + + Widget::destroy $path + unset data +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_see +# ---------------------------------------------------------------------------- +proc ListBox::_see { path idn side } { + set bbox [$path.c bbox $idn] + set scrl [$path.c cget -scrollregion] + + set ymax [lindex $scrl 3] + set dy [$path.c cget -yscrollincrement] + set yv [$path.c yview] + set yv0 [expr {round([lindex $yv 0]*$ymax/$dy)}] + set yv1 [expr {round([lindex $yv 1]*$ymax/$dy)}] + set y [expr {int([lindex [$path.c coords $idn] 1]/$dy)}] + if { $y < $yv0 } { + $path.c yview scroll [expr {$y-$yv0}] units + } elseif { $y >= $yv1 } { + $path.c yview scroll [expr {$y-$yv1+1}] units + } + + set xmax [lindex $scrl 2] + set dx [$path.c cget -xscrollincrement] + set xv [$path.c xview] + if { [string equal $side "right"] } { + set xv1 [expr {round([lindex $xv 1]*$xmax/$dx)}] + set x1 [expr {int([lindex $bbox 2]/$dx)}] + if { $x1 >= $xv1 } { + $path.c xview scroll [expr {$x1-$xv1+1}] units + } + } else { + set xv0 [expr {round([lindex $xv 0]*$xmax/$dx)}] + set x0 [expr {int([lindex $bbox 0]/$dx)}] + if { $x0 < $xv0 } { + $path.c xview scroll [expr {$x0-$xv0}] units + } + } +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_update_scrollregion +# ---------------------------------------------------------------------------- +proc ListBox::_update_scrollregion { path } { + set bd [$path.c cget -borderwidth] + set ht [$path.c cget -highlightthickness] + set bd [expr {2*($bd + $ht)}] + set w [expr {[winfo width $path] - $bd}] + set h [expr {[winfo height $path] - $bd}] + set xinc [$path.c cget -xscrollincrement] + set yinc [$path.c cget -yscrollincrement] + set bbox [$path.c bbox item win img] + if { [llength $bbox] } { + set xs [lindex $bbox 2] + set ys [lindex $bbox 3] + + if { $w < $xs } { + set w [expr {int($xs)}] + if { [set r [expr {$w % $xinc}]] } { + set w [expr {$w+$xinc-$r}] + } + } + if { $h < $ys } { + set h [expr {int($ys)}] + if { [set r [expr {$h % $yinc}]] } { + set h [expr {$h+$yinc-$r}] + } + } + } + + $path.c configure -scrollregion [list 0 0 $w $h] +} + + +proc ListBox::_update_select_fill { path } { + variable $path + upvar 0 $path data + + set width [winfo width $path] + + foreach item $data(items) { + set bbox [$path.c bbox n:$item] + set bbox [list 0 [lindex $bbox 1] $width [lindex $bbox 3]] + $path.c coords b:$item $bbox + } + + _redraw_selection $path +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_draw_item +# ---------------------------------------------------------------------------- +proc ListBox::_draw_item {path item x0 x1 y bg selfill multi ww} { + set indent [Widget::getoption $path.$item -indent] + set i [$path.c create text [expr {$x1+$indent}] $y \ + -text [Widget::getoption $path.$item -text] \ + -fill [_getoption $path $item -foreground] \ + -font [_getoption $path $item -font] \ + -anchor w \ + -tags [list item n:$item click clickbind]] + + if { $selfill && !$multi } { + set bbox [$path.c bbox n:$item] + set bbox [list 0 [lindex $bbox 1] $ww [lindex $bbox 3]] + set tags [list box b:$item click clickbind] + $path.c create rect $bbox -fill $bg -width 0 -tags $tags + $path.c raise $i + } + + if { [set win [Widget::getoption $path.$item -window]] != "" } { + $path.c create window [expr {$x0+$indent}] $y \ + -window $win -anchor w -tags [list win i:$item] + } elseif { [set img [Widget::getoption $path.$item -image]] != "" } { + $path.c create image [expr {$x0+$indent}] $y \ + -image $img -anchor w -tags [list img imgbind i:$item] + } + + _set_help $path $item +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_redraw_items +# ---------------------------------------------------------------------------- +proc ListBox::_redraw_items { path } { + variable $path + upvar 0 $path data + + set cursor [$path.c cget -cursor] + $path.c configure -cursor watch + update idletasks ; # make sure watch cursor is reflected + set dx [Widget::getoption $path -deltax] + set dy [Widget::getoption $path -deltay] + set padx [Widget::getoption $path -padx] + set y0 [expr {$dy/2}] + set x0 4 + set x1 [expr {$x0+$padx}] + set nitem 0 + set width 0 + set drawn {} + set data(xlist) {} + if { [Widget::cget $path -multicolumn] } { + set nrows $data(nrows) + } else { + set nrows [llength $data(items)] + } + foreach item $data(upd,delete) { + $path.c delete i:$item n:$item s:$item b:$item + } + # Pass these to _draw_item so it doesn't have to request them + # for each item. + set bg [Widget::cget $path -background] + set selfill [Widget::cget $path -selectfill] + set multi [Widget::cget $path -multicolumn] + set ww [winfo width $path] + foreach item $data(items) { + if { [info exists data(upd,create,$item)] } { + _draw_item $path $item $x0 $x1 $y0 $bg $selfill $multi $ww + unset data(upd,create,$item) + } else { + set indent [Widget::getoption $path.$item -indent] + $path.c coords n:$item [expr {$x1+$indent}] $y0 + $path.c coords i:$item [expr {$x0+$indent}] $y0 + } + set font [_getoption $path $item -font] + set text [Widget::getoption $path.$item -text] + set tw [font measure $font $text] + if {$tw > $width} { set width $tw } + incr y0 $dy + incr nitem + lappend drawn n:$item + if { $nitem == $nrows } { + set x2 [expr {$x1 + $width}] + set y0 [expr {$dy/2}] + set drawn {} + set x0 [expr {$x2+$dx}] + set x1 [expr {$x0+$padx}] + set nitem 0 + lappend data(xlist) $x2 + set width 0 + } + } + if { $nitem && $nitem < $nrows } { + lappend data(xlist) [expr {$x1 + $width}] + } + set data(upd,delete) {} + $path.c configure -cursor $cursor +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_redraw_selection +# ---------------------------------------------------------------------------- +proc ListBox::_redraw_selection { path } { + variable $path + upvar 0 $path data + + set selbg [Widget::getoption $path -selectbackground] + set selfg [Widget::getoption $path -selectforeground] + set selfill [Widget::getoption $path -selectfill] + set multi [Widget::getoption $path -multicolumn] + foreach id [$path.c find withtag sel] { + set item [string range [lindex [$path.c gettags $id] 1] 2 end] + if {-1 == [lsearch -exact $data(upd,delete) $item]} { + $path.c itemconfigure "n:$item" \ + -fill [_getoption $path $item -foreground] + } + } + $path.c delete sel + if {$selfill && !$multi} { + # cache window width for use below + set width [winfo width $path] + } + foreach item $data(selitems) { + set bbox [$path.c bbox "n:$item"] + if { [llength $bbox] } { + if { $selfill && !$multi } { + # With -selectfill, make box occupy full width of widget + set bbox [list 0 [lindex $bbox 1] $width [lindex $bbox 3]] + } + set tags [list sel s:$item click clickbind] + set id [$path.c create rectangle $bbox \ + -fill $selbg -outline $selbg -tags $tags] + if {$selfg != ""} { + # Don't allow an empty fill - that would be transparent + $path.c itemconfigure "n:$item" -fill $selfg + } + $path.c lower $id + $path.c lower b:$item + } + } +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_redraw_listbox +# ---------------------------------------------------------------------------- +proc ListBox::_redraw_listbox { path } { + variable $path + upvar 0 $path data + + if { [Widget::getoption $path -redraw] } { + if { $data(upd,level) == 2 } { + _redraw_items $path + } + _redraw_selection $path + _update_scrollregion $path + if {[Widget::cget $path -selectfill]} { + _update_select_fill $path + } + set data(upd,level) 0 + set data(upd,afterid) "" + } +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_redraw_idle +# ---------------------------------------------------------------------------- +proc ListBox::_redraw_idle { path level } { + variable $path + upvar 0 $path data + + if { $data(nrows) != -1 } { + # widget is realized + if { [Widget::getoption $path -redraw] && $data(upd,afterid) == "" } { + set data(upd,afterid) \ + [after idle [list ListBox::_redraw_listbox $path]] + } + } + if { $level > $data(upd,level) } { + set data(upd,level) $level + } + return "" +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_resize +# ---------------------------------------------------------------------------- +proc ListBox::_resize { path } { + variable $path + upvar 0 $path data + + if { [Widget::getoption $path -multicolumn] } { + set bd [expr {[$path.c cget -borderwidth]+[$path.c cget -highlightthickness]}] + set h [expr {[winfo height $path] - 2*$bd}] + set nrows [expr {$h/[$path.c cget -yscrollincrement]}] + if { $nrows == 0 } { + set nrows 1 + } + if { $nrows != $data(nrows) } { + set data(nrows) $nrows + _redraw_idle $path 2 + } else { + _update_scrollregion $path + } + } elseif { $data(nrows) == -1 } { + # first Configure event + set data(nrows) 0 + ListBox::_redraw_listbox $path + if {[Widget::cget $path -selectfill]} { + _update_select_fill $path + } + } else { + if {[Widget::cget $path -selectfill]} { + _update_select_fill $path + } + + _update_scrollregion $path + } +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_init_drag_cmd +# ---------------------------------------------------------------------------- +proc ListBox::_init_drag_cmd { path X Y top } { + set path [winfo parent $path] + set ltags [$path.c gettags current] + set item [lindex $ltags 0] + if { [string equal $item "item"] || + [string equal $item "img"] || + [string equal $item "win"] } { + set item [string range [lindex $ltags 1] 2 end] + if {[llength [set cmd [Widget::getoption $path -draginitcmd]]]} { + return [uplevel \#0 $cmd [list $path $item $top]] + } + if { [set type [Widget::getoption $path -dragtype]] == "" } { + set type "LISTBOX_ITEM" + } + if { [set img [Widget::getoption $path.$item -image]] != "" } { + pack [label $top.l -image $img -padx 0 -pady 0] + } + return [list $type {copy move link} $item] + } + return {} +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_drop_cmd +# ---------------------------------------------------------------------------- +proc ListBox::_drop_cmd { path source X Y op type dnddata } { + set path [winfo parent $path] + variable $path + upvar 0 $path data + + if { [string length $data(dnd,afterid)] } { + after cancel $data(dnd,afterid) + set data(dnd,afterid) "" + } + $path.c delete drop + set data(dnd,scroll) "" + if { [llength $data(dnd,item)] || ![llength $data(items)] } { + if {[llength [set cmd [Widget::getoption $path -dropcmd]]]} { + return [uplevel \#0 $cmd [list $path $source $data(dnd,item) $op $type $dnddata]] + } + } + return 0 +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_over_cmd +# ---------------------------------------------------------------------------- +proc ListBox::_over_cmd { path source event X Y op type dnddata } { + set path [winfo parent $path] + variable $path + upvar 0 $path data + + if { [string equal $event "leave"] } { + # we leave the window listbox + $path.c delete drop + if { [string length $data(dnd,afterid)] } { + after cancel $data(dnd,afterid) + set data(dnd,afterid) "" + } + set data(dnd,scroll) "" + return 0 + } + + if { [string equal $event "enter"] } { + # we enter the window listbox - dnd data initialization + set mode [Widget::getoption $path -dropovermode] + set data(dnd,mode) 0 + foreach c {w p i} { + set data(dnd,mode) [expr {($data(dnd,mode) << 1) | ([string first $c $mode] != -1)}] + } + } + + set x [expr {$X-[winfo rootx $path]}] + set y [expr {$Y-[winfo rooty $path]}] + $path.c delete drop + set data(dnd,item) "" + + # test for auto-scroll unless mode is widget only + if { $data(dnd,mode) != 4 && [_auto_scroll $path $x $y] != "" } { + return 2 + } + + if { $data(dnd,mode) & 4 } { + # dropovermode includes widget + set target [list widget] + set vmode 4 + } else { + set target [list ""] + set vmode 0 + } + if { ($data(dnd,mode) & 2) && ![llength $data(items)] } { + # dropovermode includes position and listbox is empty + lappend target "" 0 + set vmode [expr {$vmode | 2}] + } + + if { ($data(dnd,mode) & 3) && [llength $data(items)]} { + # dropovermode includes item or position + # we extract the box (xi,yi,xs,ys) where we can find item around x,y + set len [llength $data(items)] + set xc [$path.c canvasx $x] + set yc [$path.c canvasy $y] + set dy [$path.c cget -yscrollincrement] + set line [expr {int($yc/$dy)}] + set yi [expr {$line*$dy}] + set ys [expr {$yi+$dy}] + set xi 0 + set pos $line + if { [Widget::getoption $path -multicolumn] } { + set nrows $data(nrows) + } else { + set nrows $len + } + if { $line < $nrows } { + foreach xs $data(xlist) { + if { $xc <= $xs } { + break + } + set xi $xs + incr pos $nrows + } + if { $pos < $len } { + set item [lindex $data(items) $pos] + set xi [expr {[lindex [$path.c coords n:$item] 0]-[Widget::getoption $path -padx]-1}] + if { $data(dnd,mode) & 1 } { + # dropovermode includes item + lappend target $item + set vmode [expr {$vmode | 1}] + } else { + lappend target "" + } + + if { $data(dnd,mode) & 2 } { + # dropovermode includes position + if { $yc >= $yi+$dy/2 } { + # position is after $item + incr pos + set yl $ys + } else { + # position is before $item + set yl $yi + } + lappend target $pos + set vmode [expr {$vmode | 2}] + } else { + lappend target "" + } + } else { + lappend target "" "" + } + } else { + lappend target "" "" + } + + if { ($vmode & 3) == 3 } { + # result have both item and position + # we compute what is the preferred method + if { $yc-$yi <= 3 || $ys-$yc <= 3 } { + lappend target "position" + } else { + lappend target "item" + } + } + } + + if {$vmode && [llength [set cmd [Widget::getoption $path -dropovercmd]]]} { + # user-defined dropover command + set res [uplevel \#0 $cmd [list $source $target $op $type $dnddata]] + set code [lindex $res 0] + set vmode 0 + if {$code & 1} { + # update vmode + switch -exact -- [lindex $res 1] { + item {set vmode 1} + position {set vmode 2} + widget {set vmode 4} + } + } + } else { + if { ($vmode & 3) == 3 } { + # result have both item and position + # we choose the preferred method + if { [string equal [lindex $target 3] "position"] } { + set vmode [expr {$vmode & ~1}] + } else { + set vmode [expr {$vmode & ~2}] + } + } + + if { $data(dnd,mode) == 4 || $data(dnd,mode) == 0 } { + # dropovermode is widget or empty - recall is not necessary + set code 1 + } else { + set code 3 + } + } + + # draw dnd visual following vmode + if {[llength $data(items)]} { + if { $vmode & 1 } { + set data(dnd,item) [list "item" [lindex $target 1]] + $path.c create rectangle $xi $yi $xs $ys -tags drop + } elseif { $vmode & 2 } { + set data(dnd,item) [concat "position" [lindex $target 2]] + $path.c create line $xi $yl $xs $yl -tags drop + } elseif { $vmode & 4 } { + set data(dnd,item) [list "widget"] + } else { + set code [expr {$code & 2}] + } + } + + if { $code & 1 } { + DropSite::setcursor based_arrow_down + } else { + DropSite::setcursor dot + } + return $code +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_auto_scroll +# ---------------------------------------------------------------------------- +proc ListBox::_auto_scroll { path x y } { + variable $path + upvar 0 $path data + + set xmax [winfo width $path] + set ymax [winfo height $path] + set scroll {} + if { $y <= 6 } { + if { [lindex [$path.c yview] 0] > 0 } { + set scroll [list yview -1] + DropSite::setcursor sb_up_arrow + } + } elseif { $y >= $ymax-6 } { + if { [lindex [$path.c yview] 1] < 1 } { + set scroll [list yview 1] + DropSite::setcursor sb_down_arrow + } + } elseif { $x <= 6 } { + if { [lindex [$path.c xview] 0] > 0 } { + set scroll [list xview -1] + DropSite::setcursor sb_left_arrow + } + } elseif { $x >= $xmax-6 } { + if { [lindex [$path.c xview] 1] < 1 } { + set scroll [list xview 1] + DropSite::setcursor sb_right_arrow + } + } + + if { [string length $data(dnd,afterid)] && ![string equal $data(dnd,scroll) $scroll] } { + after cancel $data(dnd,afterid) + set data(dnd,afterid) "" + } + + set data(dnd,scroll) $scroll + if { [llength $scroll] && ![string length $data(dnd,afterid)] } { + set data(dnd,afterid) [after 200 [list ListBox::_scroll $path $scroll]] + } + return $data(dnd,afterid) + +} + +# ----------------------------------------------------------------------------- +# Command ListBox::_multiple_select +# ----------------------------------------------------------------------------- +proc ListBox::_multiple_select { path mode x y idx } { + + variable $path + upvar 0 $path data + + + if { ![info exists data(anchor)] || ![info exists data(sel_anchor)] } { + set data(anchor) $idx + set data(sel_anchor) {} + } + + switch -exact -- $mode { + n { + _mouse_select $path set $idx + set data(anchor) $idx + set data(sel_anchor) {} + } + c { + set l [$path selection get] + if { [lsearch -exact $l $idx] >= 0 } { + _mouse_select $path remove $idx + } else { + _mouse_select $path add $idx + } + set data(anchor) $idx + set data(sel_anchor) {} + } + s { + eval [list $path _mouse_select remove] $data(sel_anchor) + + set ix [$path index $idx] + set ia [$path index $data(anchor)] + if { $ix > $ia } { + set istart $ia + set iend $ix + } else { + set istart $ix + set iend $ia + } + + for { set i $istart } { $i <= $iend } { incr i } { + set l [$path selection get] + set t [$path items $i] + set li [lsearch -exact $l $t] + if { $li < 0 } { + _mouse_select $path add $t + lappend data(sel_anchor) $t + } + } + } + } +} + + +# ---------------------------------------------------------------------------- +# Command ListBox::_scroll +# ---------------------------------------------------------------------------- +proc ListBox::_scroll { path scroll} { + variable $path + upvar 0 $path data + set cmd [lindex $scroll 0] + set dir [lindex $scroll 1] + if { ($dir == -1 && [lindex [$path.c $cmd] 0] > 0) || + ($dir == 1 && [lindex [$path.c $cmd] 1] < 1) } { + $path $cmd scroll $dir units + set data(dnd,afterid) \ + [after 50 [list ListBox::_scroll $path $scroll]] + } else { + set data(dnd,afterid) "" + DropSite::setcursor dot + } +} + +# ListBox::_set_help -- +# +# Register dynamic help for an item in the listbox. +# +# Arguments: +# path ListBox to query +# item Item in the listbox +# force Optional argument to force a reset of the help +# +# Results: +# none +proc ListBox::_set_help { path node } { + Widget::getVariable $path help + + set item $path.$node + set opts [list -helptype -helptext -helpvar] + foreach {cty ctx cv} [eval [linsert $opts 0 Widget::hasChangedX $item]] break + set text [Widget::getoption $item -helptext] + + ## If we've never set help for this item before, and text is not blank, + ## we need to setup help. We also need to reset help if any of the + ## options have changed. + if { (![info exists help($node)] && $text != "") || $cty || $ctx || $cv } { + set help($node) 1 + set type [Widget::getoption $item -helptype] + switch $type { + balloon { + DynamicHelp::register $path.c balloon n:$node $text + DynamicHelp::register $path.c balloon i:$node $text + DynamicHelp::register $path.c balloon b:$node $text + } + variable { + set var [Widget::getoption $item -helpvar] + DynamicHelp::register $path.c variable n:$node $var $text + DynamicHelp::register $path.c variable i:$node $var $text + DynamicHelp::register $path.c variable b:$node $var $text + } + } + } +} + +# ListBox::_mouse_select -- +# +# Handle selection commands that are done by the mouse. If the +# selection command returns true, we generate a <<ListboxSelect>> +# event for the listbox. +# +# Arguments: +# Standard arguments passed to a selection command. +# +# Results: +# none +proc ListBox::_mouse_select { path cmd args } { + eval [linsert $args 0 selection $path $cmd] + switch -- $cmd { + "add" - "clear" - "remove" - "set" { + event generate $path <<ListboxSelect>> + } + } +} + + +proc ListBox::_get_current { path } { + set t [$path.c gettags current] + return [string range [lindex $t 1] 2 end] +} + + +# ListBox::_drag_and_drop -- +# +# A default command to handle drag-and-drop functions local to this +# listbox. With this as the default -dropcmd, the user can simply +# enable drag-and-drop and be able to move items within this list +# with no further code. +# +# Arguments: +# Standard arguments passed to a dropcmd. +# +# Results: +# none +proc ListBox::_drag_and_drop { path from endItem operation type startItem } { + set items [$path items] + + ## This proc only handles drag-and-drop commands within itself. + ## If the widget this came from is not our widget (minus the canvas), + ## we don't want to do anything. They need to handle this themselves. + if {[winfo parent $from] != $path} { return } + + set place [lindex $endItem 0] + set i [lindex $endItem 1] + + switch -- $place { + "position" { + set idx $i + } + "item" { + set idx [$path index $i] + } + "widget" { + set idx [llength $items] + } + } + + # Check if startItem is part of the current selection and process the + # whole selection if so + set selItems [selection $path get] + if {-1 != [lsearch -exact $selItems $startItem]} { + set dragItems $selItems + } else { + set dragItems [list $startItem] + } + + # get drag indexes (to sort them) + foreach dragItem $dragItems { + lappend dragIdx [$path index $dragItem] + } + foreach pos [lsort -integer -indices $dragIdx] { + set dragItem [lindex $dragItems $pos] + set dragIdx [$path index $dragItem] + if {$idx > $dragIdx} { incr idx -1 } + if {[string equal $operation "copy"]} { + set options [Widget::options $path.$dragItem] + eval [linsert $options 0 $path insert $idx $dragItem\#auto] + incr idx + } else { + $path move $dragItem $idx + set idx [$path index $dragItem] + incr idx + } + } +} + + +proc ListBox::_keyboard_navigation { path dir } { + variable $path + upvar 0 $path data + + set sel [$path index [lindex [$path selection get] end]] + if {$dir > 0} { + incr sel + if {$sel >= [llength $data(items)]} { return } + } else { + incr sel -1 + if {$sel < 0} { return } + } + set item [lindex $data(items) $sel] + $path see $item + _mouse_select $path set $item +} diff --git a/modules/tclsci/tcl/BWidget/mainframe.tcl b/modules/tclsci/tcl/BWidget/mainframe.tcl new file mode 100755 index 000000000..e66bf572f --- /dev/null +++ b/modules/tclsci/tcl/BWidget/mainframe.tcl @@ -0,0 +1,713 @@ +# ---------------------------------------------------------------------------- +# mainframe.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: mainframe.tcl,v 1.24.2.1 2010/11/09 16:05:43 oehhar Exp $ +# ------------------------------------------------------------------------------ +# Index of commands: +# - MainFrame::create +# - MainFrame::configure +# - MainFrame::cget +# - MainFrame::getframe +# - MainFrame::addtoolbar +# - MainFrame::gettoolbar +# - MainFrame::addindicator +# - MainFrame::getindicator +# - MainFrame::getmenu +# - MainFrame::menuonly +# - MainFrame::showtoolbar +# - MainFrame::showstatusbar +# - MainFrame::_create_menubar +# - MainFrame::_create_entries +# - MainFrame::_parse_name +# - MainFrame::_parse_accelerator +# ---------------------------------------------------------------------------- + +namespace eval MainFrame { + Widget::define MainFrame mainframe ProgressBar + + Widget::bwinclude MainFrame ProgressBar .status.prg \ + remove { + -fg -bg -bd -troughcolor -background -borderwidth + -relief -orient -width -height + } \ + rename { + -maximum -progressmax + -variable -progressvar + -type -progresstype + -foreground -progressfg + } + + Widget::declare MainFrame { + {-width TkResource 0 0 frame} + {-height TkResource 0 0 frame} + {-background TkResource "" 0 frame} + {-textvariable String "" 0} + {-menu String {} 1} + {-separator Enum both 1 {none top bottom both}} + {-bg Synonym -background} + + {-menubarfont String "" 0} + {-menuentryfont String "" 0} + {-statusbarfont String "" 0} + } + + Widget::addmap MainFrame "" .frame {-width {} -height {} -background {}} + Widget::addmap MainFrame "" .topf {-background {}} + Widget::addmap MainFrame "" .botf {-background {}} + Widget::addmap MainFrame "" .status {-background {}} + Widget::addmap MainFrame "" .status.label {-background {}} + Widget::addmap MainFrame "" .status.indf {-background {}} + Widget::addmap MainFrame "" .status.prgf {-background {}} + Widget::addmap MainFrame ProgressBar .status.prg {-background {} -background -troughcolor} + + variable _widget +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::create +# ---------------------------------------------------------------------------- +proc MainFrame::create { path args } { + global tcl_platform + variable _widget + + if {[Widget::theme]} { + set path [ttk::frame $path] + } else { + set path [frame $path -takefocus 0 -highlightthickness 0] + } + set top [winfo parent $path] + if { ![string equal [winfo toplevel $path] $top] } { + destroy $path + return -code error "parent must be a toplevel" + } + Widget::init MainFrame $path $args + + if { $tcl_platform(platform) == "unix" } { + set relief raised + set bd 1 + } else { + set relief flat + set bd 0 + } + if {[Widget::theme]} { + set userframe [eval [list ttk::frame $path.frame] \ + [Widget::subcget $path .frame]] + set topframe [ttk::frame $path.topf] + set botframe [ttk::frame $path.botf] + } else { + set userframe [eval [list frame $path.frame] \ + [Widget::subcget $path .frame] \ + -relief $relief -borderwidth $bd] + set topframe [eval [list frame $path.topf] \ + [Widget::subcget $path .topf]] + set botframe [eval [list frame $path.botf] \ + -relief $relief -borderwidth $bd \ + [Widget::subcget $path .botf]] + } + + pack $topframe -fill x + grid columnconfigure $topframe 0 -weight 1 + + if {![Widget::theme]} { + set bg [Widget::cget $path -background] + $path configure -background $bg + } + if { $tcl_platform(platform) != "unix" } { + set sepopt [Widget::getoption $path -separator] + if { $sepopt == "both" || $sepopt == "top" } { + if {[Widget::theme]} { + set sep [ttk::separator $path.sep -orient horizontal] + } else { + set sep [Separator::create $path.sep -orient horizontal -background $bg] + } + pack $sep -fill x + } + if { $sepopt == "both" || $sepopt == "bottom" } { + if {[Widget::theme]} { + set sep [ttk::separator $botframe.sep -orient horizontal] + } else { + set sep [Separator::create $botframe.sep -orient horizontal -background $bg] + } + pack $sep -fill x + } + } + + # --- status bar --------------------------------------------------------- + if {[string length [Widget::getoption $path -statusbarfont]]} { + set sbfnt [list -font [Widget::getoption $path -statusbarfont]] + } else { + set sbfnt "" + } + + if {[Widget::theme]} { + set status [ttk::frame $path.status] + set label [eval [list ttk::label $status.label \ + -textvariable [Widget::getoption $path -textvariable]] $sbfnt] + set indframe [ttk::frame $status.indf] + set prgframe [ttk::frame $status.prgf] + } else { + set status [frame $path.status -background $bg] + set label [eval [list label $status.label \ + -textvariable [Widget::getoption $path -textvariable] \ + -background $bg] $sbfnt] + set indframe [frame $status.indf -background $bg] + set prgframe [frame $status.prgf -background $bg] + } + + place $label -anchor w -x 0 -rely 0.5 + place $indframe -anchor ne -relx 1 -y 0 -relheight 1 + pack $prgframe -in $indframe -side left -padx 2 + $status configure -height [winfo reqheight $label] + + set progress [eval [list ProgressBar::create $status.prg] \ + [Widget::subcget $path .status.prg] \ + -width 50 \ + -height [expr {[winfo reqheight $label]-2}] \ + -borderwidth 1 \ + -relief sunken] + pack $status -in $botframe -fill x -pady 2 + pack $botframe -side bottom -fill x + pack $userframe -fill both -expand yes + + set _widget($path,top) $top + set _widget($path,ntoolbar) 0 + set _widget($path,nindic) 0 + + set menu [Widget::getoption $path -menu] + if { [llength $menu] } { + _create_menubar $path $menu + } + + bind $path <Destroy> [list MainFrame::_destroy %W] + + return [Widget::create MainFrame $path] +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::configure +# ---------------------------------------------------------------------------- +proc MainFrame::configure { path args } { + variable _widget + + set res [Widget::configure $path $args] + + if { [Widget::hasChanged $path -textvariable newv] } { + uplevel \#0 $path.status.label configure -textvariable [list $newv] + } + + # The ttk frame has no -background + if {![Widget::theme] && [Widget::hasChanged $path -background bg] } { + if {$::tcl_platform(platform) == "unix"} { + set listmenu [$_widget($path,top) cget -menu] + while { [llength $listmenu] } { + set newlist {} + foreach menu $listmenu { + $menu configure -background $bg + set newlist [concat $newlist [winfo children $menu]] + } + set listmenu $newlist + } + } + foreach sep {.sep .botf.sep} { + if {[winfo exists $path.$sep]} { + Separator::configure $path.$sep -background $bg + } + } + foreach w [winfo children $path.topf] { + $w configure -background $bg + } + } + + if { [Widget::hasChanged $path -menubarfont newmbfnt] } { + if {[string length $newmbfnt]} { + set mbfnt [list -font $newmbfnt] + } else { + set mbfnt "" + } + set top $_widget($path,top) + if {[string equal $top .]} { + eval [list .menubar configure] $mbfnt + } else { + eval [list $top.menubar configure] $mbfnt + } + } + if { [Widget::hasChanged $path -menuentryfont newmefnt] } { + if {[string length $newmefnt]} { + set mefnt [list -font $newmefnt] + } else { + set mefnt "" + } + set top $_widget($path,top) + if {[string equal $top .]} { + set mb .menubar + } else { + set mb $top.menubar + } + set l [winfo children $mb] + while {[llength $l]} { + set e [lindex $l 0] + set l [lrange $l 1 end] + if {[string length $e] == 0} {continue} + lappend l [winfo children $e] + eval [list $e configure] $mefnt + } + } + + + if { [Widget::hasChanged $path -statusbarfont newsbfnt] } { + if {[string length $newsbfnt]} { + set sbfnt [list -font $newsbfnt] + } else { + set sbfnt "" + } + for {set index 0} {$index<$_widget($path,nindic)} {incr index} { + set indic $path.status.indf.f$index + eval [list $indic configure] $sbfnt + } + eval [list $path.status.label configure] $sbfnt + $path.status configure -height [winfo reqheight $path.status.label] + + $path.status.prg configure \ + -height [expr {[winfo reqheight $path.status.label]-2}] + } + + return $res +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::cget +# ---------------------------------------------------------------------------- +proc MainFrame::cget { path option } { + return [Widget::cget $path $option] +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::getframe +# ---------------------------------------------------------------------------- +proc MainFrame::getframe { path } { + return $path.frame +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::addtoolbar +# ---------------------------------------------------------------------------- +proc MainFrame::addtoolbar { path } { + global tcl_platform + variable _widget + + set index $_widget($path,ntoolbar) + set toolframe $path.topf.f$index + set toolbar $path.topf.tb$index + set bg [Widget::getoption $path -background] + if { $tcl_platform(platform) == "unix" } { + if {[Widget::theme]} { + ttk::frame $toolframe -padding 1 + } else { + frame $toolframe -relief raised -borderwidth 1 \ + -takefocus 0 -highlightthickness 0 -background $bg + } + } else { + if {[Widget::theme]} { + ttk::frame $toolframe + set sep [ttk::separator $toolframe.sep -orient horizontal] + } else { + frame $toolframe -relief flat -borderwidth 0 -takefocus 0 \ + -highlightthickness 0 -background $bg + set sep [Separator::create $toolframe.sep -orient horizontal -background $bg] + } + pack $sep -fill x + } + if {[Widget::theme]} { + set toolbar [ttk::frame $toolbar -padding 2] + } else { + set toolbar [frame $toolbar -relief flat -borderwidth 2 \ + -takefocus 0 -highlightthickness 0 -background $bg] + } + pack $toolbar -in $toolframe -anchor w -expand yes -fill x + incr _widget($path,ntoolbar) + grid $toolframe -column 0 -row $index -sticky ew + return $toolbar +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::gettoolbar +# ---------------------------------------------------------------------------- +proc MainFrame::gettoolbar { path index } { + return $path.topf.tb$index +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::addindicator +# ---------------------------------------------------------------------------- +proc MainFrame::addindicator { path args } { + variable _widget + + if {[string length [Widget::getoption $path -statusbarfont]]} { + set sbfnt [list -font [Widget::getoption $path -statusbarfont]] + } else { + set sbfnt "" + } + + set index $_widget($path,nindic) + set indic $path.status.indf.f$index + eval [list label $indic] $args -relief sunken -borderwidth 1 \ + -takefocus 0 -highlightthickness 0 $sbfnt + + pack $indic -side left -anchor w -padx 2 -fill y -expand 1 + + incr _widget($path,nindic) + + return $indic +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::getindicator +# ---------------------------------------------------------------------------- +proc MainFrame::getindicator { path index } { + return $path.status.indf.f$index +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::getmenu +# ---------------------------------------------------------------------------- +proc MainFrame::getmenu { path menuid } { + variable _widget + + if { [info exists _widget($path,menuid,$menuid)] } { + return $_widget($path,menuid,$menuid) + } + return "" +} + + +# ----------------------------------------------------------------------------- +# Command MainFrame::setmenustate +# ----------------------------------------------------------------------------- +proc MainFrame::setmenustate { path tag state } { + variable _widget + + # Set menustate to enabled when ALL of its tags are enabled. + + # First see if this is a real tag + if { [info exists _widget($path,tagstate,$tag)] } { + if { ![string equal $state "disabled"] } { + set _widget($path,tagstate,$tag) 1 + } else { + set _widget($path,tagstate,$tag) 0 + } + foreach {menu entry} $_widget($path,tags,$tag) { + set expression "1" + foreach menutag $_widget($path,menutags,[list $menu $entry]) { + append expression " && $_widget($path,tagstate,$menutag)" + } + if { [expr $expression] } { + set state normal + } else { + set state disabled + } + $menu entryconfigure $entry -state $state + } + } + return +} + +# ----------------------------------------------------------------------------- +# Command MainFrame::getmenustate +# ----------------------------------------------------------------------------- +proc MainFrame::getmenustate { path tag } { + variable _widget + + if {$_widget($path,tagstate,$tag)} { + return normal + } else { + return disabled + } +} + +# ----------------------------------------------------------------------------- +# Command MainFrame::menuonly +# ----------------------d------------------------------------------------------ +proc MainFrame::menuonly { path } { + variable _widget + + catch {pack forget $path.sep} + catch {pack forget $path.botf.sep} + catch {pack forget $path.frame} +} + +# ---------------------------------------------------------------------------- +# Command MainFrame::showtoolbar +# ---------------------------------------------------------------------------- +proc MainFrame::showtoolbar { path index bool } { + variable _widget + + set toolframe $path.topf.f$index + if { [winfo exists $toolframe] } { + if { !$bool && [llength [grid info $toolframe]] } { + grid forget $toolframe + $path.topf configure -height 1 + } elseif { $bool && ![llength [grid info $toolframe]] } { + grid $toolframe -column 0 -row $index -sticky ew + } + } +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::showstatusbar +# ---------------------------------------------------------------------------- +proc MainFrame::showstatusbar { path name } { + set status $path.status + set botframe $path.botf + if { [string equal $name "none"] } { + pack forget $status + } else { + pack $status -fill x -in $botframe -fill x -pady 2 + switch -- $name { + status { + catch {pack forget $status.prg} + } + progression { + pack $status.prg -in $status.prgf + } + } + } +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::_destroy +# ---------------------------------------------------------------------------- +proc MainFrame::_destroy { path } { + variable _widget + + Widget::destroy $path + catch {destroy [$_widget($path,top) cget -menu]} + $_widget($path,top) configure -menu {} + + # Unset all of the state vars associated with this main frame. + foreach index [array names _widget $path,*] { + unset _widget($index) + } +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::_create_menubar +# ---------------------------------------------------------------------------- +proc MainFrame::_create_menubar { path descmenu } { + variable _widget + global tcl_platform + + set top $_widget($path,top) + + foreach {v x} {mbfnt -menubarfont mefnt -menuentryfont} { + if {[string length [Widget::getoption $path $x]]} { + set $v [list -font [Widget::getoption $path $x]] + } else { + set $v "" + } + } + + if { ![Widget::theme] && $tcl_platform(platform) == "unix" + && [tk windowingsystem] !="aqua" } { + set menuopts [list -background [Widget::getoption $path -background] \ + -borderwidth 1] + } else { + set menuopts [list] + } + set menubar [eval [list menu $top.menubar -tearoff 0] $menuopts $mbfnt] + $top configure -menu $menubar + + set count 0 + foreach {name tags menuid tearoff entries} $descmenu { + set opt [_parse_name $name] + if {[string length $menuid] + && ![info exists _widget($path,menuid,$menuid)] } { + # menu has identifier + # we use it for its pathname, to enable special menu entries + # (help, system, ...) + set menu $menubar.$menuid + } else { + set menu $menubar.menu$count + } + eval [list $menubar add cascade] $opt [list -menu $menu] + eval [list menu $menu -tearoff $tearoff] $menuopts $mefnt + foreach tag $tags { + lappend _widget($path,tags,$tag) $menubar $count + # ericm@scriptics: Add a tagstate tracker + if { ![info exists _widget($path,tagstate,$tag)] } { + set _widget($path,tagstate,$tag) 1 + } + } + # ericm@scriptics: Add mapping from menu items to tags + set _widget($path,menutags,[list $menubar $count]) $tags + + if { [string length $menuid] } { + # menu has identifier + set _widget($path,menuid,$menuid) $menu + } + _create_entries $path $menu $menuopts $entries + incr count + } +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::_create_entries +# ---------------------------------------------------------------------------- +proc MainFrame::_create_entries { path menu menuopts entries } { + variable _widget + + set count [$menu cget -tearoff] + set registered 0 + foreach entry $entries { + set len [llength $entry] + set type [lindex $entry 0] + + if { [string equal $type "separator"] } { + $menu add separator + incr count + continue + } + + # entry name and tags + set opt [_parse_name [lindex $entry 1]] + set tags [lindex $entry 2] + foreach tag $tags { + lappend _widget($path,tags,$tag) $menu $count + # ericm@scriptics: Add a tagstate tracker + if { ![info exists _widget($path,tagstate,$tag)] } { + set _widget($path,tagstate,$tag) 1 + } + } + # ericm@scriptics: Add mapping from menu items to tags + set _widget($path,menutags,[list $menu $count]) $tags + + if {[string equal $type "cascade"] || [string equal $type "cascad"]} { + set menuid [lindex $entry 3] + set tearoff [lindex $entry 4] + set submenu $menu.menu$count + eval [list $menu add cascade] $opt [list -menu $submenu] + eval [list menu $submenu -tearoff $tearoff] $menuopts + if { [string length $menuid] } { + # menu has identifier + set _widget($path,menuid,$menuid) $submenu + } + _create_entries $path $submenu $menuopts [lindex $entry 5] + incr count + continue + } + + # entry help description + set desc [lindex $entry 3] + if { [string length $desc] } { + if { !$registered } { + DynamicHelp::register $menu menu [Widget::getoption $path -textvariable] + set registered 1 + } + DynamicHelp::register $menu menuentry $count $desc + } + + # entry accelerator + set accel [_parse_accelerator [lindex $entry 4]] + if { [llength $accel] } { + lappend opt -accelerator [lindex $accel 0] + bind $_widget($path,top) [lindex $accel 1] [list $menu invoke $count] + } + + # user options + set useropt [lrange $entry 5 end] + if { [string equal $type "command"] || + [string equal $type "radiobutton"] || + [string equal $type "checkbutton"] } { + eval [list $menu add $type] $opt $useropt + } else { + return -code error "invalid menu type \"$type\"" + } + incr count + } +} + + +# ---------------------------------------------------------------------------- +# Command MainFrame::_parse_name +# ---------------------------------------------------------------------------- +proc MainFrame::_parse_name { menuname } { + set idx [string first "&" $menuname] + if { $idx == -1 } { + return [list -label $menuname] + } else { + set beg [string range $menuname 0 [expr {$idx-1}]] + set end [string range $menuname [expr {$idx+1}] end] + append beg $end + return [list -label $beg -underline $idx] + } +} + + +# MainFrame::_parse_accelerator -- +# +# Given a key combo description, construct an appropriate human readable +# string (for display on as a menu accelerator) and the corresponding +# bind event. +# +# Arguments: +# desc a list with the following format: +# ?sequence? key +# sequence may be None, Ctrl, Alt, or CtrlAlt +# key may be any key +# +# Results: +# {accel event} a list containing the accelerator string and the event + +proc MainFrame::_parse_accelerator { desc } { + if { [llength $desc] == 1 } { + set seq None + set key [string tolower [lindex $desc 0]] + # If the key is an F key (ie, F1, F2, etc), it has to be capitalized + if {[regexp {^f([1-9]|([12][0-9]|3[0-5]))$} $key]} { + set key [string toupper $key] + } + } elseif { [llength $desc] == 2 } { + set seq [lindex $desc 0] + set key [string tolower [lindex $desc 1]] + # If the key is an F key (ie, F1, F2, etc), it has to be capitalized + if {[regexp {^f([1-9]|([12][0-9]|3[0-5]))$} $key]} { + set key [string toupper $key] + } + } else { + return {} + } + switch -- $seq { + None { + set accel "[string toupper $key]" + set event "<Key-$key>" + } + Ctrl { + set accel "Ctrl+[string toupper $key]" + set event "<Control-Key-$key>" + } + Alt { + set accel "Alt+[string toupper $key]" + set event "<Alt-Key-$key>" + } + CtrlAlt { + set accel "Ctrl+Alt+[string toupper $key]" + set event "<Control-Alt-Key-$key>" + } + default { + return -code error "invalid accelerator code $seq" + } + } + return [list $accel $event] +} diff --git a/modules/tclsci/tcl/BWidget/messagedlg.tcl b/modules/tclsci/tcl/BWidget/messagedlg.tcl new file mode 100755 index 000000000..effe6ed90 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/messagedlg.tcl @@ -0,0 +1,128 @@ +# ------------------------------------------------------------------------------ +# messagedlg.tcl +# This file is part of Unifix BWidget Toolkit +# ------------------------------------------------------------------------------ +# Index of commands: +# - MessageDlg::create +# ------------------------------------------------------------------------------ + +namespace eval MessageDlg { + Widget::define MessageDlg messagedlg Dialog + + Widget::tkinclude MessageDlg message .frame.msg \ + remove [list -cursor -highlightthickness \ + -highlightbackground -highlightcolor \ + -relief -borderwidth -takefocus -textvariable \ + ] \ + rename [list -text -message] \ + initialize [list -aspect 800 -anchor c -justify center] + + Widget::bwinclude MessageDlg Dialog :cmd \ + remove [list -modal -image -bitmap -side -anchor -separator \ + -homogeneous -padx -pady -spacing] + + Widget::declare MessageDlg { + {-icon Enum info 0 {none error info question warning}} + {-type Enum user 0 {abortretryignore ok okcancel \ + retrycancel yesno yesnocancel user}} + {-buttons String "" 0} + {-buttonwidth String 0 0} + } + + Widget::addmap MessageDlg "" tkMBox { + -parent {} -message {} -default {} -title {} + } +} + + +# ------------------------------------------------------------------------------ +# Command MessageDlg::create +# ------------------------------------------------------------------------------ +proc MessageDlg::create { path args } { + global tcl_platform + + array set maps [list MessageDlg {} :cmd {} .frame.msg {} tkMBox {}] + array set maps [Widget::parseArgs MessageDlg $args] + Widget::initFromODB MessageDlg "$path#Message" $maps(MessageDlg) + + array set dialogArgs $maps(:cmd) + + set type [Widget::cget "$path#Message" -type] + set icon [Widget::cget "$path#Message" -icon] + set width [Widget::cget "$path#Message" -buttonwidth] + + set defb -1 + set canb -1 + switch -- $type { + abortretryignore {set lbut {abort retry ignore}; set defb 0} + ok {set lbut {ok}; set defb 0 } + okcancel {set lbut {ok cancel}; set defb 0; set canb 1} + retrycancel {set lbut {retry cancel}; set defb 0; set canb 1} + yesno {set lbut {yes no}; set defb 0; set canb 1} + yesnocancel {set lbut {yes no cancel}; set defb 0; set canb 2} + user {set lbut [Widget::cget "$path#Message" -buttons]} + } + + # If the user didn't specify a default button, use our type-specific + # default, adding its flag/value to the "user" settings and to the tkMBox + # settings + if { ![info exists dialogArgs(-default)] } { + lappend maps(:cmd) -default $defb + lappend maps(tkMBox) -default $defb + } + if { ![info exists dialogArgs(-cancel)] } { + lappend maps(:cmd) -cancel $canb + } + + # Same with title as with default + if { ![info exists dialogArgs(-title)] } { + set frame [frame $path -class MessageDlg] + set title [option get $frame "${icon}Title" MessageDlg] + destroy $frame + if { $title == "" } { + set title "Message" + } + lappend maps(:cmd) -title $title + lappend maps(tkMBox) -title $title + } + + # Create the "user" type dialog + if { $type == "user" } { + if { $icon != "none" } { + set image [Bitmap::get $icon] + } else { + set image "" + } + eval [list Dialog::create $path] $maps(:cmd) \ + [list -image $image -modal local -side bottom -anchor e] + foreach but $lbut { + Dialog::add $path -text $but -name $but -width $width + } + set frame [Dialog::getframe $path] + + eval [list message $frame.msg] $maps(.frame.msg) \ + [list -relief flat -borderwidth 0 -highlightthickness 0 \ + -textvariable ""] + pack $frame.msg -side left -padx 3m -pady 1m -fill x -expand yes + + set res [Dialog::draw $path] + destroy $path + } else { + # Do some translation of args into tk_messageBox syntax, then create + # the tk_messageBox + array set tkMBoxArgs $maps(tkMBox) + set tkMBoxArgs(-default) [lindex $lbut $tkMBoxArgs(-default)] + if { ![string equal $icon "none"] } { + set tkMBoxArgs(-icon) $icon + } + if {[info exists tkMBoxArgs(-parent)] + && ![winfo exists $tkMBoxArgs(-parent)]} { + unset tkMBoxArgs(-parent) + } + set tkMBoxArgs(-type) $type + set res [eval [list tk_messageBox] [array get tkMBoxArgs]] + set res [lsearch $lbut $res] + } + Widget::destroy "$path#Message" + return $res +} diff --git a/modules/tclsci/tcl/BWidget/notebook.tcl b/modules/tclsci/tcl/BWidget/notebook.tcl new file mode 100755 index 000000000..f5532a4be --- /dev/null +++ b/modules/tclsci/tcl/BWidget/notebook.tcl @@ -0,0 +1,1166 @@ +# --------------------------------------------------------------------------- +# notebook.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: notebook.tcl,v 1.25.2.1 2009/08/10 11:28:50 oehhar Exp $ +# --------------------------------------------------------------------------- +# Index of commands: +# - NoteBook::create +# - NoteBook::configure +# - NoteBook::cget +# - NoteBook::compute_size +# - NoteBook::insert +# - NoteBook::delete +# - NoteBook::itemconfigure +# - NoteBook::itemcget +# - NoteBook::bindtabs +# - NoteBook::raise +# - NoteBook::see +# - NoteBook::page +# - NoteBook::pages +# - NoteBook::index +# - NoteBook::getframe +# - NoteBook::_test_page +# - NoteBook::_itemconfigure +# - NoteBook::_compute_width +# - NoteBook::_get_x_page +# - NoteBook::_xview +# - NoteBook::_highlight +# - NoteBook::_select +# - NoteBook::_redraw +# - NoteBook::_draw_page +# - NoteBook::_draw_arrows +# - NoteBook::_draw_area +# - NoteBook::_resize +# --------------------------------------------------------------------------- + +namespace eval NoteBook { + Widget::define NoteBook notebook ArrowButton DynamicHelp + + namespace eval Page { + Widget::declare NoteBook::Page { + {-state Enum normal 0 {normal disabled}} + {-createcmd String "" 0} + {-raisecmd String "" 0} + {-leavecmd String "" 0} + {-image TkResource "" 0 label} + {-text String "" 0} + {-foreground String "" 0} + {-background String "" 0} + {-activeforeground String "" 0} + {-activebackground String "" 0} + {-disabledforeground String "" 0} + } + } + + DynamicHelp::include NoteBook::Page balloon + + Widget::bwinclude NoteBook ArrowButton .c.fg \ + include {-foreground -background -activeforeground \ + -activebackground -disabledforeground -repeatinterval \ + -repeatdelay -borderwidth} \ + initialize {-borderwidth 1} + Widget::bwinclude NoteBook ArrowButton .c.fd \ + include {-foreground -background -activeforeground \ + -activebackground -disabledforeground -repeatinterval \ + -repeatdelay -borderwidth} \ + initialize {-borderwidth 1} + + Widget::declare NoteBook { + {-foreground TkResource "" 0 button} + {-background TkResource "" 0 button} + {-activebackground TkResource "" 0 button} + {-activeforeground TkResource "" 0 button} + {-disabledforeground TkResource "" 0 button} + {-font TkResource "" 0 button} + {-side Enum top 0 {top bottom}} + {-homogeneous Boolean 0 0} + {-borderwidth Int 1 0 "%d >= 1 && %d <= 2"} + {-internalborderwidth Int 10 0 "%d >= 0"} + {-width Int 0 0 "%d >= 0"} + {-height Int 0 0 "%d >= 0"} + + {-repeatdelay BwResource "" 0 ArrowButton} + {-repeatinterval BwResource "" 0 ArrowButton} + + {-fg Synonym -foreground} + {-bg Synonym -background} + {-bd Synonym -borderwidth} + {-ibd Synonym -internalborderwidth} + + {-arcradius Int 2 0 "%d >= 0 && %d <= 8"} + {-tabbevelsize Int 0 0 "%d >= 0 && %d <= 8"} + {-tabpady Padding {0 6} 0 "%d >= 0"} + } + + Widget::addmap NoteBook "" .c {-background {}} + + variable _warrow 12 + + bind NoteBook <Configure> [list NoteBook::_resize %W] + bind NoteBook <Destroy> [list NoteBook::_destroy %W] +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::create +# --------------------------------------------------------------------------- +proc NoteBook::create { path args } { + variable $path + upvar 0 $path data + + Widget::init NoteBook $path $args + + set data(base) 0 + set data(select) "" + set data(pages) {} + set data(pages) {} + set data(cpt) 0 + set data(realized) 0 + set data(wpage) 0 + + _compute_height $path + + # Create the canvas + set w [expr {[Widget::cget $path -width]+4}] + set h [expr {[Widget::cget $path -height]+$data(hpage)+4}] + + frame $path -class NoteBook -borderwidth 0 -highlightthickness 0 \ + -relief flat + eval [list canvas $path.c] [Widget::subcget $path .c] \ + [list -relief flat -borderwidth 0 -highlightthickness 0 \ + -width $w -height $h] + pack $path.c -expand yes -fill both + + # Removing the Canvas global bindings from our canvas as + # application specific bindings on that tag may interfere with its + # operation here. [SF item #459033] + + set bindings [bindtags $path.c] + set pos [lsearch -exact $bindings Canvas] + if {$pos >= 0} { + set bindings [lreplace $bindings $pos $pos] + } + bindtags $path.c $bindings + + # Create the arrow button + eval [list ArrowButton::create $path.c.fg] [Widget::subcget $path .c.fg] \ + [list -highlightthickness 0 -type button -dir left \ + -armcommand [list NoteBook::_xview $path -1]] + + eval [list ArrowButton::create $path.c.fd] [Widget::subcget $path .c.fd] \ + [list -highlightthickness 0 -type button -dir right \ + -armcommand [list NoteBook::_xview $path 1]] + + Widget::create NoteBook $path + + set bg [Widget::cget $path -background] + foreach {data(dbg) data(lbg)} [BWidget::get3dcolor $path $bg] {break} + + return $path +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::configure +# --------------------------------------------------------------------------- +proc NoteBook::configure { path args } { + variable $path + upvar 0 $path data + + set res [Widget::configure $path $args] + set redraw 0 + set opts [list -font -homogeneous -tabpady] + foreach {cf ch cp} [eval Widget::hasChangedX $path $opts] {break} + if {$cf || $ch || $cp} { + if { $cf || $cp } { + _compute_height $path + } + _compute_width $path + set redraw 1 + } + set chibd [Widget::hasChanged $path -internalborderwidth ibd] + set chbg [Widget::hasChanged $path -background bg] + if {$chibd || $chbg} { + foreach page $data(pages) { + $path.f$page configure \ + -borderwidth $ibd -background $bg + } + } + + if {$chbg} { + set col [BWidget::get3dcolor $path $bg] + set data(dbg) [lindex $col 0] + set data(lbg) [lindex $col 1] + set redraw 1 + } + if { [Widget::hasChanged $path -foreground fg] || + [Widget::hasChanged $path -borderwidth bd] || + [Widget::hasChanged $path -arcradius radius] || + [Widget::hasChanged $path -tabbevelsize bevel] || + [Widget::hasChanged $path -side side] } { + set redraw 1 + } + set wc [Widget::hasChanged $path -width w] + set hc [Widget::hasChanged $path -height h] + if { $wc || $hc } { + $path.c configure \ + -width [expr {$w + 4}] \ + -height [expr {$h + $data(hpage) + 4}] + } + if { $redraw } { + _redraw $path + } + + return $res +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::cget +# --------------------------------------------------------------------------- +proc NoteBook::cget { path option } { + return [Widget::cget $path $option] +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::compute_size +# --------------------------------------------------------------------------- +proc NoteBook::compute_size { path } { + variable $path + upvar 0 $path data + + set wmax 0 + set hmax 0 + update idletasks + foreach page $data(pages) { + set w [winfo reqwidth $path.f$page] + set h [winfo reqheight $path.f$page] + set wmax [expr {$w>$wmax ? $w : $wmax}] + set hmax [expr {$h>$hmax ? $h : $hmax}] + } + configure $path -width $wmax -height $hmax + # Sven... well ok so this is called twice in some cases... + NoteBook::_redraw $path + # Sven end +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::insert +# --------------------------------------------------------------------------- +proc NoteBook::insert { path index page args } { + variable $path + upvar 0 $path data + + if { [lsearch -exact $data(pages) $page] != -1 } { + return -code error "page \"$page\" already exists" + } + + set f $path.f$page + Widget::init NoteBook::Page $f $args + + set data(pages) [linsert $data(pages) $index $page] + # If the page doesn't exist, create it; if it does reset its bg and ibd + if { ![winfo exists $f] } { + frame $f \ + -relief flat \ + -background [Widget::cget $path -background] \ + -borderwidth [Widget::cget $path -internalborderwidth] + set data($page,realized) 0 + } else { + $f configure \ + -background [Widget::cget $path -background] \ + -borderwidth [Widget::cget $path -internalborderwidth] + } + _compute_height $path + _compute_width $path + _draw_page $path $page 1 + _set_help $path $page + _redraw $path + + return $f +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::delete +# --------------------------------------------------------------------------- +proc NoteBook::delete { path page {destroyframe 1} } { + variable $path + upvar 0 $path data + + set pos [_test_page $path $page] + set data(pages) [lreplace $data(pages) $pos $pos] + _compute_width $path + $path.c delete p:$page + if { $data(select) == $page } { + set data(select) "" + } + if { $pos < $data(base) } { + incr data(base) -1 + } + if { $destroyframe } { + destroy $path.f$page + unset data($page,width) data($page,realized) + } + _redraw $path +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::itemconfigure +# --------------------------------------------------------------------------- +proc NoteBook::itemconfigure { path page args } { + _test_page $path $page + set res [_itemconfigure $path $page $args] + _redraw $path + + return $res +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::itemcget +# --------------------------------------------------------------------------- +proc NoteBook::itemcget { path page option } { + _test_page $path $page + return [Widget::cget $path.f$page $option] +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::bindtabs +# --------------------------------------------------------------------------- +proc NoteBook::bindtabs { path event script } { + if { $script != "" } { + append script " \[NoteBook::_get_page_name [list $path] current 1\]" + $path.c bind "page" $event $script + } else { + $path.c bind "page" $event {} + } +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::move +# --------------------------------------------------------------------------- +proc NoteBook::move { path page index } { + variable $path + upvar 0 $path data + + set pos [_test_page $path $page] + set data(pages) [linsert [lreplace $data(pages) $pos $pos] $index $page] + _redraw $path +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::raise +# --------------------------------------------------------------------------- +proc NoteBook::raise { path {page ""} } { + variable $path + upvar 0 $path data + + if { $page != "" } { + _test_page $path $page + _select $path $page + } + return $data(select) +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::see +# --------------------------------------------------------------------------- +proc NoteBook::see { path page } { + variable $path + upvar 0 $path data + + set pos [_test_page $path $page] + if { $pos < $data(base) } { + set data(base) $pos + _redraw $path + } else { + set w [expr {[winfo width $path]-1}] + set fpage [expr {[_get_x_page $path $pos] + $data($page,width) + 6}] + set idx $data(base) + while { $idx < $pos && $fpage > $w } { + set fpage [expr {$fpage - $data([lindex $data(pages) $idx],width)}] + incr idx + } + if { $idx != $data(base) } { + set data(base) $idx + _redraw $path + } + } +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::page +# --------------------------------------------------------------------------- +proc NoteBook::page { path first {last ""} } { + variable $path + upvar 0 $path data + + if { $last == "" } { + return [lindex $data(pages) $first] + } else { + return [lrange $data(pages) $first $last] + } +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::pages +# --------------------------------------------------------------------------- +proc NoteBook::pages { path {first ""} {last ""}} { + variable $path + upvar 0 $path data + + if { ![string length $first] } { + return $data(pages) + } + + if { ![string length $last] } { + return [lindex $data(pages) $first] + } else { + return [lrange $data(pages) $first $last] + } +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::index +# --------------------------------------------------------------------------- +proc NoteBook::index { path page } { + variable $path + upvar 0 $path data + + return [lsearch -exact $data(pages) $page] +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::_destroy +# --------------------------------------------------------------------------- +proc NoteBook::_destroy { path } { + variable $path + upvar 0 $path data + + foreach page $data(pages) { + Widget::destroy $path.f$page + } + Widget::destroy $path + unset data +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::getframe +# --------------------------------------------------------------------------- +proc NoteBook::getframe { path page } { + return $path.f$page +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::_test_page +# --------------------------------------------------------------------------- +proc NoteBook::_test_page { path page } { + variable $path + upvar 0 $path data + + if { [set pos [lsearch -exact $data(pages) $page]] == -1 } { + return -code error "page \"$page\" does not exists" + } + return $pos +} + +proc NoteBook::_getoption { path page option } { + set value [Widget::cget $path.f$page $option] + if {![string length $value]} { + set value [Widget::cget $path $option] + } + return $value +} + +# --------------------------------------------------------------------------- +# Command NoteBook::_itemconfigure +# --------------------------------------------------------------------------- +proc NoteBook::_itemconfigure { path page lres } { + variable $path + upvar 0 $path data + + set res [Widget::configure $path.f$page $lres] + if { [Widget::hasChanged $path.f$page -text foo] } { + _compute_width $path + } elseif { [Widget::hasChanged $path.f$page -image foo] } { + _compute_height $path + _compute_width $path + } + if { [Widget::hasChanged $path.f$page -state state] && + $state == "disabled" && $data(select) == $page } { + set data(select) "" + } + _set_help $path $page + return $res +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::_compute_width +# --------------------------------------------------------------------------- +proc NoteBook::_compute_width { path } { + variable $path + upvar 0 $path data + + set wmax 0 + set wtot 0 + set hmax $data(hpage) + set font [Widget::cget $path -font] + if { ![info exists data(textid)] } { + set data(textid) [$path.c create text 0 -100 -font $font -anchor nw] + } + set id $data(textid) + $path.c itemconfigure $id -font $font + foreach page $data(pages) { + $path.c itemconfigure $id -text [Widget::cget $path.f$page -text] + # Get the bbox for this text to determine its width, then substract + # 6 from the width to account for canvas bbox oddness w.r.t. widths of + # simple text. + foreach {x1 y1 x2 y2} [$path.c bbox $id] break + set x2 [expr {$x2 - 6}] + set wtext [expr {$x2 - $x1 + 20}] + if { [set img [Widget::cget $path.f$page -image]] != "" } { + set wtext [expr {$wtext + [image width $img] + 4}] + set himg [expr {[image height $img] + 6}] + if { $himg > $hmax } { + set hmax $himg + } + } + set wmax [expr {$wtext > $wmax ? $wtext : $wmax}] + incr wtot $wtext + set data($page,width) $wtext + } + if { [Widget::cget $path -homogeneous] } { + foreach page $data(pages) { + set data($page,width) $wmax + } + set wtot [expr {$wmax * [llength $data(pages)]}] + } + set data(hpage) $hmax + set data(wpage) $wtot +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::_compute_height +# --------------------------------------------------------------------------- +proc NoteBook::_compute_height { path } { + variable $path + upvar 0 $path data + + set font [Widget::cget $path -font] + set pady0 [Widget::_get_padding $path -tabpady 0] + set pady1 [Widget::_get_padding $path -tabpady 1] + set metrics [font metrics $font -linespace] + set imgh 0 + set lines 1 + foreach page $data(pages) { + set img [Widget::cget $path.f$page -image] + set text [Widget::cget $path.f$page -text] + set len [llength [split $text \n]] + if {$len > $lines} { set lines $len} + if {$img != ""} { + set h [image height $img] + if {$h > $imgh} { set imgh $h } + } + } + set height [expr {$metrics * $lines}] + if {$imgh > $height} { set height $imgh } + set data(hpage) [expr {$height + $pady0 + $pady1}] +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::_get_x_page +# --------------------------------------------------------------------------- +proc NoteBook::_get_x_page { path pos } { + variable _warrow + variable $path + upvar 0 $path data + + set base $data(base) + # notebook tabs start flush with the left side of the notebook + set x 0 + if { $pos < $base } { + foreach page [lrange $data(pages) $pos [expr {$base-1}]] { + incr x [expr {-$data($page,width)}] + } + } elseif { $pos > $base } { + foreach page [lrange $data(pages) $base [expr {$pos-1}]] { + incr x $data($page,width) + } + } + return $x +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::_xview +# --------------------------------------------------------------------------- +proc NoteBook::_xview { path inc } { + variable $path + upvar 0 $path data + + if { $inc == -1 } { + set base [expr {$data(base)-1}] + set dx $data([lindex $data(pages) $base],width) + } else { + set dx [expr {-$data([lindex $data(pages) $data(base)],width)}] + set base [expr {$data(base)+1}] + } + + if { $base >= 0 && $base < [llength $data(pages)] } { + set data(base) $base + $path.c move page $dx 0 + _draw_area $path + _draw_arrows $path + } +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::_highlight +# --------------------------------------------------------------------------- +proc NoteBook::_highlight { type path page } { + variable $path + upvar 0 $path data + + if { [string equal [Widget::cget $path.f$page -state] "disabled"] } { + return + } + + switch -- $type { + on { + $path.c itemconfigure "$page:poly" \ + -fill [_getoption $path $page -activebackground] + $path.c itemconfigure "$page:text" \ + -fill [_getoption $path $page -activeforeground] + } + off { + $path.c itemconfigure "$page:poly" \ + -fill [_getoption $path $page -background] + $path.c itemconfigure "$page:text" \ + -fill [_getoption $path $page -foreground] + } + } +} + + +# --------------------------------------------------------------------------- +# Command NoteBook::_select +# --------------------------------------------------------------------------- +proc NoteBook::_select { path page } { + variable $path + upvar 0 $path data + + if {![string equal [Widget::cget $path.f$page -state] "normal"]} { return } + + set oldsel $data(select) + + if {[string equal $page $oldsel]} { return } + + if { ![string equal $oldsel ""] } { + set cmd [Widget::cget $path.f$oldsel -leavecmd] + if { ![string equal $cmd ""] } { + set code [catch {uplevel \#0 $cmd} res] + if { $code == 1 || $res == 0 } { + return -code $code $res + } + } + set data(select) "" + _draw_page $path $oldsel 0 + } + + set data(select) $page + if { ![string equal $page ""] } { + if { !$data($page,realized) } { + set data($page,realized) 1 + set cmd [Widget::cget $path.f$page -createcmd] + if { ![string equal $cmd ""] } { + uplevel \#0 $cmd + } + } + set cmd [Widget::cget $path.f$page -raisecmd] + if { ![string equal $cmd ""] } { + uplevel \#0 $cmd + } + _draw_page $path $page 0 + } + + _draw_area $path +} + + +# ----------------------------------------------------------------------------- +# Command NoteBook::_redraw +# ----------------------------------------------------------------------------- +proc NoteBook::_redraw { path } { + variable $path + upvar 0 $path data + + if { !$data(realized) } { return } + + _compute_height $path + + foreach page $data(pages) { + _draw_page $path $page 0 + } + _draw_area $path + _draw_arrows $path +} + + +# ---------------------------------------------------------------------------- +# Command NoteBook::_draw_page +# ---------------------------------------------------------------------------- +proc NoteBook::_draw_page { path page create } { + variable $path + upvar 0 $path data + + # --- calcul des coordonnees et des couleurs de l'onglet ------------------ + set pos [lsearch -exact $data(pages) $page] + set bg [_getoption $path $page -background] + + # lookup the tab colors + set fgt $data(lbg) + set fgb $data(dbg) + + set h $data(hpage) + set xd [_get_x_page $path $pos] + set xf [expr {$xd + $data($page,width)}] + + # Set the initial text offsets -- a few pixels down, centered left-to-right + set textOffsetY [expr [Widget::_get_padding $path -tabpady 0] + 3] + set textOffsetX 9 + + # Coordinates of the tab corners are: + # c3 c4 + # + # c2 c5 + # + # c1 c6 + # + # where + # c1 = $xd, $h + # c2 = $xd+$xBevel, $arcRadius+2 + # c3 = $xd+$xBevel+$arcRadius, $arcRadius + # c4 = $xf+1-$xBevel, $arcRadius + # c5 = $xf+$arcRadius-$xBevel, $arcRadius+2 + # c6 = $xf+$arcRadius, $h + + set top 2 + set arcRadius [Widget::cget $path -arcradius] + set xBevel [Widget::cget $path -tabbevelsize] + + if { $data(select) != $page } { + if { $pos == 0 } { + # The leftmost page is a special case -- it is drawn with its + # tab a little indented. To achieve this, we incr xd. We also + # decr textOffsetX, so that the text doesn't move left/right. + incr xd 2 + incr textOffsetX -2 + } + } else { + # The selected page's text is raised higher than the others + incr top -2 + } + + # Precompute some coord values that we use a lot + set topPlusRadius [expr {$top + $arcRadius}] + set rightPlusRadius [expr {$xf + $arcRadius}] + set leftPlusRadius [expr {$xd + $arcRadius}] + + # Sven + set side [Widget::cget $path -side] + set tabsOnBottom [string equal $side "bottom"] + + set h1 [expr {[winfo height $path]}] + set bd [Widget::cget $path -borderwidth] + if {$bd < 1} { set bd 1 } + + if { $tabsOnBottom } { + # adjust to keep bottom edge in view + incr h1 -1 + set top [expr {$top * -1}] + set topPlusRadius [expr {$topPlusRadius * -1}] + # Hrm... the canvas has an issue with drawing diagonal segments + # of lines from the bottom to the top, so we have to draw this line + # backwards (ie, lt is actually the bottom, drawn from right to left) + set lt [list \ + $rightPlusRadius [expr {$h1-$h-1}] \ + [expr {$rightPlusRadius - $xBevel}] [expr {$h1 + $topPlusRadius}] \ + [expr {$xf - $xBevel}] [expr {$h1 + $top}] \ + [expr {$leftPlusRadius + $xBevel}] [expr {$h1 + $top}] \ + ] + set lb [list \ + [expr {$leftPlusRadius + $xBevel}] [expr {$h1 + $top}] \ + [expr {$xd + $xBevel}] [expr {$h1 + $topPlusRadius}] \ + $xd [expr {$h1-$h-1}] \ + ] + # Because we have to do this funky reverse order thing, we have to + # swap the top/bottom colors too. + set tmp $fgt + set fgt $fgb + set fgb $tmp + } else { + set lt [list \ + $xd $h \ + [expr {$xd + $xBevel}] $topPlusRadius \ + [expr {$leftPlusRadius + $xBevel}] $top \ + [expr {$xf + 1 - $xBevel}] $top \ + ] + set lb [list \ + [expr {$xf + 1 - $xBevel}] [expr {$top + 1}] \ + [expr {$rightPlusRadius - $xBevel}] $topPlusRadius \ + $rightPlusRadius $h \ + ] + } + + set img [Widget::cget $path.f$page -image] + + set ytext $top + if { $tabsOnBottom } { + # The "+ 2" below moves the text closer to the bottom of the tab, + # so it doesn't look so cramped. I should be able to achieve the + # same goal by changing the anchor of the text and using this formula: + # ytext = $top + $h1 - $textOffsetY + # but that doesn't quite work (I think the linespace from the text + # gets in the way) + incr ytext [expr {$h1 - $h + 2}] + } + incr ytext $textOffsetY + + set xtext [expr {$xd + $textOffsetX}] + if { $img != "" } { + # if there's an image, put it on the left and move the text right + set ximg $xtext + incr xtext [expr {[image width $img] + 2}] + } + + if { $data(select) == $page } { + set bd [Widget::cget $path -borderwidth] + if {$bd < 1} { set bd 1 } + set fg [_getoption $path $page -foreground] + } else { + set bd 1 + if { [Widget::cget $path.f$page -state] == "normal" } { + set fg [_getoption $path $page -foreground] + } else { + set fg [_getoption $path $page -disabledforeground] + } + } + + # --- creation ou modification de l'onglet -------------------------------- + # Sven + if { $create } { + # Create the tab region + eval [list $path.c create polygon] [concat $lt $lb] [list \ + -tags [list page p:$page $page:poly] \ + -outline $bg \ + -fill $bg \ + ] + eval [list $path.c create line] $lt [list \ + -tags [list page p:$page $page:top top] -fill $fgt -width $bd] + eval [list $path.c create line] $lb [list \ + -tags [list page p:$page $page:bot bot] -fill $fgb -width $bd] + $path.c create text $xtext $ytext \ + -text [Widget::cget $path.f$page -text] \ + -font [Widget::cget $path -font] \ + -fill $fg \ + -anchor nw \ + -tags [list page p:$page $page:text] + + $path.c bind p:$page <ButtonPress-1> \ + [list NoteBook::_select $path $page] + $path.c bind p:$page <Enter> \ + [list NoteBook::_highlight on $path $page] + $path.c bind p:$page <Leave> \ + [list NoteBook::_highlight off $path $page] + } else { + $path.c coords "$page:text" $xtext $ytext + + $path.c itemconfigure "$page:text" \ + -text [Widget::cget $path.f$page -text] \ + -font [Widget::cget $path -font] \ + -fill $fg + } + eval [list $path.c coords "$page:poly"] [concat $lt $lb] + eval [list $path.c coords "$page:top"] $lt + eval [list $path.c coords "$page:bot"] $lb + $path.c itemconfigure "$page:poly" -fill $bg -outline $bg + $path.c itemconfigure "$page:top" -fill $fgt -width $bd + $path.c itemconfigure "$page:bot" -fill $fgb -width $bd + + # Sven end + + if { $img != "" } { + # Sven + set id [$path.c find withtag $page:img] + if { [string equal $id ""] } { + set id [$path.c create image $ximg $ytext \ + -anchor nw \ + -tags [list page p:$page $page:img]] + } + $path.c coords $id $ximg $ytext + $path.c itemconfigure $id -image $img + # Sven end + } else { + $path.c delete $page:img + } + + if { $data(select) == $page } { + $path.c raise p:$page + } elseif { $pos == 0 } { + if { $data(select) == "" } { + $path.c raise p:$page + } else { + $path.c lower p:$page p:$data(select) + } + } else { + set pred [lindex $data(pages) [expr {$pos-1}]] + if { $data(select) != $pred || $pos == 1 } { + $path.c lower p:$page p:$pred + } else { + $path.c lower p:$page p:[lindex $data(pages) [expr {$pos-2}]] + } + } +} + + +# ----------------------------------------------------------------------------- +# Command NoteBook::_draw_arrows +# ----------------------------------------------------------------------------- +proc NoteBook::_draw_arrows { path } { + variable _warrow + variable $path + upvar 0 $path data + + set w [expr {[winfo width $path]-1}] + set h [expr {$data(hpage)-1}] + set nbpages [llength $data(pages)] + set xl 0 + set xr [expr {$w-$_warrow+1}] + # Sven + set side [Widget::cget $path -side] + if { [string equal $side "bottom"] } { + set h1 [expr {[winfo height $path]-1}] + set bd [Widget::cget $path -borderwidth] + if {$bd < 1} { set bd 1 } + set y0 [expr {$h1 - $data(hpage) + $bd}] + } else { + set y0 1 + } + # Sven end (all y positions where replaced with $y0 later) + + if { $data(base) > 0 } { + # Sven + if { ![llength [$path.c find withtag "leftarrow"]] } { + $path.c create window $xl $y0 \ + -width $_warrow \ + -height $h \ + -anchor nw \ + -window $path.c.fg \ + -tags "leftarrow" + } else { + $path.c coords "leftarrow" $xl $y0 + $path.c itemconfigure "leftarrow" -width $_warrow -height $h + } + # Sven end + } else { + $path.c delete "leftarrow" + } + + if { $data(base) < $nbpages-1 && + $data(wpage) + [_get_x_page $path 0] + 6 > $w } { + # Sven + if { ![llength [$path.c find withtag "rightarrow"]] } { + $path.c create window $xr $y0 \ + -width $_warrow \ + -height $h \ + -window $path.c.fd \ + -anchor nw \ + -tags "rightarrow" + } else { + $path.c coords "rightarrow" $xr $y0 + $path.c itemconfigure "rightarrow" -width $_warrow -height $h + } + # Sven end + } else { + $path.c delete "rightarrow" + } +} + + +# ----------------------------------------------------------------------------- +# Command NoteBook::_draw_area +# ----------------------------------------------------------------------------- +proc NoteBook::_draw_area { path } { + variable $path + upvar 0 $path data + + set w [expr {[winfo width $path] - 1}] + set h [expr {[winfo height $path] - 1}] + set bd [Widget::cget $path -borderwidth] + if {$bd < 1} { set bd 1 } + set x0 [expr {$bd - 1}] + + set arcRadius [Widget::cget $path -arcradius] + + # Sven + set side [Widget::cget $path -side] + if {"$side" == "bottom"} { + set y0 0 + set y1 [expr {$h - $data(hpage)}] + set yo $y1 + } else { + set y0 $data(hpage) + set y1 $h + set yo [expr {$h-$y0}] + } + # Sven end + set dbg $data(dbg) + set sel $data(select) + if { $sel == "" } { + set xd [expr {$w/2}] + set xf $xd + set lbg $data(dbg) + } else { + set xd [_get_x_page $path [lsearch -exact $data(pages) $data(select)]] + set xf [expr {$xd + $data($sel,width) + $arcRadius + 1}] + set lbg $data(lbg) + } + + # Sven + if { [llength [$path.c find withtag rect]] == 0} { + $path.c create line $xd $y0 $x0 $y0 $x0 $y1 \ + -tags "rect toprect1" + $path.c create line $w $y0 $xf $y0 \ + -tags "rect toprect2" + $path.c create line 1 $h $w $h $w $y0 \ + -tags "rect botrect" + } + if {"$side" == "bottom"} { + $path.c coords "toprect1" $w $y0 $x0 $y0 $x0 $y1 + $path.c coords "toprect2" $x0 $y1 $xd $y1 + $path.c coords "botrect" $xf $y1 $w $y1 $w $y0 + $path.c itemconfigure "toprect1" -fill $lbg -width $bd + $path.c itemconfigure "toprect2" -fill $dbg -width $bd + $path.c itemconfigure "botrect" -fill $dbg -width $bd + } else { + $path.c coords "toprect1" $xd $y0 $x0 $y0 $x0 $y1 + $path.c coords "toprect2" $w $y0 $xf $y0 + $path.c coords "botrect" $x0 $h $w $h $w $y0 + $path.c itemconfigure "toprect1" -fill $lbg -width $bd + $path.c itemconfigure "toprect2" -fill $lbg -width $bd + $path.c itemconfigure "botrect" -fill $dbg -width $bd + } + $path.c raise "rect" + # Sven end + + if { $sel != "" } { + # Sven + if { [llength [$path.c find withtag "window"]] == 0 } { + $path.c create window 2 [expr {$y0+1}] \ + -width [expr {$w-3}] \ + -height [expr {$yo-3}] \ + -anchor nw \ + -tags "window" \ + -window $path.f$sel + } + $path.c coords "window" 2 [expr {$y0+1}] + $path.c itemconfigure "window" \ + -width [expr {$w-3}] \ + -height [expr {$yo-3}] \ + -window $path.f$sel + # Sven end + } else { + $path.c delete "window" + } +} + + +# ----------------------------------------------------------------------------- +# Command NoteBook::_resize +# ----------------------------------------------------------------------------- +proc NoteBook::_resize { path } { + variable $path + upvar 0 $path data + + if {!$data(realized)} { + if { [set width [Widget::cget $path -width]] == 0 || + [set height [Widget::cget $path -height]] == 0 } { + compute_size $path + } + set data(realized) 1 + } + + NoteBook::_redraw $path +} + + +# Tree::_set_help -- +# +# Register dynamic help for a node in the tree. +# +# Arguments: +# path Tree to query +# node Node in the tree +# force Optional argument to force a reset of the help +# +# Results: +# none +# Tree::_set_help -- +# +# Register dynamic help for a node in the tree. +# +# Arguments: +# path Tree to query +# node Node in the tree +# force Optional argument to force a reset of the help +# +# Results: +# none +proc NoteBook::_set_help { path page } { + Widget::getVariable $path help + + set item $path.f$page + set opts [list -helptype -helptext -helpvar] + foreach {cty ctx cv} [eval [list Widget::hasChangedX $item] $opts] break + set text [Widget::getoption $item -helptext] + + ## If we've never set help for this item before, and text is not blank, + ## we need to setup help. We also need to reset help if any of the + ## options have changed. + if { (![info exists help($page)] && $text != "") || $cty || $ctx || $cv } { + set help($page) 1 + set type [Widget::getoption $item -helptype] + switch $type { + balloon { + DynamicHelp::register $path.c balloon p:$page $text + } + variable { + set var [Widget::getoption $item -helpvar] + DynamicHelp::register $path.c variable p:$page $var $text + } + } + } +} + + +proc NoteBook::_get_page_name { path {item current} {tagindex end-1} } { + return [string range [lindex [$path.c gettags $item] $tagindex] 2 end] +} diff --git a/modules/tclsci/tcl/BWidget/pagesmgr.tcl b/modules/tclsci/tcl/BWidget/pagesmgr.tcl new file mode 100755 index 000000000..d6ce1b626 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/pagesmgr.tcl @@ -0,0 +1,294 @@ +# ------------------------------------------------------------------------------ +# pagesmgr.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: pagesmgr.tcl,v 1.6 2003/10/20 21:23:52 damonc Exp $ +# ------------------------------------------------------------------------------ +# Index of commands: +# - PagesManager::create +# - PagesManager::configure +# - PagesManager::cget +# - PagesManager::compute_size +# - PagesManager::add +# - PagesManager::delete +# - PagesManager::raise +# - PagesManager::page +# - PagesManager::pages +# - PagesManager::getframe +# - PagesManager::_test_page +# - PagesManager::_select +# - PagesManager::_redraw +# - PagesManager::_draw_area +# - PagesManager::_realize +# ------------------------------------------------------------------------------ +package require Tcl 8.1.1 + +namespace eval PagesManager { + Widget::define PagesManager pagesmgr + + Widget::declare PagesManager { + {-background TkResource "" 0 frame} + {-cursor TkResource "" 0 frame} + {-width Int 0 0 "%d >= 0"} + {-height Int 0 0 "%d >= 0"} + } + + Widget::addmap PagesManager "" :cmd { -width {} -height {} -cursor {} } +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::create +# ------------------------------------------------------------------------------ +proc PagesManager::create { path args } { + variable $path + upvar 0 $path data + + Widget::init PagesManager $path $args + + set data(select) "" + set data(pages) {} + set data(cpt) 0 + set data(realized) 0 + + # --- creation du canvas ----------------------------------------------------------------- + eval canvas $path -relief flat -bd 0 -highlightthickness 0 \ + [Widget::subcget $path :cmd] + + bind $path <Configure> [list PagesManager::_realize $path] + bind $path <Destroy> [list PagesManager::_destroy $path] + + return [Widget::create PagesManager $path] +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::configure +# ------------------------------------------------------------------------------ +proc PagesManager::configure { path args } { + return [Widget::configure $path $args] +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::cget +# ------------------------------------------------------------------------------ +proc PagesManager::cget { path option } { + return [Widget::cget $path $option] +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::compute_size +# ------------------------------------------------------------------------------ +proc PagesManager::compute_size { path } { + variable $path + upvar 0 $path data + + set wmax 0 + set hmax 0 + update idletasks + foreach page $data(pages) { + set w [winfo reqwidth $path.f$page] + set h [winfo reqheight $path.f$page] + set wmax [expr {$w>$wmax ? $w : $wmax}] + set hmax [expr {$h>$hmax ? $h : $hmax}] + } + configure $path -width $wmax -height $hmax +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::add +# ------------------------------------------------------------------------------ +proc PagesManager::add { path page } { + variable $path + upvar 0 $path data + + if { [lsearch -exact $data(pages) $page] != -1 } { + return -code error "page \"$page\" already exists" + } + + lappend data(pages) $page + + frame $path.f$page -relief flat \ + -background [Widget::cget $path -background] -borderwidth 0 + + return $path.f$page +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::delete +# ------------------------------------------------------------------------------ +proc PagesManager::delete { path page } { + variable $path + upvar 0 $path data + + set pos [_test_page $path $page] + set data(pages) [lreplace $data(pages) $pos $pos] + if { $data(select) == $page } { + set data(select) "" + } + destroy $path.f$page + _redraw $path +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::raise +# ------------------------------------------------------------------------------ +proc PagesManager::raise { path {page ""} } { + variable $path + upvar 0 $path data + + if { $page != "" } { + _test_page $path $page + _select $path $page + } + return $data(select) +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::page - deprecated, use pages +# ------------------------------------------------------------------------------ +proc PagesManager::page { path first {last ""} } { + variable $path + upvar 0 $path data + + if { $last == "" } { + return [lindex $data(pages) $first] + } else { + return [lrange $data(pages) $first $last] + } +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::pages +# ------------------------------------------------------------------------------ +proc PagesManager::pages { path {first ""} {last ""} } { + variable $path + upvar 0 $path data + + if { ![string length $first] } { + return $data(pages) + } + + if { ![string length $last] } { + return [lindex $data(pages) $first] + } else { + return [lrange $data(pages) $first $last] + } +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::getframe +# ------------------------------------------------------------------------------ +proc PagesManager::getframe { path page } { + return $path.f$page +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::_test_page +# ------------------------------------------------------------------------------ +proc PagesManager::_test_page { path page } { + variable $path + upvar 0 $path data + + if { [set pos [lsearch $data(pages) $page]] == -1 } { + return -code error "page \"$page\" does not exists" + } + return $pos +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::_select +# ------------------------------------------------------------------------------ +proc PagesManager::_select { path page } { + variable $path + upvar 0 $path data + + set oldsel $data(select) + if { $page != $oldsel } { + set data(select) $page + _draw_area $path + } +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::_redraw +# ------------------------------------------------------------------------------ +proc PagesManager::_redraw { path } { + variable $path + upvar 0 $path data + + if { !$data(realized) } { + return + } + _draw_area $path +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::_draw_area +# ------------------------------------------------------------------------------ +proc PagesManager::_draw_area { path } { + variable $path + upvar 0 $path data + + set w [winfo width $path] + set h [winfo height $path] + set sel $data(select) + if { $sel != "" } { + if { [llength [$path:cmd find withtag "window"]] } { + $path:cmd coords "window" 0 0 + $path:cmd itemconfigure "window" \ + -width $w \ + -height $h \ + -window $path.f$sel + } else { + $path:cmd create window 0 0 \ + -width $w \ + -height $h \ + -anchor nw \ + -tags "window" \ + -window $path.f$sel + } + } else { + $path:cmd delete "window" + } +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::_realize +# ------------------------------------------------------------------------------ +proc PagesManager::_realize { path } { + variable $path + upvar 0 $path data + + if { [set width [Widget::cget $path -width]] == 0 || + [set height [Widget::cget $path -height]] == 0 } { + compute_size $path + } + + set data(realized) 1 + _draw_area $path + bind $path <Configure> [list PagesManager::_draw_area $path] +} + + +# ------------------------------------------------------------------------------ +# Command PagesManager::_destroy +# ------------------------------------------------------------------------------ +proc PagesManager::_destroy { path } { + variable $path + upvar 0 $path data + Widget::destroy $path + unset data +} diff --git a/modules/tclsci/tcl/BWidget/panedw.tcl b/modules/tclsci/tcl/BWidget/panedw.tcl new file mode 100755 index 000000000..7c72bfea0 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/panedw.tcl @@ -0,0 +1,385 @@ +# ---------------------------------------------------------------------------- +# panedw.tcl +# This file is part of Unifix BWidget Toolkit +# ---------------------------------------------------------------------------- +# Index of commands: +# - PanedWindow::create +# - PanedWindow::configure +# - PanedWindow::cget +# - PanedWindow::add +# - PanedWindow::getframe +# - PanedWindow::_apply_weights +# - PanedWindow::_destroy +# - PanedWindow::_beg_move_sash +# - PanedWindow::_move_sash +# - PanedWindow::_end_move_sash +# - PanedWindow::_realize +# ---------------------------------------------------------------------------- + +# JDC: added option to choose behavior of weights +# -weights extra : only apply weights to extra space (as current (>= 1.3.1) with grid command) +# -weights available : apply weights to total available space (as before (<1.3.1) with place command) + +namespace eval PanedWindow { + Widget::define PanedWindow panedw + + namespace eval Pane { + Widget::declare PanedWindow::Pane { + {-minsize Int 0 0 "%d >= 0"} + {-weight Int 1 0 "%d >= 0"} + } + } + + Widget::declare PanedWindow { + {-side Enum top 1 {top left bottom right}} + {-width Int 10 1 "%d >=3"} + {-pad Int 4 1 "%d >= 0"} + {-background TkResource "" 0 frame} + {-bg Synonym -background} + {-activator Enum "" 1 {line button}} + {-weights Enum extra 1 {extra available}} + } + + variable _panedw +} + + + +# ---------------------------------------------------------------------------- +# Command PanedWindow::create +# ---------------------------------------------------------------------------- +proc PanedWindow::create { path args } { + variable _panedw + + Widget::init PanedWindow $path $args + + frame $path -background [Widget::cget $path -background] -class PanedWindow + set _panedw($path,nbpanes) 0 + set _panedw($path,weights) "" + set _panedw($path,configuredone) 0 + + set activator [Widget::getoption $path -activator] + if {[string equal $activator ""]} { + if { $::tcl_platform(platform) != "windows" } { + Widget::setMegawidgetOption $path -activator button + } else { + Widget::setMegawidgetOption $path -activator line + } + } + if {[string equal [Widget::getoption $path -activator] "line"]} { + Widget::setMegawidgetOption $path -width 3 + } + + bind $path <Configure> [list PanedWindow::_realize $path %w %h] + bind $path <Destroy> [list PanedWindow::_destroy $path] + + return [Widget::create PanedWindow $path] +} + + +# ---------------------------------------------------------------------------- +# Command PanedWindow::configure +# ---------------------------------------------------------------------------- +proc PanedWindow::configure { path args } { + variable _panedw + + set res [Widget::configure $path $args] + + if { [Widget::hasChanged $path -background bg] && $_panedw($path,nbpanes) > 0 } { + $path:cmd configure -background $bg + $path.f0 configure -background $bg + for {set i 1} {$i < $_panedw($path,nbpanes)} {incr i} { + set frame $path.sash$i + $frame configure -background $bg + $frame.sep configure -background $bg + $frame.but configure -background $bg + $path.f$i configure -background $bg + $path.f$i.frame configure -background $bg + } + } + return $res +} + + +# ---------------------------------------------------------------------------- +# Command PanedWindow::cget +# ---------------------------------------------------------------------------- +proc PanedWindow::cget { path option } { + return [Widget::cget $path $option] +} + + +# ---------------------------------------------------------------------------- +# Command PanedWindow::add +# ---------------------------------------------------------------------------- +proc PanedWindow::add { path args } { + variable _panedw + + set num $_panedw($path,nbpanes) + Widget::init PanedWindow::Pane $path.f$num $args + set bg [Widget::getoption $path -background] + + set wbut [Widget::getoption $path -width] + set pad [Widget::getoption $path -pad] + set width [expr {$wbut+2*$pad}] + set side [Widget::getoption $path -side] + set weight [Widget::getoption $path.f$num -weight] + lappend _panedw($path,weights) $weight + + if { $num > 0 } { + set frame [frame $path.sash$num -relief flat -bd 0 \ + -highlightthickness 0 -width $width -height $width -bg $bg] + set sep [frame $frame.sep -bd 5 -relief raised \ + -highlightthickness 0 -bg $bg] + set but [frame $frame.but -bd 1 -relief raised \ + -highlightthickness 0 -bg $bg -width $wbut -height $wbut] + set sepsize 2 + + set activator [Widget::getoption $path -activator] + if {$activator == "button"} { + set activator $but + set placeButton 1 + } else { + set activator $sep + $sep configure -bd 1 + set placeButton 0 + } + if {[string equal $side "top"] || [string equal $side "bottom"]} { + place $sep -relx 0.5 -y 0 -width $sepsize -relheight 1.0 -anchor n + if { $placeButton } { + if {[string equal $side "top"]} { + place $but -relx 0.5 -y [expr {6+$wbut/2}] -anchor c + } else { + place $but -relx 0.5 -rely 1.0 -y [expr {-6-$wbut/2}] \ + -anchor c + } + } + $activator configure -cursor sb_h_double_arrow + grid $frame -column [expr {2*$num-1}] -row 0 -sticky ns + grid columnconfigure $path [expr {2*$num-1}] -weight 0 + } else { + place $sep -x 0 -rely 0.5 -height $sepsize -relwidth 1.0 -anchor w + if { $placeButton } { + if {[string equal $side "left"]} { + place $but -rely 0.5 -x [expr {6+$wbut/2}] -anchor c + } else { + place $but -rely 0.5 -relx 1.0 -x [expr {-6-$wbut/2}] \ + -anchor c + } + } + $activator configure -cursor sb_v_double_arrow + grid $frame -row [expr {2*$num-1}] -column 0 -sticky ew + grid rowconfigure $path [expr {2*$num-1}] -weight 0 + } + bind $activator <ButtonPress-1> \ + [list PanedWindow::_beg_move_sash $path $num %X %Y] + } else { + if { [string equal $side "top"] || \ + [string equal $side "bottom"] } { + grid rowconfigure $path 0 -weight 1 + } else { + grid columnconfigure $path 0 -weight 1 + } + } + + set pane [frame $path.f$num -bd 0 -relief flat \ + -highlightthickness 0 -bg $bg] + set user [frame $path.f$num.frame -bd 0 -relief flat \ + -highlightthickness 0 -bg $bg] + if { [string equal $side "top"] || [string equal $side "bottom"] } { + grid $pane -column [expr {2*$num}] -row 0 -sticky nsew + grid columnconfigure $path [expr {2*$num}] -weight $weight + } else { + grid $pane -row [expr {2*$num}] -column 0 -sticky nsew + grid rowconfigure $path [expr {2*$num}] -weight $weight + } + pack $user -fill both -expand yes + incr _panedw($path,nbpanes) + if {$_panedw($path,configuredone)} { + _realize $path [winfo width $path] [winfo height $path] + } + + return $user +} + + +# ---------------------------------------------------------------------------- +# Command PanedWindow::getframe +# ---------------------------------------------------------------------------- +proc PanedWindow::getframe { path index } { + if { [winfo exists $path.f$index.frame] } { + return $path.f$index.frame + } +} + + +# ---------------------------------------------------------------------------- +# Command PanedWindow::_beg_move_sash +# ---------------------------------------------------------------------------- +proc PanedWindow::_beg_move_sash { path num x y } { + variable _panedw + + set fprev $path.f[expr {$num-1}] + set fnext $path.f$num + set wsash [expr {[Widget::getoption $path -width] + 2*[Widget::getoption $path -pad]}] + + $path.sash$num.but configure -relief sunken + set top [toplevel $path.sash -borderwidth 1 -relief raised] + + set minszg [Widget::getoption $fprev -minsize] + set minszd [Widget::getoption $fnext -minsize] + set side [Widget::getoption $path -side] + + if { [string equal $side "top"] || [string equal $side "bottom"] } { + $top configure -cursor sb_h_double_arrow + set h [winfo height $path] + set yr [winfo rooty $path.sash$num] + set xmin [expr {$wsash/2+[winfo rootx $fprev]+$minszg}] + set xmax [expr {-$wsash/2-1+[winfo rootx $fnext]+[winfo width $fnext]-$minszd}] + wm overrideredirect $top 1 + wm geom $top "2x${h}+$x+$yr" + + update idletasks + grab set $top + bind $top <ButtonRelease-1> [list PanedWindow::_end_move_sash $path $top $num $xmin $xmax %X rootx width] + bind $top <Motion> [list PanedWindow::_move_sash $top $xmin $xmax %X +%%d+$yr] + _move_sash $top $xmin $xmax $x "+%d+$yr" + } else { + $top configure -cursor sb_v_double_arrow + set w [winfo width $path] + set xr [winfo rootx $path.sash$num] + set ymin [expr {$wsash/2+[winfo rooty $fprev]+$minszg}] + set ymax [expr {-$wsash/2-1+[winfo rooty $fnext]+[winfo height $fnext]-$minszd}] + wm overrideredirect $top 1 + wm geom $top "${w}x2+$xr+$y" + + update idletasks + grab set $top + bind $top <ButtonRelease-1> [list PanedWindow::_end_move_sash \ + $path $top $num $ymin $ymax %Y rooty height] + bind $top <Motion> [list PanedWindow::_move_sash \ + $top $ymin $ymax %Y +$xr+%%d] + _move_sash $top $ymin $ymax $y "+$xr+%d" + } +} + + +# ---------------------------------------------------------------------------- +# Command PanedWindow::_move_sash +# ---------------------------------------------------------------------------- +proc PanedWindow::_move_sash { top min max v form } { + + if { $v < $min } { + set v $min + } elseif { $v > $max } { + set v $max + } + wm geom $top [format $form $v] +} + + +# ---------------------------------------------------------------------------- +# Command PanedWindow::_end_move_sash +# ---------------------------------------------------------------------------- +proc PanedWindow::_end_move_sash { path top num min max v rootv size } { + variable _panedw + + destroy $top + if { $v < $min } { + set v $min + } elseif { $v > $max } { + set v $max + } + set fprev $path.f[expr {$num-1}] + set fnext $path.f$num + + $path.sash$num.but configure -relief raised + + set wsash [expr {[Widget::getoption $path -width] + 2*[Widget::getoption $path -pad]}] + set dv [expr {$v-[winfo $rootv $path.sash$num]-$wsash/2}] + set w1 [winfo $size $fprev] + set w2 [winfo $size $fnext] + + for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} { + if { $i == $num-1} { + $fprev configure -$size [expr {[winfo $size $fprev]+$dv}] + } elseif { $i == $num } { + $fnext configure -$size [expr {[winfo $size $fnext]-$dv}] + } else { + $path.f$i configure -$size [winfo $size $path.f$i] + } + } +} + + +# ---------------------------------------------------------------------------- +# Command PanedWindow::_realize +# ---------------------------------------------------------------------------- +proc PanedWindow::_realize { path width height } { + variable _panedw + + set x 0 + set y 0 + set hc [winfo reqheight $path] + set hmax 0 + for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} { + $path.f$i configure \ + -width [winfo reqwidth $path.f$i.frame] \ + -height [winfo reqheight $path.f$i.frame] + place $path.f$i.frame -x 0 -y 0 -relwidth 1 -relheight 1 + } + + bind $path <Configure> {} + + _apply_weights $path + set _panedw($path,configuredone) 1 + return +} + +# ---------------------------------------------------------------------------- +# Command PanedWindow::_apply_weights +# ---------------------------------------------------------------------------- +proc PanedWindow::_apply_weights { path } { + variable _panedw + + set weights [Widget::getoption $path -weights] + if {[string equal $weights "extra"]} { + return + } + + set side [Widget::getoption $path -side] + if {[string equal $side "top"] || [string equal $side "bottom"] } { + set size width + } else { + set size height + } + set wsash [expr {[Widget::getoption $path -width] + 2*[Widget::getoption $path -pad]}] + set rs [winfo $size $path] + set s [expr {$rs - ($_panedw($path,nbpanes) - 1) * $wsash}] + + set tw 0.0 + foreach w $_panedw($path,weights) { + set tw [expr {$tw + $w}] + } + + for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} { + set rw [lindex $_panedw($path,weights) $i] + set ps [expr {int($rw / $tw * $s)}] + $path.f$i configure -$size $ps + } + return +} + + +# ---------------------------------------------------------------------------- +# Command PanedWindow::_destroy +# ---------------------------------------------------------------------------- +proc PanedWindow::_destroy { path } { + variable _panedw + + for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} { + Widget::destroy $path.f$i + } + unset _panedw($path,nbpanes) + Widget::destroy $path +} diff --git a/modules/tclsci/tcl/BWidget/panelframe.tcl b/modules/tclsci/tcl/BWidget/panelframe.tcl new file mode 100755 index 000000000..fb8bc1937 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/panelframe.tcl @@ -0,0 +1,246 @@ +# ----------------------------------------------------------------------------
+# panelframe.tcl
+# Create PanelFrame widgets.
+# A PanelFrame is a boxed frame that allows you to place items
+# in the label area (liked combined frame+toolbar). It uses the
+# highlight colors the default frame color.
+# $Id: panelframe.tcl,v 1.1 2004/09/09 22:17:51 hobbs Exp $
+# ----------------------------------------------------------------------------
+# Index of commands:
+# - PanelFrame::create
+# - PanelFrame::configure
+# - PanelFrame::cget
+# - PanelFrame::getframe
+# - PanelFrame::add
+# - PanelFrame::remove
+# - PanelFrame::items
+# ----------------------------------------------------------------------------
+
+namespace eval PanelFrame {
+ Widget::define PanelFrame panelframe
+
+ Widget::declare PanelFrame {
+ {-background TkResource "" 0 frame}
+ {-borderwidth TkResource 1 0 frame}
+ {-relief TkResource flat 0 frame}
+ {-panelbackground TkResource "" 0 {entry -selectbackground}}
+ {-panelforeground TkResource "" 0 {entry -selectforeground}}
+ {-width Int 0 0}
+ {-height Int 0 0}
+ {-font TkResource "" 0 label}
+ {-text String "" 0}
+ {-textvariable String "" 0}
+ {-ipad String 1 0}
+ {-bg Synonym -background}
+ {-bd Synonym -borderwidth}
+ }
+ # Should we have automatic state handling?
+ #{-state TkResource "" 0 label}
+
+ Widget::addmap PanelFrame "" :cmd {
+ -panelbackground -background
+ -width {} -height {} -borderwidth {} -relief {}
+ }
+ Widget::addmap PanelFrame "" .title {
+ -panelbackground -background
+ }
+ Widget::addmap PanelFrame "" .title.text {
+ -panelbackground -background
+ -panelforeground -foreground
+ -text {} -textvariable {} -font {}
+ }
+ Widget::addmap PanelFrame "" .frame {
+ -background {}
+ }
+
+ if {0} {
+ # This would be code to have an automated close button
+ #{-closebutton Boolean 0 0}
+ Widget::addmap PanelFrame "" .title.close {
+ -panelbackground -background
+ -panelforeground -foreground
+ }
+ variable HaveMarlett \
+ [expr {[lsearch -exact [font families] "Marlett"] != -1}]
+
+ variable imgdata {
+ #define close_width 16
+ #define close_height 16
+ static char close_bits[] = {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x08,
+ 0x38, 0x1c, 0x70, 0x0e,
+ 0xe0, 0x07, 0xc0, 0x03,
+ 0xc0, 0x03, 0xe0, 0x07,
+ 0x70, 0x0e, 0x38, 0x1c,
+ 0x10, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00};
+ }
+ # We use the same -foreground as the default -panelbackground
+ image create bitmap ::PanelFrame::X -data $imgdata \
+ -foreground [lindex $Widget::PanelFrame::opt(-panelbackground) 1]
+ }
+
+ bind PanelFrame <Destroy> [list Widget::destroy %W]
+}
+
+
+# ----------------------------------------------------------------------------
+# Command PanelFrame::create
+# ----------------------------------------------------------------------------
+proc PanelFrame::create { path args } {
+ variable HaveMarlett
+
+ Widget::init PanelFrame $path $args
+
+ set lblopts [list -bd 0 -highlightthickness 0]
+ set outer [eval [list frame $path -class PanelFrame] \
+ [Widget::subcget $path :cmd]]
+ set title [eval [list frame $path.title] \
+ [Widget::subcget $path .title]]
+ set tlbl [eval [list label $path.title.text] $lblopts -anchor w \
+ [Widget::subcget $path .title.text]]
+ set inner [eval [list frame $path.frame] \
+ [Widget::subcget $path .frame]]
+
+ foreach {ipadx ipady} [_padval [Widget::cget $path -ipad]] { break }
+
+ if {0} {
+ set btnopts [list -padx 0 -pady 0 -relief flat -overrelief raised \
+ -bd 1 -highlightthickness 0]
+ set clbl [eval [list button $path.title.close] $btnopts \
+ [Widget::subcget $path .title.close]]
+ set close [Widget::cget $path -closebutton]
+ if {$HaveMarlett} {
+ $clbl configure -font "Marlett -14" -text \u0072
+ } else {
+ $clbl configure -image ::PanelFrame::X
+ }
+ if {$close} {
+ pack $path.title.close -side right -padx $ipadx -pady $ipady
+ }
+ }
+
+ grid $path.title -row 0 -column 0 -sticky ew
+ grid $path.frame -row 1 -column 0 -sticky news
+ grid columnconfigure $path 0 -weight 1
+ grid rowconfigure $path 1 -weight 1
+
+ pack $path.title.text -side left -fill x -anchor w \
+ -padx $ipadx -pady $ipady
+
+ return [Widget::create PanelFrame $path]
+}
+
+
+# ----------------------------------------------------------------------------
+# Command PanelFrame::configure
+# ----------------------------------------------------------------------------
+proc PanelFrame::configure { path args } {
+ set res [Widget::configure $path $args]
+
+ if {[Widget::hasChanged $path -ipad ipad]} {
+ }
+
+ return $res
+}
+
+
+# ----------------------------------------------------------------------------
+# Command PanelFrame::cget
+# ----------------------------------------------------------------------------
+proc PanelFrame::cget { path option } {
+ return [Widget::cget $path $option]
+}
+
+# ----------------------------------------------------------------------------
+# Command PanelFrame::getframe
+# ----------------------------------------------------------------------------
+proc PanelFrame::getframe { path } {
+ return $path.frame
+}
+
+# ------------------------------------------------------------------------
+# Command PanelFrame::add
+# ------------------------------------------------------------------------
+proc PanelFrame::add {path w args} {
+ variable _widget
+
+ array set opts [list \
+ -side right \
+ -fill none \
+ -expand 0 \
+ -pad [Widget::cget $path -ipad] \
+ ]
+ foreach {key val} $args {
+ if {[info exists opts($key)]} {
+ set opts($key) $val
+ } else {
+ set msg "unknown option \"$key\", must be one of: "
+ append msg [join [lsort [array names opts]] {, }]
+ return -code error $msg
+ }
+ }
+ foreach {ipadx ipady} [_padval $opts(-pad)] { break }
+
+ set f $path.title
+
+ lappend _widget($path,items) $w
+ pack $w -in $f -padx $ipadx -pady $ipady -side $opts(-side) \
+ -fill $opts(-fill) -expand $opts(-expand)
+
+ return $w
+}
+
+# ------------------------------------------------------------------------
+# Command PanelFrame::remove
+# ------------------------------------------------------------------------
+proc PanelFrame::remove {path args} {
+ variable _widget
+
+ set destroy [string equal [lindex $args 0] "-destroy"]
+ if {$destroy} {
+ set args [lrange $args 1 end]
+ }
+ foreach w $args {
+ set idx [lsearch -exact $_widget($path,items) $w]
+ if {$idx == -1} {
+ # ignore unknown
+ continue
+ }
+ if {$destroy} {
+ destroy $w
+ } elseif {[winfo exists $w]} {
+ pack forget $w
+ }
+ set _widget($path,items) [lreplace $_widget($path,items) $idx $idx]
+ }
+}
+
+# ------------------------------------------------------------------------
+# Command PanelFrame::delete
+# ------------------------------------------------------------------------
+proc PanelFrame::delete {path args} {
+ return [PanelFrame::remove $path -destroy $args]
+}
+
+# ------------------------------------------------------------------------
+# Command PanelFrame::items
+# ------------------------------------------------------------------------
+proc PanelFrame::items {path} {
+ variable _widget
+ return $_widget($path,items)
+}
+
+proc PanelFrame::_padval {padval} {
+ set len [llength $padval]
+ foreach {a b} $padval { break }
+ if {$len == 0 || $len > 2} {
+ return -code error \
+ "invalid pad value \"$padval\", must be 1 or 2 pixel values"
+ } elseif {$len == 1} {
+ return [list $a $a]
+ } elseif {$len == 2} {
+ return $padval
+ }
+}
diff --git a/modules/tclsci/tcl/BWidget/passwddlg.tcl b/modules/tclsci/tcl/BWidget/passwddlg.tcl new file mode 100755 index 000000000..551d0ab9a --- /dev/null +++ b/modules/tclsci/tcl/BWidget/passwddlg.tcl @@ -0,0 +1,182 @@ +# ----------------------------------------------------------------------------- +# passwddlg.tcl +# This file is part of Unifix BWidget Toolkit +# by Stephane Lavirotte (Stephane.Lavirotte@sophia.inria.fr) +# $Id: passwddlg.tcl,v 1.12 2009/06/11 15:42:51 oehhar Exp $ +# ----------------------------------------------------------------------------- +# Index of commands: +# - PasswdDlg::create +# - PasswdDlg::configure +# - PasswdDlg::cget +# - PasswdDlg::_verifonlogin +# - PasswdDlg::_verifonpasswd +# - PasswdDlg::_max +#------------------------------------------------------------------------------ + +namespace eval PasswdDlg { + Widget::define PasswdDlg passwddlg Dialog LabelEntry + + Widget::bwinclude PasswdDlg Dialog :cmd \ + remove {-image -bitmap -side -default -cancel -separator} \ + initialize {-modal local -anchor e} + + Widget::bwinclude PasswdDlg LabelEntry .frame.lablog \ + remove [list -command -justify -name -show -side \ + -state -takefocus -width -xscrollcommand -padx -pady \ + -dragenabled -dragendcmd -dragevent -draginitcmd \ + -dragtype -dropenabled -dropcmd -dropovercmd -droptypes \ + ] \ + prefix [list login -editable -helptext -helpvar -label \ + -text -textvariable -underline \ + ] \ + initialize [list -relief sunken -borderwidth 2 \ + -labelanchor w -width 15 -loginlabel "Login" \ + ] + + Widget::bwinclude PasswdDlg LabelEntry .frame.labpass \ + remove [list -command -width -show -side -takefocus \ + -xscrollcommand -dragenabled -dragendcmd -dragevent \ + -draginitcmd -dragtype -dropenabled -dropcmd \ + -dropovercmd -droptypes -justify -padx -pady -name \ + ] \ + prefix [list passwd -editable -helptext -helpvar -label \ + -state -text -textvariable -underline \ + ] \ + initialize [list -relief sunken -borderwidth 2 \ + -labelanchor w -width 15 -passwdlabel "Password" \ + ] + + Widget::declare PasswdDlg { + {-type Enum ok 0 {ok okcancel}} + {-labelwidth TkResource -1 0 {label -width}} + {-command String "" 0} + } +} + + +# ----------------------------------------------------------------------------- +# Command PasswdDlg::create +# ----------------------------------------------------------------------------- +proc PasswdDlg::create { path args } { + + array set maps [list PasswdDlg {} :cmd {} .frame.lablog {} \ + .frame.labpass {}] + array set maps [Widget::parseArgs PasswdDlg $args] + + Widget::initFromODB PasswdDlg "$path#PasswdDlg" $maps(PasswdDlg) + + # Extract the PasswdDlg megawidget options (those that don't map to a + # subwidget) + set type [Widget::cget "$path#PasswdDlg" -type] + set cmd [Widget::cget "$path#PasswdDlg" -command] + + set defb -1 + set canb -1 + switch -- $type { + ok { set lbut {ok}; set defb 0 } + okcancel { set lbut {ok cancel} ; set defb 0; set canb 1 } + } + + eval [list Dialog::create $path] $maps(:cmd) \ + [list -class PasswdDlg -image [Bitmap::get passwd] \ + -side bottom -default $defb -cancel $canb] + foreach but $lbut { + if { $but == "ok" && $cmd != "" } { + Dialog::add $path -text $but -name $but -command $cmd + } else { + Dialog::add $path -text $but -name $but + } + } + + set frame [Dialog::getframe $path] + bind $path <Return> "" + bind $frame <Destroy> [list Widget::destroy $path\#PasswdDlg] + + set lablog [eval [list LabelEntry::create $frame.lablog] \ + $maps(.frame.lablog) \ + [list -name login -dragenabled 0 -dropenabled 0 \ + -command [list PasswdDlg::_verifonpasswd \ + $path $frame.labpass]]] + + set labpass [eval [list LabelEntry::create $frame.labpass] \ + $maps(.frame.labpass) \ + [list -name password -show "*" \ + -dragenabled 0 -dropenabled 0 \ + -command [list PasswdDlg::_verifonlogin \ + $path $frame.lablog]]] + + # compute label width + if {[$lablog cget -labelwidth] == 0} { + set loglabel [$lablog cget -label] + set passlabel [$labpass cget -label] + set labwidth [_max [string length $loglabel] [string length $passlabel]] + incr labwidth 1 + $lablog configure -labelwidth $labwidth + $labpass configure -labelwidth $labwidth + } + + Widget::create PasswdDlg $path 0 + + pack $frame.lablog $frame.labpass -fill x -expand 1 + + # added by bach@mwgdna.com + # give focus to loginlabel unless the state is disabled + if {[$lablog cget -editable]} { + focus $frame.lablog.e + } else { + focus $frame.labpass.e + } + set res [Dialog::draw $path] + + if { $res == 0 } { + set res [list [$lablog.e cget -text] [$labpass.e cget -text]] + } else { + set res [list] + } + Widget::destroy "$path#PasswdDlg" + destroy $path + + return $res +} + +# ----------------------------------------------------------------------------- +# Command PasswdDlg::configure +# ----------------------------------------------------------------------------- + +proc PasswdDlg::configure { path args } { + set res [Widget::configure "$path#PasswdDlg" $args] +} + +# ----------------------------------------------------------------------------- +# Command PasswdDlg::cget +# ----------------------------------------------------------------------------- + +proc PasswdDlg::cget { path option } { + return [Widget::cget "$path#PasswdDlg" $option] +} + + +# ----------------------------------------------------------------------------- +# Command PasswdDlg::_verifonlogin +# ----------------------------------------------------------------------------- +proc PasswdDlg::_verifonlogin { path labpass } { + Dialog::enddialog $path 0 +} + +# ----------------------------------------------------------------------------- +# Command PasswdDlg::_verifonpasswd +# ----------------------------------------------------------------------------- +proc PasswdDlg::_verifonpasswd { path labpass } { + if {[string equal [$labpass cget -state] "disabled"]} { + Dialog::enddialog $path 0 + } else { + focus $labpass + } +} + +# ----------------------------------------------------------------------------- +# Command PasswdDlg::_max +# ----------------------------------------------------------------------------- +proc PasswdDlg::_max { val1 val2 } { + return [expr {($val1 > $val2) ? ($val1) : ($val2)}] +} diff --git a/modules/tclsci/tcl/BWidget/pkgIndex.tcl b/modules/tclsci/tcl/BWidget/pkgIndex.tcl new file mode 100755 index 000000000..884aeed01 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/pkgIndex.tcl @@ -0,0 +1,84 @@ + +# @@ Meta Begin +# Package BWidget 1.9.4 +# Meta activestatetags ActiveTcl Public +# Meta as::author {Jeff Hobbs} {Damon Courtney} +# Meta as::build::date 2011-01-27 +# Meta as::origin http://sourceforge.net/projects/tcllib +# Meta category Widget set +# Meta description The BWidget Toolkit is a high-level widget set for +# Meta description Tcl/Tk. They feature a professional look and feel +# Meta description and don't require a compiled extension library. +# Meta license BSD +# Meta platform tcl +# Meta recommend {Tk 8.5a6} +# Meta recommend {tile 0.6 1} +# Meta require {Tcl 8.1.1} +# Meta require {Tk 8.3} +# Meta subject bwidget widget toolkit Tk megawidget +# Meta summary A suite of megawidgets for Tk +# @@ Meta End + + +if {![package vsatisfies [package provide Tcl] 8.1]} return + +package ifneeded BWidget 1.9.4 [string map [list @ $dir] { + # ACTIVESTATE TEAPOT-PKG BEGIN REQUIREMENTS + + package require Tcl 8.1.1 + package require Tk 8.3 + + # ACTIVESTATE TEAPOT-PKG END REQUIREMENTS + + set dir {@} + eval "package require Tk 8.1.1;\ + [list tclPkgSetup $dir BWidget 1.9.4 { + {arrow.tcl source {ArrowButton ArrowButton::create ArrowButton::use}} + {labelframe.tcl source {LabelFrame LabelFrame::create LabelFrame::use}} + {labelentry.tcl source {LabelEntry LabelEntry::create LabelEntry::use}} + {bitmap.tcl source {Bitmap::get Bitmap::use}} + {button.tcl source {Button Button::create Button::use}} + {buttonbox.tcl source {ButtonBox ButtonBox::create ButtonBox::use}} + {combobox.tcl source {ComboBox ComboBox::create ComboBox::use}} + {label.tcl source {Label Label::create Label::use}} + {entry.tcl source {Entry Entry::create Entry::use}} + {pagesmgr.tcl source {PagesManager PagesManager::create PagesManager::use}} + {notebook.tcl source {NoteBook NoteBook::create NoteBook::use}} + {panedw.tcl source {PanedWindow PanedWindow::create PanedWindow::use}} + {scrollw.tcl source {ScrolledWindow ScrolledWindow::create ScrolledWindow::use}} + {scrollview.tcl source {ScrollView ScrollView::create ScrollView::use}} + {scrollframe.tcl source {ScrollableFrame ScrollableFrame::create ScrollableFrame::use}} + {panelframe.tcl source {PanelFrame PanelFrame::create PanelFrame::use}} + {progressbar.tcl source {ProgressBar ProgressBar::create ProgressBar::use}} + {progressdlg.tcl source {ProgressDlg ProgressDlg::create ProgressDlg::use}} + {passwddlg.tcl source {PasswdDlg PasswdDlg::create PasswdDlg::use}} + {dragsite.tcl source {DragSite::register DragSite::include DragSite::use}} + {dropsite.tcl source {DropSite::register DropSite::include DropSite::use}} + {separator.tcl source {Separator Separator::create Separator::use}} + {spinbox.tcl source {SpinBox SpinBox::create SpinBox::use}} + {statusbar.tcl source {StatusBar StatusBar::create StatusBar::use}} + {titleframe.tcl source {TitleFrame TitleFrame::create TitleFrame::use}} + {mainframe.tcl source {MainFrame MainFrame::create MainFrame::use}} + {listbox.tcl source {ListBox ListBox::create ListBox::use}} + {tree.tcl source {Tree Tree::create Tree::use}} + {color.tcl source {SelectColor SelectColor::menu SelectColor::dialog SelectColor::setcolor}} + {dynhelp.tcl source {DynamicHelp::configure DynamicHelp::use DynamicHelp::register DynamicHelp::include DynamicHelp::add DynamicHelp::delete}} + {dialog.tcl source {Dialog Dialog::create Dialog::use}} + {messagedlg.tcl source {MessageDlg MessageDlg::create MessageDlg::use}} + {font.tcl source {SelectFont SelectFont::create SelectFont::use SelectFont::loadfont}} + {widgetdoc.tcl source {Widget::generate-doc Widget::generate-widget-doc}} + {wizard.tcl source {Wizard Wizard::create Wizard::use SimpleWizard ClassicWizard}} + {xpm2image.tcl source {xpm-to-image}} + }]; \ + [list namespace eval ::BWIDGET {}]; \ + [list set ::BWIDGET::LIBRARY $dir]; \ + [list source [file join $dir widget.tcl]]; \ + [list source [file join $dir init.tcl]]; \ + [list source [file join $dir utils.tcl]];" + + # ACTIVESTATE TEAPOT-PKG BEGIN DECLARE + + package provide BWidget 1.9.4 + + # ACTIVESTATE TEAPOT-PKG END DECLARE + }] diff --git a/modules/tclsci/tcl/BWidget/progressbar.tcl b/modules/tclsci/tcl/BWidget/progressbar.tcl new file mode 100755 index 000000000..73c48f255 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/progressbar.tcl @@ -0,0 +1,208 @@ +# ---------------------------------------------------------------------------- +# progressbar.tcl +# This file is part of Unifix BWidget Toolkit +# ---------------------------------------------------------------------------- +# Index of commands: +# - ProgressBar::create +# - ProgressBar::configure +# - ProgressBar::cget +# - ProgressBar::_destroy +# - ProgressBar::_modify +# ---------------------------------------------------------------------------- + +namespace eval ProgressBar { + Widget::define ProgressBar progressbar + + Widget::declare ProgressBar { + {-type Enum normal 0 + {normal incremental infinite nonincremental_infinite}} + {-maximum Int 100 0 "%d > 0"} + {-background TkResource "" 0 frame} + {-foreground TkResource "blue" 0 label} + {-borderwidth TkResource 2 0 frame} + {-troughcolor TkResource "" 0 scrollbar} + {-relief TkResource sunken 0 label} + {-orient Enum horizontal 1 {horizontal vertical}} + {-variable String "" 0} + {-idle Boolean 0 0} + {-width TkResource 100 0 frame} + {-height TkResource 4m 0 frame} + {-bg Synonym -background} + {-fg Synonym -foreground} + {-bd Synonym -borderwidth} + } + + Widget::addmap ProgressBar "" :cmd {-background {} -width {} -height {}} + Widget::addmap ProgressBar "" .bar { + -troughcolor -background -borderwidth {} -relief {} + } + + variable _widget +} + + +# ---------------------------------------------------------------------------- +# Command ProgressBar::create +# ---------------------------------------------------------------------------- +proc ProgressBar::create { path args } { + variable _widget + + array set maps [list ProgressBar {} :cmd {} .bar {}] + array set maps [Widget::parseArgs ProgressBar $args] + eval frame $path $maps(:cmd) -class ProgressBar -bd 0 \ + -highlightthickness 0 -relief flat + Widget::initFromODB ProgressBar $path $maps(ProgressBar) + + set c [eval [list canvas $path.bar] $maps(.bar) -highlightthickness 0] + set fg [Widget::cget $path -foreground] + if { [string equal [Widget::cget $path -orient] "horizontal"] } { + $path.bar create rectangle -1 0 0 0 -fill $fg -outline $fg -tags rect + } else { + $path.bar create rectangle 0 1 0 0 -fill $fg -outline $fg -tags rect + } + + set _widget($path,val) 0 + set _widget($path,dir) 1 + set _widget($path,var) [Widget::cget $path -variable] + if {$_widget($path,var) != ""} { + GlobalVar::tracevar variable $_widget($path,var) w \ + [list ProgressBar::_modify $path] + set _widget($path,afterid) \ + [after idle [list ProgressBar::_modify $path]] + } + + bind $path.bar <Destroy> [list ProgressBar::_destroy $path] + bind $path.bar <Configure> [list ProgressBar::_modify $path] + + return [Widget::create ProgressBar $path] +} + + +# ---------------------------------------------------------------------------- +# Command ProgressBar::configure +# ---------------------------------------------------------------------------- +proc ProgressBar::configure { path args } { + variable _widget + + set res [Widget::configure $path $args] + + if { [Widget::hasChangedX $path -variable] } { + set newv [Widget::cget $path -variable] + if { $_widget($path,var) != "" } { + GlobalVar::tracevar vdelete $_widget($path,var) w \ + [list ProgressBar::_modify $path] + } + if { $newv != "" } { + set _widget($path,var) $newv + GlobalVar::tracevar variable $newv w \ + [list ProgressBar::_modify $path] + if {![info exists _widget($path,afterid)]} { + set _widget($path,afterid) \ + [after idle [list ProgressBar::_modify $path]] + } + } else { + set _widget($path,var) "" + } + } + + foreach {cbd cor cma} [Widget::hasChangedX $path -borderwidth \ + -orient -maximum] break + + if { $cbd || $cor || $cma } { + if {![info exists _widget($path,afterid)]} { + set _widget($path,afterid) \ + [after idle [list ProgressBar::_modify $path]] + } + } + if { [Widget::hasChangedX $path -foreground] } { + set fg [Widget::cget $path -foreground] + $path.bar itemconfigure rect -fill $fg -outline $fg + } + return $res +} + + +# ---------------------------------------------------------------------------- +# Command ProgressBar::cget +# ---------------------------------------------------------------------------- +proc ProgressBar::cget { path option } { + return [Widget::cget $path $option] +} + + +# ---------------------------------------------------------------------------- +# Command ProgressBar::_modify +# ---------------------------------------------------------------------------- +proc ProgressBar::_modify { path args } { + variable _widget + + catch {unset _widget($path,afterid)} + if { ![GlobalVar::exists $_widget($path,var)] || + [set val [GlobalVar::getvar $_widget($path,var)]] < 0 } { + catch {place forget $path.bar} + } else { + place $path.bar -relx 0 -rely 0 -relwidth 1 -relheight 1 + set type [Widget::getoption $path -type] + if { $val != 0 && $type != "normal" && \ + $type != "nonincremental_infinite"} { + set val [expr {$val+$_widget($path,val)}] + } + set _widget($path,val) $val + set max [Widget::getoption $path -maximum] + set bd [expr {2*[$path.bar cget -bd]}] + set w [winfo width $path.bar] + set h [winfo height $path.bar] + if {$type == "infinite" || $type == "nonincremental_infinite"} { + # JDC: New infinite behaviour + set tval [expr {$val % $max}] + if { $tval < ($max / 2.0) } { + set x0 [expr {double($tval) / double($max) * 1.5}] + } else { + set x0 [expr {(1.0-(double($tval) / double($max))) * 1.5}] + } + set x1 [expr {$x0 + 0.25}] + # convert coords to ints to prevent triggering canvas refresh + # bug related to fractional coords + if {[Widget::getoption $path -orient] == "horizontal"} { + $path.bar coords rect [expr {int($x0*$w)}] 0 \ + [expr {int($x1*$w)}] $h + } else { + $path.bar coords rect 0 [expr {int($h-$x0*$h)}] $w \ + [expr {int($x1*$h)}] + } + } else { + if { $val > $max } {set val $max} + if {[Widget::getoption $path -orient] == "horizontal"} { + $path.bar coords rect -1 0 [expr {int(double($val)*$w/$max)}] $h + } else { + $path.bar coords rect 0 [expr {$h+1}] $w \ + [expr {int($h*(1.0 - double($val)/$max))}] + } + } + } + if {![Widget::cget $path -idle]} { + update idletasks + } +} + + +# ---------------------------------------------------------------------------- +# Command ProgressBar::_destroy +# ---------------------------------------------------------------------------- +proc ProgressBar::_destroy { path } { + variable _widget + + if {[info exists _widget($path,afterid)]} { + after cancel $_widget($path,afterid) + unset _widget($path,afterid) + } + if {[info exists _widget($path,var)]} { + if {$_widget($path,var) != ""} { + GlobalVar::tracevar vdelete $_widget($path,var) w \ + [list ProgressBar::_modify $path] + } + unset _widget($path,var) + } + unset _widget($path,dir) + Widget::destroy $path +} diff --git a/modules/tclsci/tcl/BWidget/progressdlg.tcl b/modules/tclsci/tcl/BWidget/progressdlg.tcl new file mode 100755 index 000000000..bd2a2768a --- /dev/null +++ b/modules/tclsci/tcl/BWidget/progressdlg.tcl @@ -0,0 +1,87 @@ +# ---------------------------------------------------------------------------- +# progressdlg.tcl +# This file is part of Unifix BWidget Toolkit +# ---------------------------------------------------------------------------- +# Index of commands: +# - ProgressDlg::create +# ---------------------------------------------------------------------------- + +namespace eval ProgressDlg { + Widget::define ProgressDlg progressdlg Dialog ProgressBar + + Widget::bwinclude ProgressDlg Dialog :cmd \ + remove { + -modal -image -bitmap -side -anchor -cancel -default + -homogeneous -padx -pady -spacing + } + + Widget::bwinclude ProgressDlg ProgressBar .frame.pb \ + remove {-orient -width -height} + + Widget::declare ProgressDlg { + {-width TkResource 25 0 label} + {-height TkResource 2 0 label} + {-textvariable TkResource "" 0 label} + {-font TkResource "" 0 label} + {-stop String "" 0} + {-command String "" 0} + } + + Widget::addmap ProgressDlg :cmd .frame.msg \ + {-width {} -height {} -textvariable {} -font {} -background {}} +} + + +# ---------------------------------------------------------------------------- +# Command ProgressDlg::create +# ---------------------------------------------------------------------------- +proc ProgressDlg::create { path args } { + array set maps [list ProgressDlg {} :cmd {} .frame.msg {} .frame.pb {}] + array set maps [Widget::parseArgs ProgressDlg $args] + + eval [list Dialog::create] $path $maps(:cmd) \ + [list -image [Bitmap::get hourglass] \ + -modal none -side bottom -anchor e -class ProgressDlg] + + Widget::initFromODB ProgressDlg "$path#ProgressDlg" $maps(ProgressDlg) + + wm protocol $path WM_DELETE_WINDOW {;} + + set frame [Dialog::getframe $path] + bind $frame <Destroy> [list Widget::destroy $path\#ProgressDlg] + $frame configure -cursor watch + + eval [list label $frame.msg] $maps(.frame.msg) \ + -relief flat -borderwidth 0 \ + -highlightthickness 0 -anchor w -justify left + pack $frame.msg -side top -pady 3m -anchor nw -fill x -expand yes + + eval [list ProgressBar::create] $frame.pb $maps(.frame.pb) -width 100 + pack $frame.pb -side bottom -anchor w -fill x -expand yes + + set stop [Widget::cget "$path#ProgressDlg" -stop] + set cmd [Widget::cget "$path#ProgressDlg" -command] + if { $stop != "" && $cmd != "" } { + Dialog::add $path -text $stop -name $stop -command $cmd + } + Dialog::draw $path + BWidget::grab local $path + + return [Widget::create ProgressDlg $path 0] +} + + +# ---------------------------------------------------------------------------- +# Command ProgressDlg::configure +# ---------------------------------------------------------------------------- +proc ProgressDlg::configure { path args } { + return [Widget::configure "$path#ProgressDlg" $args] +} + + +# ---------------------------------------------------------------------------- +# Command ProgressDlg::cget +# ---------------------------------------------------------------------------- +proc ProgressDlg::cget { path option } { + return [Widget::cget "$path#ProgressDlg" $option] +} diff --git a/modules/tclsci/tcl/BWidget/scrollframe.tcl b/modules/tclsci/tcl/BWidget/scrollframe.tcl new file mode 100755 index 000000000..fc5e43a1f --- /dev/null +++ b/modules/tclsci/tcl/BWidget/scrollframe.tcl @@ -0,0 +1,262 @@ +# ---------------------------------------------------------------------------- +# scrollframe.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: scrollframe.tcl,v 1.11 2009/07/17 15:29:51 oehhar Exp $ +# ---------------------------------------------------------------------------- +# Index of commands: +# - ScrollableFrame::create +# - ScrollableFrame::configure +# - ScrollableFrame::cget +# - ScrollableFrame::getframe +# - ScrollableFrame::see +# - ScrollableFrame::xview +# - ScrollableFrame::yview +# - ScrollableFrame::_resize +# ---------------------------------------------------------------------------- + +namespace eval ScrollableFrame { + Widget::define ScrollableFrame scrollframe + + # If themed, there is no background and -bg option + if {[Widget::theme]} { + Widget::declare ScrollableFrame { + {-width Int 0 0 {}} + {-height Int 0 0 {}} + {-areawidth Int 0 0 {}} + {-areaheight Int 0 0 {}} + {-constrainedwidth Boolean 0 0} + {-constrainedheight Boolean 0 0} + {-xscrollcommand TkResource "" 0 canvas} + {-yscrollcommand TkResource "" 0 canvas} + {-xscrollincrement TkResource "" 0 canvas} + {-yscrollincrement TkResource "" 0 canvas} + } + } else { + Widget::declare ScrollableFrame { + {-background TkResource "" 0 frame} + {-width Int 0 0 {}} + {-height Int 0 0 {}} + {-areawidth Int 0 0 {}} + {-areaheight Int 0 0 {}} + {-constrainedwidth Boolean 0 0} + {-constrainedheight Boolean 0 0} + {-xscrollcommand TkResource "" 0 canvas} + {-yscrollcommand TkResource "" 0 canvas} + {-xscrollincrement TkResource "" 0 canvas} + {-yscrollincrement TkResource "" 0 canvas} + {-bg Synonym -background} + } + } + + Widget::addmap ScrollableFrame "" :cmd { + -width {} -height {} + -xscrollcommand {} -yscrollcommand {} + -xscrollincrement {} -yscrollincrement {} + } + if { ! [Widget::theme]} { + Widget::addmap ScrollableFrame "" .frame {-background {}} + } + + variable _widget + + bind BwScrollableFrame <Configure> [list ScrollableFrame::_resize %W] + bind BwScrollableFrame <Destroy> [list Widget::destroy %W] +} + + +# ---------------------------------------------------------------------------- +# Command ScrollableFrame::create +# ---------------------------------------------------------------------------- +proc ScrollableFrame::create { path args } { + Widget::init ScrollableFrame $path $args + + set canvas [eval [list canvas $path] [Widget::subcget $path :cmd] \ + -highlightthickness 0 -borderwidth 0 -relief flat] + + if {[Widget::theme]} { + set frame [eval [list ttk::frame $path.frame] \ + [Widget::subcget $path .frame]] + set bg [ttk::style lookup TFrame -background] + } else { + set frame [eval [list frame $path.frame] \ + [Widget::subcget $path .frame] \ + -highlightthickness 0 -borderwidth 0 -relief flat] + set bg [$frame cget -background] + } + # Give canvas frame (or theme) background + $canvas configure -background $bg + + $canvas create window 0 0 -anchor nw -window $frame -tags win \ + -width [Widget::cget $path -areawidth] \ + -height [Widget::cget $path -areaheight] + + bind $frame <Configure> \ + [list ScrollableFrame::_frameConfigure $canvas] + # add <unmap> binding: <configure> is not called when frame + # becomes so small that it suddenly falls outside of currently visible area. + # but now we need to add a <map> binding too + bind $frame <Map> \ + [list ScrollableFrame::_frameConfigure $canvas] + bind $frame <Unmap> \ + [list ScrollableFrame::_frameConfigure $canvas 1] + + bindtags $path [list $path BwScrollableFrame [winfo toplevel $path] all] + + return [Widget::create ScrollableFrame $path] +} + + +# ---------------------------------------------------------------------------- +# Command ScrollableFrame::configure +# ---------------------------------------------------------------------------- +proc ScrollableFrame::configure { path args } { + set res [Widget::configure $path $args] + set upd 0 + + set modcw [Widget::hasChanged $path -constrainedwidth cw] + set modw [Widget::hasChanged $path -areawidth w] + if { $modcw || (!$cw && $modw) } { + if { $cw } { + set w [winfo width $path] + } + set upd 1 + } + + set modch [Widget::hasChanged $path -constrainedheight ch] + set modh [Widget::hasChanged $path -areaheight h] + if { $modch || (!$ch && $modh) } { + if { $ch } { + set h [winfo height $path] + } + set upd 1 + } + + if { $upd } { + $path:cmd itemconfigure win -width $w -height $h + } + return $res +} + + +# ---------------------------------------------------------------------------- +# Command ScrollableFrame::cget +# ---------------------------------------------------------------------------- +proc ScrollableFrame::cget { path option } { + return [Widget::cget $path $option] +} + + +# ---------------------------------------------------------------------------- +# Command ScrollableFrame::getframe +# ---------------------------------------------------------------------------- +proc ScrollableFrame::getframe { path } { + return $path.frame +} + +# ---------------------------------------------------------------------------- +# Command ScrollableFrame::see +# ---------------------------------------------------------------------------- +proc ScrollableFrame::see { path widget {vert top} {horz left} {xOffset 0} {yOffset 0}} { + set x0 [winfo x $widget] + set y0 [winfo y $widget] + set x1 [expr {$x0+[winfo width $widget]}] + set y1 [expr {$y0+[winfo height $widget]}] + set xb0 [$path:cmd canvasx 0] + set yb0 [$path:cmd canvasy 0] + set xb1 [$path:cmd canvasx [winfo width $path]] + set yb1 [$path:cmd canvasy [winfo height $path]] + set dx 0 + set dy 0 + + if { [string equal $horz "left"] } { + if { $x1 > $xb1 } { + set dx [expr {$x1-$xb1}] + } + if { $x0 < $xb0+$dx } { + set dx [expr {$x0-$xb0}] + } + } elseif { [string equal $horz "right"] } { + if { $x0 < $xb0 } { + set dx [expr {$x0-$xb0}] + } + if { $x1 > $xb1+$dx } { + set dx [expr {$x1-$xb1}] + } + } + + if { [string equal $vert "top"] } { + if { $y1 > $yb1 } { + set dy [expr {$y1-$yb1}] + } + if { $y0 < $yb0+$dy } { + set dy [expr {$y0-$yb0}] + } + } elseif { [string equal $vert "bottom"] } { + if { $y0 < $yb0 } { + set dy [expr {$y0-$yb0}] + } + if { $y1 > $yb1+$dy } { + set dy [expr {$y1-$yb1}] + } + } + + if {($dx + $xOffset) != 0} { + set x [expr {($xb0+$dx+$xOffset)/[winfo width $path.frame]}] + $path:cmd xview moveto $x + } + if {($dy + $yOffset) != 0} { + set y [expr {($yb0+$dy+$yOffset)/[winfo height $path.frame]}] + $path:cmd yview moveto $y + } +} + + +# ---------------------------------------------------------------------------- +# Command ScrollableFrame::xview +# ---------------------------------------------------------------------------- +proc ScrollableFrame::xview { path args } { + return [eval [list $path:cmd xview] $args] +} + + +# ---------------------------------------------------------------------------- +# Command ScrollableFrame::yview +# ---------------------------------------------------------------------------- +proc ScrollableFrame::yview { path args } { + return [eval [list $path:cmd yview] $args] +} + + +# ---------------------------------------------------------------------------- +# Command ScrollableFrame::_resize +# ---------------------------------------------------------------------------- +proc ScrollableFrame::_resize { path } { + if { [Widget::getoption $path -constrainedwidth] } { + $path:cmd itemconfigure win -width [winfo width $path] + } + if { [Widget::getoption $path -constrainedheight] } { + $path:cmd itemconfigure win -height [winfo height $path] + } + # scollregion must also be reset when canvas size changes + _frameConfigure $path +} + + +# ---------------------------------------------------------------------------- +# Command ScrollableFrame::_frameConfigure +# ---------------------------------------------------------------------------- +proc ScrollableFrame::_max {a b} {return [expr {$a <= $b ? $b : $a}]} +proc ScrollableFrame::_frameConfigure {canvas {unmap 0}} { + # This ensures that we don't get funny scrollability in the frame + # when it is smaller than the canvas space + # use [winfo] to get height & width of frame + + # [winfo] doesn't work for unmapped frame + set frameh [expr {$unmap ? 0 : [winfo height $canvas.frame]}] + set framew [expr {$unmap ? 0 : [winfo width $canvas.frame]}] + + set height [_max $frameh [winfo height $canvas]] + set width [_max $framew [winfo width $canvas]] + + $canvas:cmd configure -scrollregion [list 0 0 $width $height] +} diff --git a/modules/tclsci/tcl/BWidget/scrollview.tcl b/modules/tclsci/tcl/BWidget/scrollview.tcl new file mode 100755 index 000000000..5fd06f5cd --- /dev/null +++ b/modules/tclsci/tcl/BWidget/scrollview.tcl @@ -0,0 +1,254 @@ +# ------------------------------------------------------------------------------ +# scrollview.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: scrollview.tcl,v 1.7 2003/11/05 18:04:29 hobbs Exp $ +# ------------------------------------------------------------------------------ +# Index of commands: +# - ScrolledWindow::create +# - ScrolledWindow::configure +# - ScrolledWindow::cget +# - ScrolledWindow::_set_hscroll +# - ScrolledWindow::_set_vscroll +# - ScrolledWindow::_update_scroll +# - ScrolledWindow::_set_view +# - ScrolledWindow::_resize +# ------------------------------------------------------------------------------ + +namespace eval ScrollView { + Widget::define ScrollView scrollview + + Widget::tkinclude ScrollView canvas :cmd \ + include {-relief -borderwidth -background -width -height -cursor} \ + initialize {-relief flat -borderwidth 0 -width 30 -height 30 \ + -cursor crosshair} + + Widget::declare ScrollView { + {-width TkResource 30 0 canvas} + {-height TkResource 30 0 canvas} + {-background TkResource "" 0 canvas} + {-foreground String black 0} + {-fill String "" 0} + {-relief TkResource flat 0 canvas} + {-borderwidth TkResource 0 0 canvas} + {-cursor TkResource crosshair 0 canvas} + {-window String "" 0} + {-fg Synonym -foreground} + {-bg Synonym -background} + {-bd Synonym -borderwidth} + } + + bind BwScrollView <B1-Motion> [list ScrollView::_set_view %W motion %x %y] + bind BwScrollView <ButtonPress-1> [list ScrollView::_set_view %W set %x %y] + bind BwScrollView <Configure> [list ScrollView::_resize %W] + bind BwScrollView <Destroy> [list ScrollView::_destroy %W] +} + + +# ------------------------------------------------------------------------------ +# Command ScrollView::create +# ------------------------------------------------------------------------------ +proc ScrollView::create { path args } { + Widget::init ScrollView $path $args + eval [list canvas $path] [Widget::subcget $path :cmd] -highlightthickness 0 + + Widget::create ScrollView $path + + Widget::getVariable $path _widget + + set w [Widget::cget $path -window] + set _widget(bd) [Widget::cget $path -borderwidth] + set _widget(width) [Widget::cget $path -width] + set _widget(height) [Widget::cget $path -height] + + if {[winfo exists $w]} { + set _widget(oldxscroll) [$w cget -xscrollcommand] + set _widget(oldyscroll) [$w cget -yscrollcommand] + $w configure \ + -xscrollcommand [list ScrollView::_set_hscroll $path] \ + -yscrollcommand [list ScrollView::_set_vscroll $path] + } + $path:cmd create rectangle -2 -2 -2 -2 \ + -fill [Widget::cget $path -fill] \ + -outline [Widget::cget $path -foreground] \ + -tags view + + bindtags $path [list $path BwScrollView [winfo toplevel $path] all] + + return $path +} + + +# ------------------------------------------------------------------------------ +# Command ScrollView::configure +# ------------------------------------------------------------------------------ +proc ScrollView::configure { path args } { + Widget::getVariable $path _widget + + set oldw [Widget::getoption $path -window] + set res [Widget::configure $path $args] + + if { [Widget::hasChanged $path -window w] } { + if { [winfo exists $oldw] } { + $oldw configure \ + -xscrollcommand $_widget(oldxscroll) \ + -yscrollcommand $_widget(oldyscroll) + } + if { [winfo exists $w] } { + set _widget(oldxscroll) [$w cget -xscrollcommand] + set _widget(oldyscroll) [$w cget -yscrollcommand] + $w configure \ + -xscrollcommand [list ScrollView::_set_hscroll $path] \ + -yscrollcommand [list ScrollView::_set_vscroll $path] + } else { + $path:cmd coords view -2 -2 -2 -2 + set _widget(oldxscroll) {} + set _widget(oldyscroll) {} + } + } + + if { [Widget::hasChanged $path -fill fill] | + [Widget::hasChanged $path -foreground fg] } { + $path:cmd itemconfigure view \ + -fill $fill \ + -outline $fg + } + + return $res +} + + +# ------------------------------------------------------------------------------ +# Command ScrollView::cget +# ------------------------------------------------------------------------------ +proc ScrollView::cget { path option } { + return [Widget::cget $path $option] +} + + +# ------------------------------------------------------------------------------ +# Command ScrollView::_set_hscroll +# ------------------------------------------------------------------------------ +proc ScrollView::_set_hscroll { path vmin vmax } { + Widget::getVariable $path _widget + + set c [$path:cmd coords view] + set x0 [expr {$vmin*$_widget(width)+$_widget(bd)}] + set x1 [expr {$vmax*$_widget(width)+$_widget(bd)-1}] + $path:cmd coords view $x0 [lindex $c 1] $x1 [lindex $c 3] + if { $_widget(oldxscroll) != "" } { + uplevel \#0 $_widget(oldxscroll) $vmin $vmax + } +} + + +# ------------------------------------------------------------------------------ +# Command ScrollView::_set_vscroll +# ------------------------------------------------------------------------------ +proc ScrollView::_set_vscroll { path vmin vmax } { + Widget::getVariable $path _widget + + set c [$path:cmd coords view] + set y0 [expr {$vmin*$_widget(height)+$_widget(bd)}] + set y1 [expr {$vmax*$_widget(height)+$_widget(bd)-1}] + $path:cmd coords view [lindex $c 0] $y0 [lindex $c 2] $y1 + if { $_widget(oldyscroll) != "" } { + uplevel \#0 $_widget(oldyscroll) $vmin $vmax + } +} + + +# ------------------------------------------------------------------------------ +# Command ScrollView::_update_scroll +# ------------------------------------------------------------------------------ +proc ScrollView::_update_scroll { path callscroll hminmax vminmax } { + Widget::getVariable $path _widget + + set c [$path:cmd coords view] + set hmin [lindex $hminmax 0] + set hmax [lindex $hminmax 1] + set vmin [lindex $vminmax 0] + set vmax [lindex $vminmax 1] + set x0 [expr {$hmin*$_widget(width)+$_widget(bd)}] + set x1 [expr {$hmax*$_widget(width)+$_widget(bd)-1}] + set y0 [expr {$vmin*$_widget(height)+$_widget(bd)}] + set y1 [expr {$vmax*$_widget(height)+$_widget(bd)-1}] + $path:cmd coords view $x0 $y0 $x1 $y1 + if { $callscroll } { + if { $_widget(oldxscroll) != "" } { + uplevel \#0 $_widget(oldxscroll) $hmin $hmax + } + if { $_widget(oldyscroll) != "" } { + uplevel \#0 $_widget(oldyscroll) $vmin $vmax + } + } +} + + +# ------------------------------------------------------------------------------ +# Command ScrollView::_set_view +# ------------------------------------------------------------------------------ +proc ScrollView::_set_view { path cmd x y } { + Widget::getVariable $path _widget + + set w [Widget::getoption $path -window] + if {[winfo exists $w]} { + if {[string equal $cmd "set"]} { + set c [$path:cmd coords view] + set x0 [lindex $c 0] + set y0 [lindex $c 1] + set x1 [lindex $c 2] + set y1 [lindex $c 3] + if {$x >= $x0 && $x <= $x1 && + $y >= $y0 && $y <= $y1} { + set _widget(dx) [expr {$x-$x0}] + set _widget(dy) [expr {$y-$y0}] + return + } else { + set x0 [expr {$x-($x1-$x0)/2}] + set y0 [expr {$y-($y1-$y0)/2}] + set _widget(dx) [expr {$x-$x0}] + set _widget(dy) [expr {$y-$y0}] + set vh [expr {double($x0-$_widget(bd))/$_widget(width)}] + set vv [expr {double($y0-$_widget(bd))/$_widget(height)}] + } + } elseif {[string equal $cmd "motion"]} { + set vh [expr {double($x-$_widget(dx)-$_widget(bd))/$_widget(width)}] + set vv [expr {double($y-$_widget(dy)-$_widget(bd))/$_widget(height)}] + } + $w xview moveto $vh + $w yview moveto $vv + _update_scroll $path 1 [$w xview] [$w yview] + } +} + + +# ------------------------------------------------------------------------------ +# Command ScrollView::_resize +# ------------------------------------------------------------------------------ +proc ScrollView::_resize { path } { + Widget::getVariable $path _widget + + set _widget(bd) [Widget::getoption $path -borderwidth] + set _widget(width) [expr {[winfo width $path]-2*$_widget(bd)}] + set _widget(height) [expr {[winfo height $path]-2*$_widget(bd)}] + set w [Widget::getoption $path -window] + if { [winfo exists $w] } { + _update_scroll $path 0 [$w xview] [$w yview] + } +} + + +# ------------------------------------------------------------------------------ +# Command ScrollView::_destroy +# ------------------------------------------------------------------------------ +proc ScrollView::_destroy { path } { + Widget::getVariable $path _widget + + set w [Widget::getoption $path -window] + if { [winfo exists $w] } { + $w configure \ + -xscrollcommand $_widget(oldxscroll) \ + -yscrollcommand $_widget(oldyscroll) + } + Widget::destroy $path +} diff --git a/modules/tclsci/tcl/BWidget/scrollw.tcl b/modules/tclsci/tcl/BWidget/scrollw.tcl new file mode 100755 index 000000000..d81a5a4f4 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/scrollw.tcl @@ -0,0 +1,294 @@ +# ----------------------------------------------------------------------------- +# scrollw.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: scrollw.tcl,v 1.13.2.1 2010/11/23 08:21:17 oehhar Exp $ +# ----------------------------------------------------------------------------- +# Index of commands: +# - ScrolledWindow::create +# - ScrolledWindow::getframe +# - ScrolledWindow::setwidget +# - ScrolledWindow::configure +# - ScrolledWindow::cget +# - ScrolledWindow::_set_hframe +# - ScrolledWindow::_set_vscroll +# - ScrolledWindow::_setData +# - ScrolledWindow::_setSBSize +# - ScrolledWindow::_realize +# ----------------------------------------------------------------------------- + +namespace eval ScrolledWindow { + Widget::define ScrolledWindow scrollw + + Widget::declare ScrolledWindow { + {-background TkResource "" 0 button} + {-scrollbar Enum both 0 {none both vertical horizontal}} + {-auto Enum both 0 {none both vertical horizontal}} + {-sides Enum se 0 {ne en nw wn se es sw ws}} + {-size Int 0 1 "%d >= 0"} + {-ipad Int 1 1 "%d >= 0"} + {-managed Boolean 1 1} + {-relief TkResource flat 0 frame} + {-borderwidth TkResource 0 0 frame} + {-bg Synonym -background} + {-bd Synonym -borderwidth} + } + + Widget::addmap ScrolledWindow "" :cmd {-relief {} -borderwidth {}} +} + + +# ----------------------------------------------------------------------------- +# Command ScrolledWindow::create +# ----------------------------------------------------------------------------- +proc ScrolledWindow::create { path args } { + Widget::init ScrolledWindow $path $args + + Widget::getVariable $path data + + set bg [Widget::cget $path -background] + set sbsize [Widget::cget $path -size] + + if { $::Widget::_theme } { + set sw [eval [list ttk::frame $path \ + -relief flat -borderwidth 0 -takefocus 0] \ + [Widget::subcget $path :cmd]] + ttk::scrollbar $path.hscroll \ + -takefocus 0 -orient horiz + ttk::scrollbar $path.vscroll \ + -takefocus 0 -orient vert + } else { + set sw [eval [list frame $path \ + -relief flat -borderwidth 0 -background $bg \ + -highlightthickness 0 -takefocus 0] \ + [Widget::subcget $path :cmd]] + scrollbar $path.hscroll \ + -highlightthickness 0 -takefocus 0 \ + -orient horiz \ + -relief sunken \ + -bg $bg + scrollbar $path.vscroll \ + -highlightthickness 0 -takefocus 0 \ + -orient vert \ + -relief sunken \ + -bg $bg + } + + set data(realized) 0 + + _setData $path \ + [Widget::cget $path -scrollbar] \ + [Widget::cget $path -auto] \ + [Widget::cget $path -sides] + + if {[Widget::cget $path -managed]} { + set data(hsb,packed) $data(hsb,present) + set data(vsb,packed) $data(vsb,present) + } else { + set data(hsb,packed) 0 + set data(vsb,packed) 0 + } + if { ! $::Widget::_theme } { + if {$sbsize} { + $path.vscroll configure -width $sbsize + $path.hscroll configure -width $sbsize + } else { + set sbsize [$path.vscroll cget -width] + } + } + set data(ipad) [Widget::cget $path -ipad] + + if {$data(hsb,packed)} { + grid $path.hscroll -column 1 -row $data(hsb,row) \ + -sticky ew -ipady $data(ipad) + } + if {$data(vsb,packed)} { + grid $path.vscroll -column $data(vsb,column) -row 1 \ + -sticky ns -ipadx $data(ipad) + } + + grid columnconfigure $path 1 -weight 1 + grid rowconfigure $path 1 -weight 1 + + bind $path <Configure> [list ScrolledWindow::_realize $path] + bind $path <Destroy> [list ScrolledWindow::_destroy $path] + + return [Widget::create ScrolledWindow $path] +} + + +# ----------------------------------------------------------------------------- +# Command ScrolledWindow::getframe +# ----------------------------------------------------------------------------- +proc ScrolledWindow::getframe { path } { + return $path +} + + +# ----------------------------------------------------------------------------- +# Command ScrolledWindow::setwidget +# ----------------------------------------------------------------------------- +proc ScrolledWindow::setwidget { path widget } { + Widget::getVariable $path data + + if {[info exists data(widget)] && [winfo exists $data(widget)] + && ![string equal $data(widget) $widget]} { + grid remove $data(widget) + $data(widget) configure -xscrollcommand "" -yscrollcommand "" + } + set data(widget) $widget + grid $widget -in $path -row 1 -column 1 -sticky news + + $path.hscroll configure -command [list $widget xview] + $path.vscroll configure -command [list $widget yview] + $widget configure \ + -xscrollcommand [list ScrolledWindow::_set_hscroll $path] \ + -yscrollcommand [list ScrolledWindow::_set_vscroll $path] +} + + +# ----------------------------------------------------------------------------- +# Command ScrolledWindow::configure +# ----------------------------------------------------------------------------- +proc ScrolledWindow::configure { path args } { + Widget::getVariable $path data + + set res [Widget::configure $path $args] + if { ! $::Widget::_theme && [Widget::hasChanged $path -background bg] } { + $path configure -background $bg + catch {$path.hscroll configure -background $bg} + catch {$path.vscroll configure -background $bg} + } + + if {[Widget::hasChanged $path -scrollbar scrollbar] | \ + [Widget::hasChanged $path -auto auto] | \ + [Widget::hasChanged $path -sides sides]} { + _setData $path $scrollbar $auto $sides + foreach {vmin vmax} [$path.hscroll get] { break } + set data(hsb,packed) [expr {$data(hsb,present) && \ + (!$data(hsb,auto) || ($vmin != 0 || $vmax != 1))}] + foreach {vmin vmax} [$path.vscroll get] { break } + set data(vsb,packed) [expr {$data(vsb,present) && \ + (!$data(vsb,auto) || ($vmin != 0 || $vmax != 1))}] + + set data(ipad) [Widget::cget $path -ipad] + + if {$data(hsb,packed)} { + grid $path.hscroll -column 1 -row $data(hsb,row) \ + -sticky ew -ipady $data(ipad) + } else { + if {![info exists data(hlock)]} { + set data(hsb,packed) 0 + grid remove $path.hscroll + } + } + if {$data(vsb,packed)} { + grid $path.vscroll -column $data(vsb,column) -row 1 \ + -sticky ns -ipadx $data(ipad) + } else { + if {![info exists data(hlock)]} { + set data(vsb,packed) 0 + grid remove $path.vscroll + } + } + } + return $res +} + + +# ----------------------------------------------------------------------------- +# Command ScrolledWindow::cget +# ----------------------------------------------------------------------------- +proc ScrolledWindow::cget { path option } { + return [Widget::cget $path $option] +} + + +# ----------------------------------------------------------------------------- +# Command ScrolledWindow::_set_hscroll +# ----------------------------------------------------------------------------- +proc ScrolledWindow::_set_hscroll { path vmin vmax } { + Widget::getVariable $path data + + if {$data(realized) && $data(hsb,present)} { + if {$data(hsb,auto) && ![info exists data(hlock)]} { + if {$data(hsb,packed) && $vmin == 0 && $vmax == 1} { + set data(hsb,packed) 0 + grid remove $path.hscroll + set data(hlock) 1 + update idletasks + unset data(hlock) + } elseif {!$data(hsb,packed) && ($vmin != 0 || $vmax != 1)} { + set data(hsb,packed) 1 + grid $path.hscroll -column 1 -row $data(hsb,row) \ + -sticky ew -ipady $data(ipad) + set data(hlock) 1 + update idletasks + unset data(hlock) + } + } + $path.hscroll set $vmin $vmax + } +} + + +# ----------------------------------------------------------------------------- +# Command ScrolledWindow::_set_vscroll +# ----------------------------------------------------------------------------- +proc ScrolledWindow::_set_vscroll { path vmin vmax } { + Widget::getVariable $path data + + if {$data(realized) && $data(vsb,present)} { + if {$data(vsb,auto) && ![info exists data(vlock)]} { + if {$data(vsb,packed) && $vmin == 0 && $vmax == 1} { + set data(vsb,packed) 0 + grid remove $path.vscroll + set data(vlock) 1 + update idletasks + unset data(vlock) + } elseif {!$data(vsb,packed) && ($vmin != 0 || $vmax != 1) } { + set data(vsb,packed) 1 + grid $path.vscroll -column $data(vsb,column) -row 1 \ + -sticky ns -ipadx $data(ipad) + set data(vlock) 1 + update idletasks + unset data(vlock) + } + } + $path.vscroll set $vmin $vmax + } +} + + +proc ScrolledWindow::_setData {path scrollbar auto sides} { + Widget::getVariable $path data + + set sb [lsearch {none horizontal vertical both} $scrollbar] + set auto [lsearch {none horizontal vertical both} $auto] + + set data(hsb,present) [expr {($sb & 1) != 0}] + set data(hsb,auto) [expr {($auto & 1) != 0}] + set data(hsb,row) [expr {[string match *n* $sides] ? 0 : 2}] + + set data(vsb,present) [expr {($sb & 2) != 0}] + set data(vsb,auto) [expr {($auto & 2) != 0}] + set data(vsb,column) [expr {[string match *w* $sides] ? 0 : 2}] +} + + +# ----------------------------------------------------------------------------- +# Command ScrolledWindow::_realize +# ----------------------------------------------------------------------------- +proc ScrolledWindow::_realize { path } { + Widget::getVariable $path data + + bind $path <Configure> {} + set data(realized) 1 +} + + +# ----------------------------------------------------------------------------- +# Command ScrolledWindow::_destroy +# ----------------------------------------------------------------------------- +proc ScrolledWindow::_destroy { path } { + Widget::destroy $path +} diff --git a/modules/tclsci/tcl/BWidget/separator.tcl b/modules/tclsci/tcl/BWidget/separator.tcl new file mode 100755 index 000000000..bae87b5ac --- /dev/null +++ b/modules/tclsci/tcl/BWidget/separator.tcl @@ -0,0 +1,75 @@ +# ------------------------------------------------------------------------------ +# separator.tcl +# This file is part of Unifix BWidget Toolkit +# ------------------------------------------------------------------------------ +# Index of commands: +# - Separator::create +# - Separator::configure +# - Separator::cget +# ------------------------------------------------------------------------------ + +namespace eval Separator { + Widget::define Separator separator + + Widget::declare Separator { + {-background TkResource "" 0 frame} + {-cursor TkResource "" 0 frame} + {-relief Enum groove 0 {ridge groove}} + {-orient Enum horizontal 1 {horizontal vertical}} + {-bg Synonym -background} + } + Widget::addmap Separator "" :cmd { -background {} -cursor {} } + + bind Separator <Destroy> [list Widget::destroy %W] +} + + +# ------------------------------------------------------------------------------ +# Command Separator::create +# ------------------------------------------------------------------------------ +proc Separator::create { path args } { + array set maps [list Separator {} :cmd {}] + array set maps [Widget::parseArgs Separator $args] + eval [list frame $path] $maps(:cmd) -class Separator + Widget::initFromODB Separator $path $maps(Separator) + + if { [Widget::cget $path -orient] == "horizontal" } { + $path configure -borderwidth 1 -height 2 + } else { + $path configure -borderwidth 1 -width 2 + } + + if { [string equal [Widget::cget $path -relief] "groove"] } { + $path configure -relief sunken + } else { + $path configure -relief raised + } + + return [Widget::create Separator $path] +} + + +# ------------------------------------------------------------------------------ +# Command Separator::configure +# ------------------------------------------------------------------------------ +proc Separator::configure { path args } { + set res [Widget::configure $path $args] + + if { [Widget::hasChanged $path -relief relief] } { + if { $relief == "groove" } { + $path:cmd configure -relief sunken + } else { + $path:cmd configure -relief raised + } + } + + return $res +} + + +# ------------------------------------------------------------------------------ +# Command Separator::cget +# ------------------------------------------------------------------------------ +proc Separator::cget { path option } { + return [Widget::cget $path $option] +} diff --git a/modules/tclsci/tcl/BWidget/spinbox.tcl b/modules/tclsci/tcl/BWidget/spinbox.tcl new file mode 100755 index 000000000..a89e3754f --- /dev/null +++ b/modules/tclsci/tcl/BWidget/spinbox.tcl @@ -0,0 +1,331 @@ +# spinbox.tcl -- +# +# BWidget SpinBox implementation. +# +# Copyright (c) 1999 by Unifix +# Copyright (c) 2000 by Ajuba Solutions +# All rights reserved. +# +# RCS: @(#) $Id: spinbox.tcl,v 1.12 2003/10/20 21:23:52 damonc Exp $ +# ----------------------------------------------------------------------------- +# Index of commands: +# - SpinBox::create +# - SpinBox::configure +# - SpinBox::cget +# - SpinBox::setvalue +# - SpinBox::_destroy +# - SpinBox::_modify_value +# - SpinBox::_test_options +# ----------------------------------------------------------------------------- + +namespace eval SpinBox { + Widget::define SpinBox spinbox Entry ArrowButton + + Widget::tkinclude SpinBox frame :cmd \ + include {-background -borderwidth -bg -bd -relief} \ + initialize {-relief sunken -borderwidth 2} + + Widget::bwinclude SpinBox Entry .e \ + remove {-relief -bd -borderwidth -fg -bg} \ + rename {-foreground -entryfg -background -entrybg} + + Widget::declare SpinBox { + {-range String "" 0} + {-values String "" 0} + {-modifycmd String "" 0} + {-repeatdelay Int 400 0 {%d >= 0}} + {-repeatinterval Int 100 0 {%d >= 0}} + {-foreground TkResource black 0 {button}} + } + + Widget::addmap SpinBox "" :cmd {-background {}} + Widget::addmap SpinBox ArrowButton .arrup { + -foreground {} -background {} -disabledforeground {} -state {} \ + -repeatinterval {} -repeatdelay {} + } + Widget::addmap SpinBox ArrowButton .arrdn { + -foreground {} -background {} -disabledforeground {} -state {} \ + -repeatinterval {} -repeatdelay {} + } + + ::bind SpinBox <FocusIn> [list after idle {BWidget::refocus %W %W.e}] + ::bind SpinBox <Destroy> [list SpinBox::_destroy %W] + + variable _widget +} + + +# ----------------------------------------------------------------------------- +# Command SpinBox::create +# ----------------------------------------------------------------------------- +proc SpinBox::create { path args } { + array set maps [list SpinBox {} :cmd {} .e {} .arrup {} .arrdn {}] + array set maps [Widget::parseArgs SpinBox $args] + eval [list frame $path] $maps(:cmd) \ + [list -highlightthickness 0 -takefocus 0 -class SpinBox] + Widget::initFromODB SpinBox $path $maps(SpinBox) + + set entry [eval [list Entry::create $path.e] $maps(.e) -relief flat -bd 0] + bindtags $path.e [linsert [bindtags $path.e] 1 SpinBoxEntry] + + set farr [frame $path.farr -relief flat -bd 0 -highlightthickness 0] + set height [expr {[winfo reqheight $path.e]/2-2}] + set width 11 + set arrup [eval [list ArrowButton::create $path.arrup -dir top] \ + $maps(.arrup) \ + [list -highlightthickness 0 -borderwidth 1 -takefocus 0 \ + -type button -width $width -height $height \ + -armcommand [list SpinBox::_modify_value $path next arm] \ + -disarmcommand [list SpinBox::_modify_value $path next disarm]]] + set arrdn [eval [list ArrowButton::create $path.arrdn -dir bottom] \ + $maps(.arrdn) \ + [list -highlightthickness 0 -borderwidth 1 -takefocus 0 \ + -type button -width $width -height $height \ + -armcommand [list SpinBox::_modify_value $path previous arm] \ + -disarmcommand [list SpinBox::_modify_value $path previous disarm]]] + + # --- update SpinBox value --- + _test_options $path + set val [Entry::cget $path.e -text] + if { [string equal $val ""] } { + Entry::configure $path.e -text $::SpinBox::_widget($path,curval) + } else { + set ::SpinBox::_widget($path,curval) $val + } + + grid $arrup -in $farr -column 0 -row 0 -sticky nsew + grid $arrdn -in $farr -column 0 -row 2 -sticky nsew + grid rowconfigure $farr 0 -weight 1 + grid rowconfigure $farr 2 -weight 1 + + pack $farr -side right -fill y + pack $entry -side left -fill both -expand yes + + ::bind $entry <Key-Up> [list SpinBox::_modify_value $path next activate] + ::bind $entry <Key-Down> [list SpinBox::_modify_value $path previous activate] + ::bind $entry <Key-Prior> [list SpinBox::_modify_value $path last activate] + ::bind $entry <Key-Next> [list SpinBox::_modify_value $path first activate] + + ::bind $farr <Configure> {grid rowconfigure %W 1 -minsize [expr {%h%%2}]} + + return [Widget::create SpinBox $path] +} + +# ----------------------------------------------------------------------------- +# Command SpinBox::configure +# ----------------------------------------------------------------------------- +proc SpinBox::configure { path args } { + set res [Widget::configure $path $args] + if { [Widget::hasChangedX $path -values] || + [Widget::hasChangedX $path -range] } { + _test_options $path + } + return $res +} + + +# ----------------------------------------------------------------------------- +# Command SpinBox::cget +# ----------------------------------------------------------------------------- +proc SpinBox::cget { path option } { + return [Widget::cget $path $option] +} + + +# ----------------------------------------------------------------------------- +# Command SpinBox::setvalue +# ----------------------------------------------------------------------------- +proc SpinBox::setvalue { path index } { + variable _widget + + set values [Widget::getMegawidgetOption $path -values] + set value [Entry::cget $path.e -text] + + if { [llength $values] } { + # --- -values SpinBox --- + switch -- $index { + next { + if { [set idx [lsearch $values $value]] != -1 } { + incr idx + } elseif { [set idx [lsearch $values "$value*"]] == -1 } { + set idx [lsearch $values $_widget($path,curval)] + } + } + previous { + if { [set idx [lsearch $values $value]] != -1 } { + incr idx -1 + } elseif { [set idx [lsearch $values "$value*"]] == -1 } { + set idx [lsearch $values $_widget($path,curval)] + } + } + first { + set idx 0 + } + last { + set idx [expr {[llength $values]-1}] + } + default { + if { [string index $index 0] == "@" } { + set idx [string range $index 1 end] + if { [catch {string compare [expr {int($idx)}] $idx} res] || $res != 0 } { + return -code error "bad index \"$index\"" + } + } else { + return -code error "bad index \"$index\"" + } + } + } + if { $idx >= 0 && $idx < [llength $values] } { + set newval [lindex $values $idx] + } else { + return 0 + } + } else { + # --- -range SpinBox --- + foreach {vmin vmax incr} [Widget::getMegawidgetOption $path -range] { + break + } + # Allow zero padding on the value; strip it out for calculation by + # scanning the value into a floating point number. + scan $value %f value + switch -- $index { + next { + if { [catch {expr {double($value-$vmin)/$incr}} idx] } { + set newval $_widget($path,curval) + } else { + set newval [expr {$vmin+(round($idx)+1)*$incr}] + if { $newval < $vmin } { + set newval $vmin + } elseif { $newval > $vmax } { + set newval $vmax + } + } + } + previous { + if { [catch {expr {double($value-$vmin)/$incr}} idx] } { + set newval $_widget($path,curval) + } else { + set newval [expr {$vmin+(round($idx)-1)*$incr}] + if { $newval < $vmin } { + set newval $vmin + } elseif { $newval > $vmax } { + set newval $vmax + } + } + } + first { + set newval $vmin + } + last { + set newval $vmax + } + default { + if { [string index $index 0] == "@" } { + set idx [string range $index 1 end] + if { [catch {string compare [expr {int($idx)}] $idx} res] || $res != 0 } { + return -code error "bad index \"$index\"" + } + set newval [expr {$vmin+int($idx)*$incr}] + if { $newval < $vmin || $newval > $vmax } { + return 0 + } + } else { + return -code error "bad index \"$index\"" + } + } + } + } + set _widget($path,curval) $newval + Entry::configure $path.e -text $newval + return 1 +} + + +# ----------------------------------------------------------------------------- +# Command SpinBox::getvalue +# ----------------------------------------------------------------------------- +proc SpinBox::getvalue { path } { + variable _widget + + set values [Widget::getMegawidgetOption $path -values] + set value [Entry::cget $path.e -text] + + if { [llength $values] } { + # --- -values SpinBox --- + return [lsearch $values $value] + } else { + foreach {vmin vmax incr} [Widget::getMegawidgetOption $path -range] { + break + } + if { ![catch {expr {double($value-$vmin)/$incr}} idx] && + $idx == int($idx) } { + return [expr {int($idx)}] + } + return -1 + } +} + + +# ----------------------------------------------------------------------------- +# Command SpinBox::bind +# ----------------------------------------------------------------------------- +proc SpinBox::bind { path args } { + return [eval [list ::bind $path.e] $args] +} + + +# ----------------------------------------------------------------------------- +# Command SpinBox::_modify_value +# ----------------------------------------------------------------------------- +proc SpinBox::_modify_value { path direction reason } { + if { $reason == "arm" || $reason == "activate" } { + SpinBox::setvalue $path $direction + } + if { ($reason == "disarm" || $reason == "activate") && + [set cmd [Widget::getMegawidgetOption $path -modifycmd]] != "" } { + uplevel \#0 $cmd + } +} + +# ----------------------------------------------------------------------------- +# Command SpinBox::_test_options +# ----------------------------------------------------------------------------- +proc SpinBox::_test_options { path } { + set values [Widget::getMegawidgetOption $path -values] + if { [llength $values] } { + set ::SpinBox::_widget($path,curval) [lindex $values 0] + } else { + foreach {vmin vmax incr} [Widget::getMegawidgetOption $path -range] { + break + } + set update 0 + if { [catch {expr {int($vmin)}}] } { + set vmin 0 + set update 1 + } + if { [catch {expr {$vmax<$vmin}} res] || $res } { + set vmax $vmin + set update 1 + } + if { [catch {expr {$incr<0}} res] || $res } { + set incr 1 + set update 1 + } + # Only do the set back (which is expensive) if we changed a value + if { $update } { + Widget::setMegawidgetOption $path -range [list $vmin $vmax $incr] + } + set ::SpinBox::_widget($path,curval) $vmin + } +} + + +# ----------------------------------------------------------------------------- +# Command SpinBox::_destroy +# ----------------------------------------------------------------------------- +proc SpinBox::_destroy { path } { + variable _widget + + unset _widget($path,curval) + Widget::destroy $path +} diff --git a/modules/tclsci/tcl/BWidget/statusbar.tcl b/modules/tclsci/tcl/BWidget/statusbar.tcl new file mode 100755 index 000000000..568c4acda --- /dev/null +++ b/modules/tclsci/tcl/BWidget/statusbar.tcl @@ -0,0 +1,422 @@ +# ------------------------------------------------------------------------ +# statusbar.tcl +# Create a status bar Tk widget +# +# Provides a status bar to be placed at the bottom of a toplevel. +# Currently does not support being placed in a toplevel that has +# gridding applied (via widget -setgrid or wm grid). +# +# Ensure that the widget is placed at the very bottom of the toplevel, +# otherwise the resize behavior may behave oddly. +# ------------------------------------------------------------------------ + +package require Tk 8.3 + +if {0} { + proc sample {} { + # sample usage + eval destroy [winfo children .] + pack [text .t -width 0 -height 0] -fill both -expand 1 + + set sbar .s + StatusBar $sbar + pack $sbar -side bottom -fill x + set f [$sbar getframe] + + # Specify -width 1 for the label widget so it truncates nicely + # instead of requesting large sizes for long messages + set w [label $f.status -width 1 -anchor w -textvariable ::STATUS] + set ::STATUS "This is a status message" + # give the entry weight, as we want it to be the one that expands + $sbar add $w -weight 1 + + # BWidget's progressbar + set w [ProgressBar $f.bpbar -orient horizontal \ + -variable ::PROGRESS -bd 1 -relief sunken] + set ::PROGRESS 50 + $sbar add $w + } +} + +namespace eval StatusBar { + Widget::define StatusBar statusbar + + Widget::declare StatusBar { + {-background TkResource "" 0 frame} + {-borderwidth TkResource 0 0 frame} + {-relief TkResource flat 0 frame} + {-showseparator Boolean 1 0} + {-showresizesep Boolean 0 0} + {-showresize Boolean 1 0} + {-width TkResource 100 0 frame} + {-height TkResource 18 0 frame} + {-ipad String 1 0} + {-pad String 0 0} + {-bg Synonym -background} + {-bd Synonym -borderwidth} + } + + # -background, -borderwidth and -relief apply to outer frame, but relief + # should be left flat for proper look + Widget::addmap StatusBar "" :cmd { + -background {} -width {} -height {} -borderwidth {} -relief {} + } + Widget::addmap StatusBar "" .sbar { + -background {} + } + Widget::addmap StatusBar "" .resize { + -background {} + } + Widget::addmap StatusBar "" .hsep { + -background {} + } + + # -pad provides general padding around the status bar + # -ipad provides padding around each status bar item + # Padding can be a list of {padx pady} + + variable HaveMarlett \ + [expr {[lsearch -exact [font families] "Marlett"] != -1}] + + bind StatusResize <1> \ + [namespace code [list begin_resize %W %X %Y]] + bind StatusResize <B1-Motion> \ + [namespace code [list continue_resize %W %X %Y]] + bind StatusResize <ButtonRelease-1> \ + [namespace code [list end_resize %W %X %Y]] + + bind StatusBar <Destroy> [list StatusBar::_destroy %W] + + # PNG version has partial alpha transparency for better look + variable pngdata { + iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAFM0aXcAAAABGdBTUEAAYagM + eiWXwAAAGJJREFUGJW9kVEOgCAMQzs8GEezN69fkKlbUAz2r3l5NGTA+pCU+Q + IA5sv39wGgZKClZGBhJMVTklRr3VNwMz04mVfQzQiEm79EkrYZycxIkq8kkv2 + v6RFGku9TUrj8RGr9AGy6mhv2ymLwAAAAAElFTkSuQmCC + } + variable gifdata { + R0lGODlhDwAPAJEAANnZ2f///4CAgD8/PyH5BAEAAAAALAAAAAAPAA8AAAJEh + I+py+1IQvh4IZlG0Qg+QshkAokGQfAvZCBIhG8hA0Ea4UPIQJBG+BAyEKQhCH + bIQAgNEQCAIA0hAyE0AEIGgjSEDBQAOw== + } + if {[package provide img::png] != ""} { + image create photo ::StatusBar::resizer -format PNG -data $pngdata + } else { + image create photo ::StatusBar::resizer -format GIF -data $gifdata + } +} + + +# ------------------------------------------------------------------------ +# Command StatusBar::create +# ------------------------------------------------------------------------ +proc StatusBar::create { path args } { + variable _widget + variable HaveMarlett + + # Allow for img::png loaded after initial source + if {[package provide img::png] != ""} { + variable pngdata + ::StatusBar::resizer configure -format PNG -data $pngdata + } + + Widget::init StatusBar $path $args + + eval [list frame $path -class StatusBar] [Widget::subcget $path :cmd] + + foreach {padx pady} [_padval [Widget::cget $path -pad]] \ + {ipadx ipady} [_padval [Widget::cget $path -ipad]] { break } + + if {[Widget::theme]} { + set sbar [ttk::frame $path.sbar -padding [list $padx $pady]] + } else { + set sbar [eval [list frame $path.sbar -padx $padx -pady $pady] \ + [Widget::subcget $path .sbar]] + } + if {[string equal $::tcl_platform(platform) "windows"]} { + set cursor size_nw_se + } else { + set cursor sizing; # bottom_right_corner ?? + } + set resize [eval [list label $path.resize] \ + [Widget::subcget $path .resize] \ + [list -borderwidth 0 -relief flat -anchor se \ + -cursor $cursor -anchor se -padx 0 -pady 0]] + if {$HaveMarlett} { + $resize configure -font "Marlett -16" -text \u006f + } else { + $resize configure -image ::StatusBar::resizer + } + bindtags $resize [list all [winfo toplevel $path] StatusResize $resize] + + if {[Widget::theme]} { + set fsep [ttk::separator $path.hsep -orient horizontal] + } else { + set fsep [eval [list frame $path.hsep -bd 1 -height 2 -relief sunken] \ + [Widget::subcget $path .hsep]] + } + set sep [_sep $path sepresize {}] + + grid $fsep -row 0 -column 0 -columnspan 3 -sticky ew + grid $sbar -row 1 -column 0 -sticky news + grid $sep -row 1 -column 1 -sticky ns -padx $ipadx -pady $ipady + grid $resize -row 1 -column 2 -sticky news + grid columnconfigure $path 0 -weight 1 + if {![Widget::cget $path -showseparator]} { + grid remove $fsep + } + if {![Widget::cget $path -showresize]} { + grid remove $sep $resize + } elseif {![Widget::cget $path -showresizesep]} { + grid remove $sep + } + set _widget($path,items) {} + + return [Widget::create StatusBar $path] +} + + +# ------------------------------------------------------------------------ +# Command StatusBar::configure +# ------------------------------------------------------------------------ +proc StatusBar::configure { path args } { + variable _widget + + set res [Widget::configure $path $args] + + foreach {chshow chshowrsep chshowsep chipad chpad} \ + [Widget::hasChangedX $path -showresize -showresizesep -showseparator \ + -ipad -pad] { break } + + if {$chshow} { + set show [Widget::cget $path -showresize] + set showrsep [Widget::cget $path -showresizesep] + if {$show} { + if {$showrsep} { + grid $path.sepresize + } + grid $path.resize + } else { + grid remove $path.sepresize $path.resize + } + } + if {$chshowsep} { + if {$show} { + grid $path.hsep + } else { + grid remove $path.hsep + } + } + if {$chipad} { + foreach {ipadx ipady} [_padval [Widget::cget $path -ipad]] { break } + foreach w [grid slaves $path.sbar] { + grid configure $w -padx $ipadx -pady $ipady + } + } + if {$chpad} { + foreach {padx pady} [_padval [Widget::cget $path -pad]] { break } + if {[string equal [winfo class $path.sbar] "TFrame"]} { + $path.sbar configure -padding [list $padx $pady] + } else { + $path.sbar configure -padx $padx -pady $pady + } + } + return $res +} + + +# ------------------------------------------------------------------------ +# Command StatusBar::cget +# ------------------------------------------------------------------------ +proc StatusBar::cget { path option } { + return [Widget::cget $path $option] +} + +# ------------------------------------------------------------------------ +# Command StatusBar::getframe +# ------------------------------------------------------------------------ +proc StatusBar::getframe {path} { + # This is the frame that users should place their statusbar widgets in + return $path.sbar +} + +# ------------------------------------------------------------------------ +# Command StatusBar::add +# ------------------------------------------------------------------------ +proc StatusBar::add {path w args} { + variable _widget + + array set opts [list \ + -weight 0 \ + -separator 1 \ + -sticky news \ + -pad [Widget::cget $path -ipad] \ + ] + foreach {key val} $args { + if {[info exists opts($key)]} { + set opts($key) $val + } else { + set msg "unknown option \"$key\", must be one of: " + append msg [join [lsort [array names opts]] {, }] + return -code error $msg + } + } + foreach {ipadx ipady} [_padval $opts(-pad)] { break } + + set sbar $path.sbar + foreach {cols rows} [grid size $sbar] break + # Add separator if requested, and we aren't the first element + if {$opts(-separator) && $cols != 0} { + set sep [_sep $path sep[winfo name $w]] + # only append name, to distinguish us from them + lappend _widget($path,items) [winfo name $sep] + grid $sep -in $sbar -row 0 -column $cols \ + -sticky ns -padx $ipadx -pady $ipady + incr cols + } + + lappend _widget($path,items) $w + grid $w -in $sbar -row 0 -column $cols -sticky $opts(-sticky) \ + -padx $ipadx -pady $ipady + grid columnconfigure $sbar $cols -weight $opts(-weight) + + return $w +} + +# ------------------------------------------------------------------------ +# Command StatusBar::delete +# ------------------------------------------------------------------------ +proc StatusBar::remove {path args} { + variable _widget + + set destroy [string equal [lindex $args 0] "-destroy"] + if {$destroy} { + set args [lrange $args 1 end] + } + foreach w $args { + set idx [lsearch -exact $_widget($path,items) $w] + if {$idx == -1 || ![winfo exists $w]} { + # ignore unknown or non-widget items (like our separators) + continue + } + # separator is always previous item + set sidx [expr {$idx - 1}] + set sep [lindex $_widget($path,items) $sidx] + if {[string match .* $sep]} { + # not one of our separators + incr sidx + } elseif {$sep != ""} { + # destroy separator too + set sep $path.sbar.$sep + destroy $sep + } + if {$destroy} { + destroy $w + } else { + grid forget $w + } + if {$idx == 0} { + # separator of next item is no longer necessary + set sep [lindex $_widget($path,items) [expr {$idx + 1}]] + if {$sep != "" && ![string match .* $sep]} { + incr idx + set sep $path.sbar.$sep + destroy $sep + } + } + set _widget($path,items) [lreplace $_widget($path,items) $sidx $idx] + } +} + +# ------------------------------------------------------------------------ +# Command StatusBar::delete +# ------------------------------------------------------------------------ +proc StatusBar::delete {path args} { + return [StatusBar::remove $path -destroy $args] +} + +# ------------------------------------------------------------------------ +# Command StatusBar::items +# ------------------------------------------------------------------------ +proc StatusBar::items {path} { + variable _widget + return $_widget($path,items) +} + +proc StatusBar::_sep {path name {sub .sbar}} { + if {[Widget::theme]} { + return [ttk::separator $path$sub.$name -orient vertical] + } else { + return [frame $path$sub.$name -bd 1 -width 2 -relief sunken] + } +} + +proc StatusBar::_padval {padval} { + set len [llength $padval] + foreach {a b} $padval { break } + if {$len == 0 || $len > 2} { + return -code error \ + "invalid pad value \"$padval\", must be 1 or 2 pixel values" + } elseif {$len == 1} { + return [list $a $a] + } elseif {$len == 2} { + return $padval + } +} + +# ------------------------------------------------------------------------ +# Command StatusBar::_destroy +# ------------------------------------------------------------------------ +proc StatusBar::_destroy { path } { + variable _widget + variable resize + array unset widget $path,* + array unset resize $path.resize,* + Widget::destroy $path +} + +# The following proc handles the mouse click on the resize control. It stores +# the original size of the window and the initial coords of the mouse relative +# to the root. + +proc StatusBar::begin_resize {w rootx rooty} { + variable resize + set t [winfo toplevel $w] + set relx [expr {$rootx - [winfo rootx $t]}] + set rely [expr {$rooty - [winfo rooty $t]}] + set resize($w,x) $relx + set resize($w,y) $rely + set resize($w,w) [winfo width $t] + set resize($w,h) [winfo height $t] + set resize($w,winc) 1 + set resize($w,hinc) 1 + set resize($w,grid) [wm grid $t] +} + +# The following proc handles mouse motion on the resize control by asking the +# wm to adjust the size of the window. + +proc StatusBar::continue_resize {w rootx rooty} { + variable resize + if {[llength $resize($w,grid)]} { + # at this time, we don't know how to handle gridded resizing + return + } + set t [winfo toplevel $w] + set relx [expr {$rootx - [winfo rootx $t]}] + set rely [expr {$rooty - [winfo rooty $t]}] + set width [expr {$relx - $resize($w,x) + $resize($w,w)}] + set height [expr {$rely - $resize($w,y) + $resize($w,h)}] + if {$width < 0} { set width 0 } + if {$height < 0} { set height 0 } + wm geometry $t ${width}x${height} +} + +# The following proc cleans up when the user releases the mouse button. + +proc StatusBar::end_resize {w rootx rooty} { + variable resize + #continue_resize $w $rootx $rooty + #wm grid $t $resize($w,grid) + array unset resize $w,* +} diff --git a/modules/tclsci/tcl/BWidget/titleframe.tcl b/modules/tclsci/tcl/BWidget/titleframe.tcl new file mode 100755 index 000000000..d077c88af --- /dev/null +++ b/modules/tclsci/tcl/BWidget/titleframe.tcl @@ -0,0 +1,170 @@ +# ------------------------------------------------------------------------------ +# titleframe.tcl +# This file is part of Unifix BWidget Toolkit +# ------------------------------------------------------------------------------ +# Index of commands: +# - TitleFrame::create +# - TitleFrame::configure +# - TitleFrame::cget +# - TitleFrame::getframe +# - TitleFrame::_place +# ------------------------------------------------------------------------------ + +namespace eval TitleFrame { + Widget::define TitleFrame titleframe + + Widget::declare TitleFrame { + {-relief TkResource groove 0 frame} + {-borderwidth TkResource 2 0 frame} + {-font TkResource "" 0 label} + {-foreground TkResource "" 0 label} + {-state TkResource "" 0 label} + {-background TkResource "" 0 frame} + {-text String "" 0} + {-ipad Int 4 0 "%d >=0"} + {-side Enum left 0 {left center right}} + {-baseline Enum center 0 {top center bottom}} + {-fg Synonym -foreground} + {-bg Synonym -background} + {-bd Synonym -borderwidth} + } + + Widget::addmap TitleFrame "" :cmd {-background {}} + Widget::addmap TitleFrame "" .l { + -background {} -foreground {} -text {} -font {} + } + Widget::addmap TitleFrame "" .l {-state {}} + Widget::addmap TitleFrame "" .p {-background {}} + Widget::addmap TitleFrame "" .b { + -background {} -relief {} -borderwidth {} + } + Widget::addmap TitleFrame "" .b.p {-background {}} + Widget::addmap TitleFrame "" .f {-background {}} +} + + +# ------------------------------------------------------------------------------ +# Command TitleFrame::create +# ------------------------------------------------------------------------------ +proc TitleFrame::create { path args } { + Widget::init TitleFrame $path $args + + set frame [eval [list frame $path] [Widget::subcget $path :cmd] \ + -class TitleFrame -relief flat -bd 0 -highlightthickness 0] + + set padtop [eval [list frame $path.p] [Widget::subcget $path :cmd] \ + -relief flat -borderwidth 0] + set border [eval [list frame $path.b] [Widget::subcget $path .b] -highlightthickness 0] + set label [eval [list label $path.l] [Widget::subcget $path .l] \ + -highlightthickness 0 \ + -relief flat \ + -bd 0 -padx 2 -pady 0] + set padbot [eval [list frame $border.p] [Widget::subcget $path .p] \ + -relief flat -bd 0 -highlightthickness 0] + set frame [eval [list frame $path.f] [Widget::subcget $path .f] \ + -relief flat -bd 0 -highlightthickness 0] + set height [winfo reqheight $label] + + switch [Widget::getoption $path -side] { + left { set relx 0.0; set x 5; set anchor nw } + center { set relx 0.5; set x 0; set anchor n } + right { set relx 1.0; set x -5; set anchor ne } + } + set bd [Widget::getoption $path -borderwidth] + switch [Widget::getoption $path -baseline] { + top { + set y 0 + set htop $height + set hbot 1 + } + center { + set y 0 + set htop [expr {$height/2}] + set hbot [expr {$height/2+$height%2+1}] + } + bottom { + set y [expr {$bd+1}] + set htop 1 + set hbot $height + } + } + $padtop configure -height $htop + $padbot configure -height $hbot + + set pad [Widget::getoption $path -ipad] + pack $padbot -side top -fill x + pack $frame -in $border -fill both -expand yes -padx $pad -pady $pad + + pack $padtop -side top -fill x + pack $border -fill both -expand yes + + place $label -relx $relx -x $x -anchor $anchor -y $y + + bind $label <Configure> [list TitleFrame::_place $path] + bind $path <Destroy> [list Widget::destroy %W] + + return [Widget::create TitleFrame $path] +} + + +# ------------------------------------------------------------------------------ +# Command TitleFrame::configure +# ------------------------------------------------------------------------------ +proc TitleFrame::configure { path args } { + set res [Widget::configure $path $args] + + if { [Widget::hasChanged $path -ipad pad] } { + pack configure $path.f -padx $pad -pady $pad + } + if { [Widget::hasChanged $path -borderwidth val] | + [Widget::hasChanged $path -font val] | + [Widget::hasChanged $path -side val] | + [Widget::hasChanged $path -baseline val] } { + _place $path + } + + return $res +} + + +# ------------------------------------------------------------------------------ +# Command TitleFrame::cget +# ------------------------------------------------------------------------------ +proc TitleFrame::cget { path option } { + return [Widget::cget $path $option] +} + + +# ------------------------------------------------------------------------------ +# Command TitleFrame::getframe +# ------------------------------------------------------------------------------ +proc TitleFrame::getframe { path } { + return $path.f +} + + +# ------------------------------------------------------------------------------ +# Command TitleFrame::_place +# ------------------------------------------------------------------------------ +proc TitleFrame::_place { path } { + set height [winfo height $path.l] + switch [Widget::getoption $path -side] { + left { set relx 0.0; set x 10; set anchor nw } + center { set relx 0.5; set x 0; set anchor n } + right { set relx 1.0; set x -10; set anchor ne } + } + set bd [Widget::getoption $path -borderwidth] + switch [Widget::getoption $path -baseline] { + top { set htop $height; set hbot 1; set y 0 } + center { set htop [expr {$height/2}]; set hbot [expr {$height/2+$height%2+1}]; set y 0 } + bottom { set htop 1; set hbot $height; set y [expr {$bd+1}] } + } + $path.p configure -height $htop + $path.b.p configure -height $hbot + + place $path.l -relx $relx -x $x -anchor $anchor -y $y +} + + + + diff --git a/modules/tclsci/tcl/BWidget/tree.tcl b/modules/tclsci/tcl/BWidget/tree.tcl new file mode 100755 index 000000000..122bec8e4 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/tree.tcl @@ -0,0 +1,2251 @@ +# ---------------------------------------------------------------------------- +# tree.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: tree.tcl,v 1.60.2.3 2010/12/14 21:24:15 oehhar Exp $ +# ---------------------------------------------------------------------------- +# Index of commands: +# - Tree::create +# - Tree::configure +# - Tree::cget +# - Tree::insert +# - Tree::itemconfigure +# - Tree::itemcget +# - Tree::bindArea +# - Tree::bindText +# - Tree::bindImage +# - Tree::delete +# - Tree::move +# - Tree::reorder +# - Tree::selection +# - Tree::exists +# - Tree::parent +# - Tree::index +# - Tree::nodes +# - Tree::see +# - Tree::opentree +# - Tree::closetree +# - Tree::edit +# - Tree::xview +# - Tree::yview +# - Tree::_update_edit_size +# - Tree::_destroy +# - Tree::_see +# - Tree::_recexpand +# - Tree::_subdelete +# - Tree::_update_scrollregion +# - Tree::_cross_event +# - Tree::_draw_node +# - Tree::_draw_subnodes +# - Tree::_update_nodes +# - Tree::_draw_tree +# - Tree::_redraw_tree +# - Tree::_redraw_selection +# - Tree::_redraw_idle +# - Tree::_drag_cmd +# - Tree::_drop_cmd +# - Tree::_over_cmd +# - Tree::_auto_scroll +# - Tree::_scroll +# ---------------------------------------------------------------------------- + +namespace eval Tree { + Widget::define Tree tree DragSite DropSite DynamicHelp + + namespace eval Node { + Widget::declare Tree::Node { + {-text String "" 0} + {-font TkResource "" 0 listbox} + {-image TkResource "" 0 label} + {-window String "" 0} + {-fill TkResource black 0 {listbox -foreground}} + {-data String "" 0} + {-open Boolean 0 0} + {-selectable Boolean 1 0} + {-drawcross Enum auto 0 {auto always never allways}} + {-padx Int -1 0 "%d >= -1"} + {-deltax Int -1 0 "%d >= -1"} + {-anchor String "w" 0 ""} + } + } + + DynamicHelp::include Tree::Node balloon + + Widget::tkinclude Tree canvas .c \ + remove { + -insertwidth -insertbackground -insertborderwidth -insertofftime + -insertontime -selectborderwidth -closeenough -confine -scrollregion + -xscrollincrement -yscrollincrement -width -height + } \ + initialize { + -relief sunken -borderwidth 2 -takefocus 1 + -highlightthickness 1 -width 200 + } + + Widget::declare Tree { + {-deltax Int 10 0 "%d >= 0"} + {-deltay Int 15 0 "%d >= 0"} + {-padx Int 20 0 "%d >= 0"} + {-background TkResource "" 0 listbox} + {-selectbackground TkResource "" 0 listbox} + {-selectforeground TkResource "" 0 listbox} + {-selectcommand String "" 0} + {-width TkResource "" 0 listbox} + {-height TkResource "" 0 listbox} + {-selectfill Boolean 0 0} + {-showlines Boolean 1 0} + {-linesfill TkResource black 0 {listbox -foreground}} + {-linestipple TkResource "" 0 {label -bitmap}} + {-crossfill TkResource black 0 {listbox -foreground}} + {-redraw Boolean 1 0} + {-opencmd String "" 0} + {-closecmd String "" 0} + {-dropovermode Flag "wpn" 0 "wpn"} + {-bg Synonym -background} + + {-crossopenimage String "" 0} + {-crosscloseimage String "" 0} + {-crossopenbitmap String "" 0} + {-crossclosebitmap String "" 0} + } + + DragSite::include Tree "TREE_NODE" 1 + DropSite::include Tree { + TREE_NODE {copy {} move {}} + } + + Widget::addmap Tree "" .c {-deltay -yscrollincrement} + + # Trees on windows have a white (system window) background + if { $::tcl_platform(platform) == "windows" } { + option add *Tree.c.background SystemWindow widgetDefault + option add *TreeNode.fill SystemWindowText widgetDefault + } + + bind Tree <FocusIn> [list after idle {BWidget::refocus %W %W.c}] + bind Tree <Destroy> [list Tree::_destroy %W] + bind Tree <Configure> [list Tree::_update_scrollregion %W] + + + bind TreeSentinalStart <Button-1> { + if { $::Tree::sentinal(%W) } { + set ::Tree::sentinal(%W) 0 + break + } + } + + bind TreeSentinalEnd <Button-1> { + set ::Tree::sentinal(%W) 0 + } + + bind TreeFocus <Button-1> [list focus %W] + + variable _edit +} + + +# ---------------------------------------------------------------------------- +# Command Tree::create +# ---------------------------------------------------------------------------- +proc Tree::create { path args } { + variable $path + upvar 0 $path data + + Widget::init Tree $path $args + set ::Tree::sentinal($path.c) 0 + + if {[Widget::cget $path -crossopenbitmap] == ""} { + set file [file join $::BWIDGET::LIBRARY images "minus.xbm"] + Widget::configure $path [list -crossopenbitmap @$file] + } + if {[Widget::cget $path -crossclosebitmap] == ""} { + set file [file join $::BWIDGET::LIBRARY images "plus.xbm"] + Widget::configure $path [list -crossclosebitmap @$file] + } + + set data(root) {{}} + set data(selnodes) {} + set data(upd,level) 0 + set data(upd,nodes) {} + set data(upd,afterid) "" + set data(dnd,scroll) "" + set data(dnd,afterid) "" + set data(dnd,selnodes) {} + set data(dnd,node) "" + + frame $path -class Tree -bd 0 -highlightthickness 0 -relief flat \ + -takefocus 0 + # For 8.4+ we don't want to inherit the padding + catch {$path configure -padx 0 -pady 0} + eval [list canvas $path.c] [Widget::subcget $path .c] -xscrollincrement 8 + bindtags $path.c [list TreeSentinalStart TreeFocus $path.c Canvas \ + [winfo toplevel $path] all TreeSentinalEnd] + pack $path.c -expand yes -fill both + $path.c bind cross <ButtonPress-1> [list Tree::_cross_event $path] + + # Added by ericm@scriptics.com + # These allow keyboard traversal of the tree + bind $path.c <KeyPress-Up> [list Tree::_keynav up $path] + bind $path.c <KeyPress-Down> [list Tree::_keynav down $path] + bind $path.c <KeyPress-Right> [list Tree::_keynav right $path] + bind $path.c <KeyPress-Left> [list Tree::_keynav left $path] + bind $path.c <KeyPress-space> [list +Tree::_keynav space $path] + + # These allow keyboard control of the scrolling + bind $path.c <Control-KeyPress-Up> [list $path.c yview scroll -1 units] + bind $path.c <Control-KeyPress-Down> [list $path.c yview scroll 1 units] + bind $path.c <Control-KeyPress-Left> [list $path.c xview scroll -1 units] + bind $path.c <Control-KeyPress-Right> [list $path.c xview scroll 1 units] + # ericm@scriptics.com + + BWidget::bindMouseWheel $path.c + + DragSite::setdrag $path $path.c Tree::_init_drag_cmd \ + [Widget::cget $path -dragendcmd] 1 + DropSite::setdrop $path $path.c Tree::_over_cmd Tree::_drop_cmd 1 + + Widget::create Tree $path + + set w [Widget::cget $path -width] + set h [Widget::cget $path -height] + set dy [Widget::cget $path -deltay] + $path.c configure -width [expr {$w*8}] -height [expr {$h*$dy}] + + # ericm + # Bind <Button-1> to select the clicked node -- no reason not to, right? + + ## Bind button 1 to select the node via the _mouse_select command. + ## This command will generate the proper <<TreeSelect>> virtual event + ## when necessary. + set selectcmd Tree::_mouse_select + Tree::bindText $path <Button-1> [list $selectcmd $path set] + Tree::bindImage $path <Button-1> [list $selectcmd $path set] + Tree::bindText $path <Control-Button-1> [list $selectcmd $path toggle] + Tree::bindImage $path <Control-Button-1> [list $selectcmd $path toggle] + + # Add sentinal bindings for double-clicking on items, to handle the + # gnarly Tk bug wherein: + # ButtonClick + # ButtonClick + # On a canvas item translates into button click on the item, button click + # on the canvas, double-button on the item, single button click on the + # canvas (which can happen if the double-button on the item causes some + # other event to be handled in between when the button clicks are examined + # for the canvas) + $path.c bind TreeItemSentinal <Double-Button-1> \ + [list set ::Tree::sentinal($path.c) 1] + # ericm + + return $path +} + + +# ---------------------------------------------------------------------------- +# Command Tree::configure +# ---------------------------------------------------------------------------- +proc Tree::configure { path args } { + variable $path + upvar 0 $path data + + set res [Widget::configure $path $args] + + set ch1 [expr {[Widget::hasChanged $path -deltax val] | + [Widget::hasChanged $path -deltay dy] | + [Widget::hasChanged $path -padx val] | + [Widget::hasChanged $path -showlines val]}] + + set ch2 [expr {[Widget::hasChanged $path -selectbackground val] | + [Widget::hasChanged $path -selectforeground val]}] + + if { [Widget::hasChanged $path -linesfill fill] | + [Widget::hasChanged $path -linestipple stipple] } { + $path.c itemconfigure line -fill $fill -stipple $stipple + } + + if { [Widget::hasChanged $path -crossfill fill] } { + $path.c itemconfigure cross -foreground $fill + } + + if {[Widget::hasChanged $path -selectfill fill]} { + # Make sure that the full-width boxes have either all or none + # of the standard node bindings + if {$fill} { + foreach event [$path.c bind "node"] { + $path.c bind "box" $event [$path.c bind "node" $event] + } + } else { + foreach event [$path.c bind "node"] { + $path.c bind "box" $event {} + } + } + } + + if { $ch1 } { + _redraw_idle $path 3 + } elseif { $ch2 } { + _redraw_idle $path 1 + } + + if { [Widget::hasChanged $path -height h] } { + $path.c configure -height [expr {$h*$dy}] + } + if { [Widget::hasChanged $path -width w] } { + $path.c configure -width [expr {$w*8}] + } + + if { [Widget::hasChanged $path -redraw bool] && $bool } { + set upd $data(upd,level) + set data(upd,level) 0 + _redraw_idle $path $upd + } + + set force [Widget::hasChanged $path -dragendcmd dragend] + DragSite::setdrag $path $path.c Tree::_init_drag_cmd $dragend $force + DropSite::setdrop $path $path.c Tree::_over_cmd Tree::_drop_cmd + + return $res +} + + +# ---------------------------------------------------------------------------- +# Command Tree::cget +# ---------------------------------------------------------------------------- +proc Tree::cget { path option } { + return [Widget::cget $path $option] +} + + +# ---------------------------------------------------------------------------- +# Command Tree::insert +# ---------------------------------------------------------------------------- +proc Tree::insert { path index parent node args } { + variable $path + upvar 0 $path data + + set node [_node_name $path $node] + set node [Widget::nextIndex $path $node] + + if { [info exists data($node)] } { + return -code error "node \"$node\" already exists" + } + set parent [_node_name $path $parent] + if { ![info exists data($parent)] } { + return -code error "node \"$parent\" does not exist" + } + + Widget::init Tree::Node $path.$node $args + if {[string equal $index "end"]} { + lappend data($parent) $node + } else { + incr index + set data($parent) [linsert $data($parent) $index $node] + } + set data($node) [list $parent] + + if { [string equal $parent "root"] } { + _redraw_idle $path 3 + } elseif { [visible $path $parent] } { + # parent is visible... + if { [Widget::getMegawidgetOption $path.$parent -open] } { + # ...and opened -> redraw whole + _redraw_idle $path 3 + } else { + # ...and closed -> redraw cross + MergeFlag $path $parent 8 + _redraw_idle $path 2 + } + } + + return $node +} + + +# ---------------------------------------------------------------------------- +# Command Tree::itemconfigure +# ---------------------------------------------------------------------------- +proc Tree::itemconfigure { path node args } { + variable $path + upvar 0 $path data + + set node [_node_name $path $node] + if { [string equal $node "root"] || ![info exists data($node)] } { + return -code error "node \"$node\" does not exist" + } + + set result [Widget::configure $path.$node $args] + + _set_help $path $node + + if { [visible $path $node] } { + set lopt {} + set flag 0 + foreach opt {-window -image -drawcross -font -text -fill} { + set flag [expr {$flag << 1}] + if { [Widget::hasChanged $path.$node $opt val] } { + set flag [expr {$flag | 1}] + } + } + + if { [Widget::hasChanged $path.$node -open val] } { + if {[llength $data($node)] > 1} { + # node have subnodes - full redraw + _redraw_idle $path 3 + } else { + # force a redraw of the plus/minus sign + set flag [expr {$flag | 8}] + } + } + + if {$data(upd,level) < 3 && [Widget::hasChanged $path.$node -padx x]} { + _redraw_idle $path 3 + } + + if { $data(upd,level) < 3 && $flag } { + MergeFlag $path $node $flag + _redraw_idle $path 2 + } + } + return $result +} + +proc Tree::MergeFlag { path node flag } { + variable $path + upvar 0 $path data + + # data(upd,nodes) is a key-val list: emulate a dict by an array + array set n $data(upd,nodes) + if {![info exists n($node)]} { + lappend data(upd,nodes) $node $flag + } else { + set n($node) [expr {$n($node) | $flag}] + set data(upd,nodes) [array get n] + } + return +} + +# ---------------------------------------------------------------------------- +# Command Tree::itemcget +# ---------------------------------------------------------------------------- +proc Tree::itemcget { path node option } { + # Instead of upvar'ing $path as data for this test, just directly refer to + # it, as that is faster. + set node [_node_name $path $node] + if { [string equal $node "root"] || \ + ![info exists ::Tree::${path}($node)] } { + return -code error "node \"$node\" does not exist" + } + + return [Widget::cget $path.$node $option] +} + +# ---------------------------------------------------------------------------- +# Command Tree::bindArea +# ---------------------------------------------------------------------------- +proc Tree::bindArea { path event script } { + bind $path.c $event $script +} + +# ---------------------------------------------------------------------------- +# Command Tree::bindText +# ---------------------------------------------------------------------------- +proc Tree::bindText { path event script } { + if {[string length $script]} { + append script " \[Tree::_get_node_name [list $path] current 2 1\]" + } + $path.c bind "node" $event $script + if {[Widget::getoption $path -selectfill]} { + $path.c bind "box" $event $script + } else { + $path.c bind "box" $event {} + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::bindImage +# ---------------------------------------------------------------------------- +proc Tree::bindImage { path event script } { + if {[string length $script]} { + append script " \[Tree::_get_node_name [list $path] current 2 1\]" + } + $path.c bind "img" $event $script + if {[Widget::getoption $path -selectfill]} { + $path.c bind "box" $event $script + } else { + $path.c bind "box" $event {} + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::delete +# ---------------------------------------------------------------------------- +proc Tree::delete { path args } { + variable $path + upvar 0 $path data + + set sel 0 + foreach lnodes $args { + foreach node $lnodes { + set node [_node_name $path $node] + if { ![string equal $node "root"] && [info exists data($node)] } { + set parent [lindex $data($node) 0] + set idx [lsearch -exact $data($parent) $node] + set data($parent) [lreplace $data($parent) $idx $idx] + incr sel [_subdelete $path [list $node]] + } + } + } + if {$sel} { + # if selection changed, call the selectcommand + __call_selectcmd $path + } + + _redraw_idle $path 3 +} + + +# ---------------------------------------------------------------------------- +# Command Tree::move +# ---------------------------------------------------------------------------- +proc Tree::move { path parent node index } { + variable $path + upvar 0 $path data + + set node [_node_name $path $node] + if { [string equal $node "root"] || ![info exists data($node)] } { + return -code error "node \"$node\" does not exist" + } + if { ![info exists data($parent)] } { + return -code error "node \"$parent\" does not exist" + } + set p $parent + while { ![string equal $p "root"] } { + if { [string equal $p $node] } { + return -code error "node \"$parent\" is a descendant of \"$node\"" + } + set p [parent $path $p] + } + + set oldp [lindex $data($node) 0] + set idx [lsearch -exact $data($oldp) $node] + set data($oldp) [lreplace $data($oldp) $idx $idx] + set data($node) [concat [list $parent] [lrange $data($node) 1 end]] + if { [string equal $index "end"] } { + lappend data($parent) $node + } else { + incr index + set data($parent) [linsert $data($parent) $index $node] + } + if { ([string equal $oldp "root"] || + ([visible $path $oldp] && [Widget::getoption $path.$oldp -open])) || + ([string equal $parent "root"] || + ([visible $path $parent] && [Widget::getoption $path.$parent -open])) } { + _redraw_idle $path 3 + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::reorder +# ---------------------------------------------------------------------------- +proc Tree::reorder { path node neworder } { + variable $path + upvar 0 $path data + + set node [_node_name $path $node] + if { ![info exists data($node)] } { + return -code error "node \"$node\" does not exist" + } + set children [lrange $data($node) 1 end] + if { [llength $children] } { + set children [BWidget::lreorder $children $neworder] + set data($node) [linsert $children 0 [lindex $data($node) 0]] + if { [visible $path $node] && [Widget::getoption $path.$node -open] } { + _redraw_idle $path 3 + } + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::selection +# ---------------------------------------------------------------------------- +proc Tree::selection { path cmd args } { + variable $path + upvar 0 $path data + + switch -- $cmd { + toggle { + foreach node $args { + set node [_node_name $path $node] + if {![info exists data($node)]} { + return -code error \ + "$path selection toggle: Cannot toggle unknown node \"$node\"." + } + } + foreach node $args { + set node [_node_name $path $node] + if {[$path selection includes $node]} { + $path selection remove $node + } else { + $path selection add $node + } + } + } + set { + foreach node $args { + set node [_node_name $path $node] + if {![info exists data($node)]} { + return -code error \ + "$path selection set: Cannot select unknown node \"$node\"." + } + } + set data(selnodes) {} + foreach node $args { + set node [_node_name $path $node] + if { [Widget::getoption $path.$node -selectable] } { + if { [lsearch -exact $data(selnodes) $node] == -1 } { + lappend data(selnodes) $node + } + } + } + __call_selectcmd $path + } + add { + foreach node $args { + set node [_node_name $path $node] + if {![info exists data($node)]} { + return -code error \ + "$path selection add: Cannot select unknown node \"$node\"." + } + } + foreach node $args { + set node [_node_name $path $node] + if { [Widget::getoption $path.$node -selectable] } { + if { [lsearch -exact $data(selnodes) $node] == -1 } { + lappend data(selnodes) $node + } + } + } + __call_selectcmd $path + } + range { + # Here's our algorithm: + # make a list of all nodes, then take the range from node1 + # to node2 and select those nodes + # + # This works because of how this widget handles redraws: + # The tree is always completely redrawn, and always from + # top to bottom. So the list of visible nodes *is* the + # list of nodes, and we can use that to decide which nodes + # to select. + + if {[llength $args] != 2} { + return -code error \ + "wrong#args: Expected $path selection range node1 node2" + } + + foreach {node1 node2} $args break + + set node1 [_node_name $path $node1] + set node2 [_node_name $path $node2] + if {![info exists data($node1)]} { + return -code error \ + "$path selection range: Cannot start range at unknown node \"$node1\"." + } + if {![info exists data($node2)]} { + return -code error \ + "$path selection range: Cannot end range at unknown node \"$node2\"." + } + + set nodes {} + foreach nodeItem [$path.c find withtag node] { + set node [Tree::_get_node_name $path $nodeItem 2] + if { [Widget::getoption $path.$node -selectable] } { + lappend nodes $node + } + } + # surles: Set the root string to the first element on the list. + if {$node1 == "root"} { + set node1 [lindex $nodes 0] + } + if {$node2 == "root"} { + set node2 [lindex $nodes 0] + } + + # Find the first visible ancestor of node1, starting with node1 + while {[set index1 [lsearch -exact $nodes $node1]] == -1} { + set node1 [lindex $data($node1) 0] + } + # Find the first visible ancestor of node2, starting with node2 + while {[set index2 [lsearch -exact $nodes $node2]] == -1} { + set node2 [lindex $data($node2) 0] + } + # If the nodes were given in backwards order, flip the + # indices now + if { $index2 < $index1 } { + incr index1 $index2 + set index2 [expr {$index1 - $index2}] + set index1 [expr {$index1 - $index2}] + } + set data(selnodes) [lrange $nodes $index1 $index2] + __call_selectcmd $path + } + remove { + foreach node $args { + set node [_node_name $path $node] + if { [set idx [lsearch -exact $data(selnodes) $node]] != -1 } { + set data(selnodes) [lreplace $data(selnodes) $idx $idx] + } + } + __call_selectcmd $path + } + clear { + if {[llength $args] != 0} { + return -code error \ + "wrong#args: Expected $path selection clear" + } + set data(selnodes) {} + __call_selectcmd $path + } + get { + if {[llength $args] != 0} { + return -code error \ + "wrong#args: Expected $path selection get" + } + set nodes [list] + foreach node $data(selnodes) { + lappend nodes [_node_name_rev $path $node] + } + return $nodes + } + includes { + if {[llength $args] != 1} { + return -code error \ + "wrong#args: Expected $path selection includes node" + } + set node [lindex $args 0] + set node [_node_name $path $node] + return [expr {[lsearch -exact $data(selnodes) $node] != -1}] + } + default { + return + } + } + _redraw_idle $path 1 +} + + +proc Tree::getcanvas { path } { + return $path.c +} + + +proc Tree::__call_selectcmd { path } { + variable $path + upvar 0 $path data + + set selectcmd [Widget::getoption $path -selectcommand] + if {[llength $selectcmd]} { + lappend selectcmd $path + lappend selectcmd $data(selnodes) + uplevel \#0 $selectcmd + } + return +} + +# ---------------------------------------------------------------------------- +# Command Tree::exists +# ---------------------------------------------------------------------------- +proc Tree::exists { path node } { + variable $path + upvar 0 $path data + + set node [_node_name $path $node] + return [info exists data($node)] +} + + +# ---------------------------------------------------------------------------- +# Command Tree::visible +# ---------------------------------------------------------------------------- +proc Tree::visible { path node } { + set node [_node_name $path $node] + set idn [$path.c find withtag n:$node] + return [llength $idn] +} + + +# ---------------------------------------------------------------------------- +# Command Tree::parent +# ---------------------------------------------------------------------------- +proc Tree::parent { path node } { + variable $path + upvar 0 $path data + + set node [_node_name $path $node] + if { ![info exists data($node)] } { + return -code error "node \"$node\" does not exist" + } + return [lindex $data($node) 0] +} + + +# ---------------------------------------------------------------------------- +# Command Tree::index +# ---------------------------------------------------------------------------- +proc Tree::index { path node } { + variable $path + upvar 0 $path data + + set node [_node_name $path $node] + if { [string equal $node "root"] || ![info exists data($node)] } { + return -code error "node \"$node\" does not exist" + } + set parent [lindex $data($node) 0] + return [expr {[lsearch -exact $data($parent) $node] - 1}] +} + + +# ---------------------------------------------------------------------------- +# Tree::find +# Returns the node given a position. +# findInfo @x,y ?confine? +# lineNumber +# ---------------------------------------------------------------------------- +proc Tree::find {path findInfo {confine ""}} { + if {[regexp -- {^@([0-9]+),([0-9]+)$} $findInfo match x y]} { + set x [$path.c canvasx $x] + set y [$path.c canvasy $y] + } elseif {[regexp -- {^[0-9]+$} $findInfo lineNumber]} { + set dy [Widget::getoption $path -deltay] + set y [expr {$dy*($lineNumber+0.5)}] + set confine "" + } else { + return -code error "invalid find spec \"$findInfo\"" + } + + set found 0 + set region [$path.c bbox all] + if {[llength $region]} { + set xi [lindex $region 0] + set xs [lindex $region 2] + foreach id [$path.c find overlapping $xi $y $xs $y] { + set ltags [$path.c gettags $id] + set item [lindex $ltags 1] + if { [string equal $item "node"] || + [string equal $item "img"] || + [string equal $item "win"] } { + # item is the label or image/window of the node + set node [Tree::_get_node_name $path $id 2] + set found 1 + break + } + } + } + + if {$found} { + if {![string equal $confine ""]} { + # test if x stand inside node bbox + set padx [_get_node_padx $path $node] + set xi [expr {[lindex [$path.c coords n:$node] 0] - $padx}] + set xs [lindex [$path.c bbox n:$node] 2] + if {$x >= $xi && $x <= $xs} { + return [_node_name_rev $path $node] + } + } else { + return [_node_name_rev $path $node] + } + } + return "" +} + + +# ---------------------------------------------------------------------------- +# Command Tree::line +# Returns the line where a node was drawn. +# ---------------------------------------------------------------------------- +proc Tree::line {path node} { + set node [_node_name $path $node] + set item [$path.c find withtag n:$node] + if {[string length $item]} { + set dy [Widget::getoption $path -deltay] + set y [lindex [$path.c coords $item] 1] + set line [expr {int($y/$dy)}] + } else { + set line -1 + } + return $line +} + + +# ---------------------------------------------------------------------------- +# Command Tree::nodes +# ---------------------------------------------------------------------------- +proc Tree::nodes { path node {first ""} {last ""} } { + variable $path + upvar 0 $path data + + set node [_node_name $path $node] + if { ![info exists data($node)] } { + return -code error "node \"$node\" does not exist" + } + + if { ![string length $first] } { + return [lrange $data($node) 1 end] + } + + if { ![string length $last] } { + return [lindex [lrange $data($node) 1 end] $first] + } else { + return [lrange [lrange $data($node) 1 end] $first $last] + } +} + + +# Tree::visiblenodes -- +# +# Retrieve a list of all the nodes in a tree. +# +# Arguments: +# path tree to retrieve nodes for. +# +# Results: +# nodes list of nodes in the tree. + +proc Tree::visiblenodes { path } { + variable $path + upvar 0 $path data + + # Root is always open (?), so all of its children automatically get added + # to the result, and to the stack. + set st [lrange $data(root) 1 end] + set result $st + + while {[llength $st]} { + set node [lindex $st end] + set st [lreplace $st end end] + # Danger, danger! Using getMegawidgetOption is fragile, but much + # much faster than going through cget. + if { [Widget::getMegawidgetOption $path.$node -open] } { + set nodes [lrange $data($node) 1 end] + set result [concat $result $nodes] + set st [concat $st $nodes] + } + } + return $result +} + +# ---------------------------------------------------------------------------- +# Command Tree::see +# ---------------------------------------------------------------------------- +proc Tree::see { path node } { + variable $path + upvar 0 $path data + + set node [_node_name $path $node] + if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } { + after cancel $data(upd,afterid) + _redraw_tree $path + } + set idn [$path.c find withtag n:$node] + if { $idn != "" } { + Tree::_see $path $idn + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::opentree +# ---------------------------------------------------------------------------- +# JDC: added option recursive +proc Tree::opentree { path node {recursive 1} } { + variable $path + upvar 0 $path data + + set node [_node_name $path $node] + if { [string equal $node "root"] || ![info exists data($node)] } { + return -code error "node \"$node\" does not exist" + } + + _recexpand $path $node 1 $recursive [Widget::getoption $path -opencmd] + _redraw_idle $path 3 +} + + +# ---------------------------------------------------------------------------- +# Command Tree::closetree +# ---------------------------------------------------------------------------- +proc Tree::closetree { path node {recursive 1} } { + variable $path + upvar 0 $path data + + set node [_node_name $path $node] + if { [string equal $node "root"] || ![info exists data($node)] } { + return -code error "node \"$node\" does not exist" + } + + _recexpand $path $node 0 $recursive [Widget::getoption $path -closecmd] + _redraw_idle $path 3 +} + + +proc Tree::toggle { path node } { + if {[$path itemcget $node -open]} { + $path closetree $node 0 + } else { + $path opentree $node 0 + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::edit +# ---------------------------------------------------------------------------- +proc Tree::edit { path node text {verifycmd ""} {clickres 0} {select 1}} { + variable _edit + variable $path + upvar 0 $path data + + set node [_node_name $path $node] + if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } { + after cancel $data(upd,afterid) + _redraw_tree $path + } + set idn [$path.c find withtag n:$node] + if { $idn != "" } { + Tree::_see $path $idn + + set oldfg [$path.c itemcget $idn -fill] + set sbg [Widget::getoption $path -selectbackground] + set coords [$path.c coords $idn] + set x [lindex $coords 0] + set y [lindex $coords 1] + set bd [expr {[$path.c cget -borderwidth]+[$path.c cget -highlightthickness]}] + set w [expr {[winfo width $path] - 2*$bd}] + set wmax [expr {[$path.c canvasx $w]-$x}] + + set _edit(text) $text + set _edit(wait) 0 + + $path.c itemconfigure $idn -fill [Widget::getoption $path -background] + $path.c itemconfigure s:$node -fill {} -outline {} + + set frame [frame $path.edit \ + -relief flat -borderwidth 0 -highlightthickness 0 \ + -background [Widget::getoption $path -background]] + set ent [entry $frame.edit \ + -width 0 \ + -relief solid \ + -borderwidth 1 \ + -highlightthickness 0 \ + -foreground [Widget::getoption $path.$node -fill] \ + -background [Widget::getoption $path -background] \ + -selectforeground [Widget::getoption $path -selectforeground] \ + -selectbackground $sbg \ + -font [Widget::getoption $path.$node -font] \ + -textvariable Tree::_edit(text)] + pack $ent -ipadx 8 -anchor w + + set idw [$path.c create window $x $y -window $frame -anchor w] + trace variable Tree::_edit(text) w \ + [list Tree::_update_edit_size $path $ent $idw $wmax] + tkwait visibility $ent + grab $frame + BWidget::focus set $ent + + _update_edit_size $path $ent $idw $wmax + update + if { $select } { + $ent selection range 0 end + $ent icursor end + $ent xview end + } + + bindtags $ent [list $ent Entry] + bind $ent <Escape> {set Tree::_edit(wait) 0} + bind $ent <Return> {set Tree::_edit(wait) 1} + if { $clickres == 0 || $clickres == 1 } { + bind $frame <Button> [list set Tree::_edit(wait) $clickres] + } + + set ok 0 + while { !$ok } { + tkwait variable Tree::_edit(wait) + if { !$_edit(wait) || [llength $verifycmd]==0 || + [uplevel \#0 $verifycmd [list $_edit(text)]] } { + set ok 1 + } + } + + trace vdelete Tree::_edit(text) w \ + [list Tree::_update_edit_size $path $ent $idw $wmax] + grab release $frame + BWidget::focus release $ent + destroy $frame + $path.c delete $idw + $path.c itemconfigure $idn -fill $oldfg + $path.c itemconfigure s:$node -fill $sbg -outline $sbg + + if { $_edit(wait) } { + return $_edit(text) + } + } + return "" +} + + +# ---------------------------------------------------------------------------- +# Command Tree::xview +# ---------------------------------------------------------------------------- +proc Tree::xview { path args } { + return [eval [linsert $args 0 $path.c xview]] +} + + +# ---------------------------------------------------------------------------- +# Command Tree::yview +# ---------------------------------------------------------------------------- +proc Tree::yview { path args } { + return [eval [linsert $args 0 $path.c yview]] +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_update_edit_size +# ---------------------------------------------------------------------------- +proc Tree::_update_edit_size { path entry idw wmax args } { + set entw [winfo reqwidth $entry] + if { $entw+8 >= $wmax } { + $path.c itemconfigure $idw -width $wmax + } else { + $path.c itemconfigure $idw -width 0 + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_see +# ---------------------------------------------------------------------------- +proc Tree::_see { path idn } { + set bbox [$path.c bbox $idn] + set scrl [$path.c cget -scrollregion] + + set ymax [lindex $scrl 3] + set dy [$path.c cget -yscrollincrement] + set yv [$path yview] + set yv0 [expr {round([lindex $yv 0]*$ymax/$dy)}] + set yv1 [expr {round([lindex $yv 1]*$ymax/$dy)}] + set y [expr {int([lindex [$path.c coords $idn] 1]/$dy)}] + if { $y < $yv0 } { + $path.c yview scroll [expr {$y-$yv0}] units + } elseif { $y >= $yv1 } { + $path.c yview scroll [expr {$y-$yv1+1}] units + } + + set xmax [lindex $scrl 2] + set dx [$path.c cget -xscrollincrement] + set xv [$path xview] + set x0 [expr {int([lindex $bbox 0]/$dx)}] + set xv0 [expr {round([lindex $xv 0]*$xmax/$dx)}] + set xv1 [expr {round([lindex $xv 1]*$xmax/$dx)}] + if { $x0 >= $xv1 || $x0 < $xv0 } { + $path.c xview scroll [expr {$x0-$xv0}] units + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_recexpand +# ---------------------------------------------------------------------------- +# JDC : added option recursive +proc Tree::_recexpand { path node expand recursive cmd } { + variable $path + upvar 0 $path data + + if { [Widget::getoption $path.$node -open] != $expand } { + Widget::setoption $path.$node -open $expand + if {[llength $cmd]} { + uplevel \#0 $cmd [list $node] + } + } + + if { $recursive } { + foreach subnode [lrange $data($node) 1 end] { + _recexpand $path $subnode $expand $recursive $cmd + } + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_subdelete +# ---------------------------------------------------------------------------- +proc Tree::_subdelete { path lnodes } { + variable $path + upvar 0 $path data + + set sel $data(selnodes) + set selchanged 0 + + while { [llength $lnodes] } { + set lsubnodes [list] + foreach node $lnodes { + foreach subnode [lrange $data($node) 1 end] { + lappend lsubnodes $subnode + } + unset data($node) + set idx [lsearch -exact $sel $node] + if { $idx >= 0 } { + set sel [lreplace $sel $idx $idx] + incr selchanged + } + if { [set win [Widget::getoption $path.$node -window]] != "" } { + destroy $win + } + Widget::destroy $path.$node + } + set lnodes $lsubnodes + } + + set data(selnodes) $sel + # return number of sel items changes + return $selchanged +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_update_scrollregion +# ---------------------------------------------------------------------------- +proc Tree::_update_scrollregion { path } { + set bd [expr {2*([$path.c cget -borderwidth]+[$path.c cget -highlightthickness])}] + set w [expr {[winfo width $path] - $bd}] + set h [expr {[winfo height $path] - $bd}] + set xinc [$path.c cget -xscrollincrement] + set yinc [$path.c cget -yscrollincrement] + set bbox [$path.c bbox node] + if { [llength $bbox] } { + set xs [lindex $bbox 2] + set ys [lindex $bbox 3] + + if { $w < $xs } { + set w [expr {int($xs)}] + if { [set r [expr {$w % $xinc}]] } { + set w [expr {$w+$xinc-$r}] + } + } + if { $h < $ys } { + set h [expr {int($ys)}] + if { [set r [expr {$h % $yinc}]] } { + set h [expr {$h+$yinc-$r}] + } + } + } + + $path.c configure -scrollregion [list 0 0 $w $h] + + if {[Widget::getoption $path -selectfill]} { + _redraw_selection $path + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_cross_event +# ---------------------------------------------------------------------------- +proc Tree::_cross_event { path } { + variable $path + upvar 0 $path data + + set node [Tree::_get_node_name $path current 1] + if { [Widget::getoption $path.$node -open] } { + Tree::itemconfigure $path $node -open 0 + if {[llength [set cmd [Widget::getoption $path -closecmd]]]} { + uplevel \#0 $cmd [list $node] + } + } else { + Tree::itemconfigure $path $node -open 1 + if {[llength [set cmd [Widget::getoption $path -opencmd]]]} { + uplevel \#0 $cmd [list $node] + } + } +} + + +proc Tree::_draw_cross { path node open x y } { + set idc [$path.c find withtag c:$node] + + if { $open } { + set img [Widget::cget $path -crossopenimage] + set bmp [Widget::cget $path -crossopenbitmap] + } else { + set img [Widget::cget $path -crosscloseimage] + set bmp [Widget::cget $path -crossclosebitmap] + } + + ## If we already have a cross for this node, we just adjust the image. + if {$idc != ""} { + if {$img == ""} { + $path.c itemconfigure $idc -bitmap $bmp + } else { + $path.c itemconfigure $idc -image $img + } + return + } + + ## Create a new image for the cross. If the user has specified an + ## image, it overrides a bitmap. + if {$img == ""} { + $path.c create bitmap $x $y \ + -bitmap $bmp \ + -background [$path.c cget -background] \ + -foreground [Widget::getoption $path -crossfill] \ + -tags [list cross c:$node] -anchor c + } else { + $path.c create image $x $y \ + -image $img \ + -tags [list cross c:$node] -anchor c + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_draw_node +# ---------------------------------------------------------------------------- +proc Tree::_draw_node { path node x0 y0 deltax deltay padx showlines } { + variable $path + upvar 0 $path data + + set x1 [expr {$x0+$deltax+5}] + set y1 $y0 + if { $showlines } { + $path.c create line $x0 $y0 $x1 $y0 \ + -fill [Widget::getoption $path -linesfill] \ + -stipple [Widget::getoption $path -linestipple] \ + -tags line + } + $path.c create text [expr {$x1+$padx}] $y0 \ + -text [Widget::getoption $path.$node -text] \ + -fill [Widget::getoption $path.$node -fill] \ + -font [Widget::getoption $path.$node -font] \ + -anchor w \ + -tags [Tree::_get_node_tags $path $node [list node n:$node]] + set len [expr {[llength $data($node)] > 1}] + set dc [Widget::getoption $path.$node -drawcross] + set exp [Widget::getoption $path.$node -open] + + if { $len && $exp } { + set y1 [_draw_subnodes $path [lrange $data($node) 1 end] \ + [expr {$x0+$deltax}] $y0 $deltax $deltay $padx $showlines] + } + + if {![string equal $dc "never"] + && ($len || [string equal $dc "always"] || [string equal $dc "allways"])} { + _draw_cross $path $node $exp $x0 $y0 + } + + if { [set win [Widget::getoption $path.$node -window]] != "" } { + set a [Widget::cget $path.$node -anchor] + $path.c create window $x1 $y0 -window $win -anchor $a \ + -tags [Tree::_get_node_tags $path $node [list win i:$node]] + } elseif { [set img [Widget::getoption $path.$node -image]] != "" } { + set a [Widget::cget $path.$node -anchor] + $path.c create image $x1 $y0 -image $img -anchor $a \ + -tags [Tree::_get_node_tags $path $node [list img i:$node]] + } + set box [$path.c bbox n:$node i:$node] + set id [$path.c create rect 0 [lindex $box 1] \ + [winfo screenwidth $path] [lindex $box 3] \ + -tags [Tree::_get_node_tags $path $node [list box b:$node]] \ + -fill {} -outline {}] + $path.c lower $id + + _set_help $path $node + + return $y1 +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_draw_subnodes +# ---------------------------------------------------------------------------- +proc Tree::_draw_subnodes { path nodes x0 y0 deltax deltay padx showlines } { + set y1 $y0 + foreach node $nodes { + set padx [_get_node_padx $path $node] + set deltax [_get_node_deltax $path $node] + set yp $y1 + set y1 [_draw_node $path $node $x0 [expr {$y1+$deltay}] $deltax $deltay $padx $showlines] + } + # Only draw a line to the invisible root node above the tree widget when + # there are multiple top nodes. + set len [llength $nodes] + if { $showlines && $len && !($y0 < 0 && $len < 2) } { + set id [$path.c create line $x0 $y0 $x0 [expr {$yp+$deltay}] \ + -fill [Widget::getoption $path -linesfill] \ + -stipple [Widget::getoption $path -linestipple] \ + -tags line] + + $path.c lower $id + } + return $y1 +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_update_nodes +# ---------------------------------------------------------------------------- +proc Tree::_update_nodes { path } { + variable $path + upvar 0 $path data + + foreach {node flag} $data(upd,nodes) { + set idn [$path.c find withtag "n:$node"] + if { $idn == "" } { + continue + } + set padx [_get_node_padx $path $node] + set deltax [_get_node_deltax $path $node] + set c [$path.c coords $idn] + set x1 [expr {[lindex $c 0]-$padx}] + set x0 [expr {$x1-$deltax-5}] + set y0 [lindex $c 1] + if { $flag & 48 } { + # -window or -image modified + set win [Widget::getoption $path.$node -window] + set img [Widget::getoption $path.$node -image] + set anc [Widget::cget $path.$node -anchor] + set idi [$path.c find withtag i:$node] + set type [lindex [$path.c gettags $idi] 1] + if { [string length $win] } { + if { [string equal $type "win"] } { + $path.c itemconfigure $idi -window $win + } else { + $path.c delete $idi + $path.c create window $x1 $y0 -window $win -anchor $anc \ + -tags [_get_node_tags $path $node [list win i:$node]] + } + } elseif { [string length $img] } { + if { [string equal $type "img"] } { + $path.c itemconfigure $idi -image $img + } else { + $path.c delete $idi + $path.c create image $x1 $y0 -image $img -anchor $anc \ + -tags [_get_node_tags $path $node [list img i:$node]] + } + } else { + $path.c delete $idi + } + } + + if { $flag & 8 } { + # -drawcross modified + set len [expr {[llength $data($node)] > 1}] + set dc [Widget::getoption $path.$node -drawcross] + set exp [Widget::getoption $path.$node -open] + + if {![string equal $dc "never"] + && ($len || [string equal $dc "always"] || [string equal $dc "allways"])} { + _draw_cross $path $node $exp $x0 $y0 + } else { + set idc [$path.c find withtag c:$node] + $path.c delete $idc + } + } + + if { $flag & 7 } { + # -font, -text or -fill modified + $path.c itemconfigure $idn \ + -text [Widget::getoption $path.$node -text] \ + -fill [Widget::getoption $path.$node -fill] \ + -font [Widget::getoption $path.$node -font] + } + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_draw_tree +# ---------------------------------------------------------------------------- +proc Tree::_draw_tree { path } { + variable $path + upvar 0 $path data + + $path.c delete all + set cursor [$path.c cget -cursor] + $path.c configure -cursor watch + _draw_subnodes $path [lrange $data(root) 1 end] 8 \ + [expr {-[Widget::getoption $path -deltay]/2}] \ + [Widget::getoption $path -deltax] \ + [Widget::getoption $path -deltay] \ + [Widget::getoption $path -padx] \ + [Widget::getoption $path -showlines] + $path.c configure -cursor $cursor +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_redraw_tree +# ---------------------------------------------------------------------------- +proc Tree::_redraw_tree { path } { + variable $path + upvar 0 $path data + + if { [Widget::getoption $path -redraw] } { + if { $data(upd,level) == 2 } { + _update_nodes $path + } elseif { $data(upd,level) == 3 } { + _draw_tree $path + } + _redraw_selection $path + _update_scrollregion $path + set data(upd,nodes) {} + set data(upd,level) 0 + set data(upd,afterid) "" + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_redraw_selection +# ---------------------------------------------------------------------------- +proc Tree::_redraw_selection { path } { + variable $path + upvar 0 $path data + + set selbg [Widget::getoption $path -selectbackground] + set selfg [Widget::getoption $path -selectforeground] + set fill [Widget::getoption $path -selectfill] + if {$fill} { + set scroll [$path.c cget -scrollregion] + if {[llength $scroll]} { + set xmax [expr {[lindex $scroll 2]-1}] + } else { + set xmax [winfo width $path] + } + } + foreach id [$path.c find withtag sel] { + set node [Tree::_get_node_name $path $id 1] + $path.c itemconfigure "n:$node" -fill [Widget::getoption $path.$node -fill] + } + $path.c delete sel + foreach node $data(selnodes) { + set bbox [$path.c bbox "n:$node"] + if { [llength $bbox] } { + if {$fill} { + # get the image to (if any), as it may have different height + set bbox [$path.c bbox "n:$node" "i:$node"] + set bbox [list 0 [lindex $bbox 1] $xmax [lindex $bbox 3]] + } + set id [$path.c create rectangle $bbox -tags [list sel s:$node] \ + -fill $selbg -outline $selbg] + if {$selfg != ""} { + # Don't allow an empty fill - that would be transparent + $path.c itemconfigure "n:$node" -fill $selfg + } + $path.c lower $id + } + } +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_redraw_idle +# ---------------------------------------------------------------------------- +proc Tree::_redraw_idle { path level } { + variable $path + upvar 0 $path data + + if { [Widget::getoption $path -redraw] && $data(upd,afterid) == "" } { + set data(upd,afterid) [after idle [list Tree::_redraw_tree $path]] + } + if { $level > $data(upd,level) } { + set data(upd,level) $level + } + return "" +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_init_drag_cmd +# ---------------------------------------------------------------------------- +proc Tree::_init_drag_cmd { path X Y top } { + set path [winfo parent $path] + set ltags [$path.c gettags current] + set item [lindex $ltags 1] + if { [string equal $item "node"] || + [string equal $item "img"] || + [string equal $item "win"] } { + set node [Tree::_get_node_name $path current 2] + if {[llength [set cmd [Widget::getoption $path -draginitcmd]]]} { + return [uplevel \#0 $cmd [list $path $node $top]] + } + if { [set type [Widget::getoption $path -dragtype]] == "" } { + set type "TREE_NODE" + } + if { [set img [Widget::getoption $path.$node -image]] != "" } { + pack [label $top.l -image $img -padx 0 -pady 0] + } + return [list $type {copy move link} $node] + } + return {} +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_drop_cmd +# ---------------------------------------------------------------------------- +proc Tree::_drop_cmd { path source X Y op type dnddata } { + set path [winfo parent $path] + variable $path + upvar 0 $path data + + $path.c delete drop + if { [string length $data(dnd,afterid)] } { + after cancel $data(dnd,afterid) + set data(dnd,afterid) "" + } + set data(dnd,scroll) "" + if {[llength [set cmd [Widget::getoption $path -dropcmd]]]} { + return [uplevel \#0 $cmd \ + [list $path $source $data(dnd,node) $op $type $dnddata]] + } + return 0 +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_over_cmd +# ---------------------------------------------------------------------------- +proc Tree::_over_cmd { path source event X Y op type dnddata } { + set path [winfo parent $path] + variable $path + upvar 0 $path data + + if { [string equal $event "leave"] } { + # we leave the window tree + $path.c delete drop + if { [string length $data(dnd,afterid)] } { + after cancel $data(dnd,afterid) + set data(dnd,afterid) "" + } + set data(dnd,scroll) "" + return 0 + } + + if { [string equal $event "enter"] } { + # we enter the window tree - dnd data initialization + set mode [Widget::getoption $path -dropovermode] + set data(dnd,mode) 0 + foreach c {w p n} { + set data(dnd,mode) [expr {($data(dnd,mode) << 1) | ([string first $c $mode] != -1)}] + } + set bbox [$path.c bbox all] + if { [llength $bbox] } { + set data(dnd,xs) [lindex $bbox 2] + set data(dnd,empty) 0 + } else { + set data(dnd,xs) 0 + set data(dnd,empty) 1 + } + set data(dnd,node) {} + } + + set x [expr {$X-[winfo rootx $path]}] + set y [expr {$Y-[winfo rooty $path]}] + $path.c delete drop + set data(dnd,node) {} + + # test for auto-scroll unless mode is widget only + if { $data(dnd,mode) != 4 && [_auto_scroll $path $x $y] != "" } { + return 2 + } + + if { $data(dnd,mode) & 4 } { + # dropovermode includes widget + set target [list widget] + set vmode 4 + } else { + set target [list ""] + set vmode 0 + } + if { ($data(dnd,mode) & 2) && $data(dnd,empty) } { + # dropovermode includes position and tree is empty + lappend target [list root 0] + set vmode [expr {$vmode | 2}] + } + + set xc [$path.c canvasx $x] + set xs $data(dnd,xs) + if { $xc <= $xs } { + set yc [$path.c canvasy $y] + set dy [$path.c cget -yscrollincrement] + set line [expr {int($yc/$dy)}] + set xi 0 + set yi [expr {$line*$dy}] + set ys [expr {$yi+$dy}] + set found 0 + foreach id [$path.c find overlapping $xi $yi $xs $ys] { + set ltags [$path.c gettags $id] + set item [lindex $ltags 1] + if { [string equal $item "node"] || + [string equal $item "img"] || + [string equal $item "win"] } { + # item is the label or image/window of the node + set node [Tree::_get_node_name $path $id 2] + set found 1 + break + } + } + if {$found} { + set padx [_get_node_padx $path $node] + set deltax [_get_node_deltax $path $node] + set xi [expr {[lindex [$path.c coords n:$node] 0] - $padx - 1}] + if { $data(dnd,mode) & 1 } { + # dropovermode includes node + lappend target $node + set vmode [expr {$vmode | 1}] + } else { + lappend target "" + } + + if { $data(dnd,mode) & 2 } { + # dropovermode includes position + if { $yc >= $yi+$dy/2 } { + # position is after $node + if { [Widget::getoption $path.$node -open] && + [llength $data($node)] > 1 } { + # $node is open and have subnodes + # drop position is 0 in children of $node + set parent $node + set index 0 + set xli [expr {$xi-5}] + } else { + # $node is not open and doesn't have subnodes + # drop position is after $node in children of parent of $node + set parent [lindex $data($node) 0] + set index [lsearch -exact $data($parent) $node] + set xli [expr {$xi - $deltax - 5}] + } + set yl $ys + } else { + # position is before $node + # drop position is before $node in children of parent of $node + set parent [lindex $data($node) 0] + set index [expr {[lsearch -exact $data($parent) $node] - 1}] + set xli [expr {$xi - $deltax - 5}] + set yl $yi + } + lappend target [list $parent $index] + set vmode [expr {$vmode | 2}] + } else { + lappend target {} + } + + if { ($vmode & 3) == 3 } { + # result have both node and position + # we compute what is the preferred method + if { $yc-$yi <= 3 || $ys-$yc <= 3 } { + lappend target "position" + } else { + lappend target "node" + } + } + } + } + + if {$vmode && [llength [set cmd [Widget::getoption $path -dropovercmd]]]} { + # user-defined dropover command + set res [uplevel \#0 $cmd [list $path $source $target $op $type $dnddata]] + set code [lindex $res 0] + set newmode 0 + if { $code & 1 } { + # update vmode + set mode [lindex $res 1] + if { ($vmode & 1) && [string equal $mode "node"] } { + set newmode 1 + } elseif { ($vmode & 2) && [string equal $mode "position"] } { + set newmode 2 + } elseif { ($vmode & 4) && [string equal $mode "widget"] } { + set newmode 4 + } + } + set vmode $newmode + } else { + if { ($vmode & 3) == 3 } { + # result have both item and position + # we choose the preferred method + if { [string equal [lindex $target 3] "position"] } { + set vmode [expr {$vmode & ~1}] + } else { + set vmode [expr {$vmode & ~2}] + } + } + + if { $data(dnd,mode) == 4 || $data(dnd,mode) == 0 } { + # dropovermode is widget or empty - recall is not necessary + set code 1 + } else { + set code 3 + } + } + + if {!$data(dnd,empty)} { + # draw dnd visual following vmode + if { $vmode & 1 } { + set data(dnd,node) [list "node" [lindex $target 1]] + $path.c create rectangle $xi $yi $xs $ys -tags drop + } elseif { $vmode & 2 } { + set data(dnd,node) [concat "position" [lindex $target 2]] + $path.c create line $xli [expr {$yl-$dy/2}] $xli $yl $xs $yl -tags drop + } elseif { $vmode & 4 } { + set data(dnd,node) [list "widget"] + } else { + set code [expr {$code & 2}] + } + } + + if { $code & 1 } { + DropSite::setcursor based_arrow_down + } else { + DropSite::setcursor dot + } + return $code +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_auto_scroll +# ---------------------------------------------------------------------------- +proc Tree::_auto_scroll { path x y } { + variable $path + upvar 0 $path data + + set xmax [winfo width $path] + set ymax [winfo height $path] + set scroll {} + if { $y <= 6 } { + if { [lindex [$path.c yview] 0] > 0 } { + set scroll [list yview -1] + DropSite::setcursor sb_up_arrow + } + } elseif { $y >= $ymax-6 } { + if { [lindex [$path.c yview] 1] < 1 } { + set scroll [list yview 1] + DropSite::setcursor sb_down_arrow + } + } elseif { $x <= 6 } { + if { [lindex [$path.c xview] 0] > 0 } { + set scroll [list xview -1] + DropSite::setcursor sb_left_arrow + } + } elseif { $x >= $xmax-6 } { + if { [lindex [$path.c xview] 1] < 1 } { + set scroll [list xview 1] + DropSite::setcursor sb_right_arrow + } + } + + if { [string length $data(dnd,afterid)] && ![string equal $data(dnd,scroll) $scroll] } { + after cancel $data(dnd,afterid) + set data(dnd,afterid) "" + } + + set data(dnd,scroll) $scroll + if { [string length $scroll] && ![string length $data(dnd,afterid)] } { + set data(dnd,afterid) [after 200 [list Tree::_scroll $path $scroll]] + } + return $data(dnd,afterid) +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_scroll +# ---------------------------------------------------------------------------- +proc Tree::_scroll { path scroll } { + variable $path + upvar 0 $path data + set cmd [lindex $scroll 0] + set dir [lindex $scroll 1] + if { ($dir == -1 && [lindex [$path.c $cmd] 0] > 0) || + ($dir == 1 && [lindex [$path.c $cmd] 1] < 1) } { + $path.c $cmd scroll $dir units + set data(dnd,afterid) [after 50 [list Tree::_scroll $path $scroll]] + } else { + set data(dnd,afterid) "" + DropSite::setcursor dot + } +} + +# Tree::_keynav -- +# +# Handle navigational keypresses on the tree. +# +# Arguments: +# which tag indicating the direction of motion: +# up move to the node graphically above current +# down move to the node graphically below current +# left close current if open, else move to parent +# right open current if closed, else move to child +# open open current if closed, close current if open +# win name of the tree widget +# +# Results: +# None. + +proc Tree::_keynav {which win} { + # check for an empty tree + if {[$win nodes root] eq ""} { + return + } + + # Keyboard navigation is riddled with special cases. In order to avoid + # the complex logic, we will instead make a list of all the visible, + # selectable nodes, then do a simple next or previous operation. + + # One easy way to get all of the visible nodes is to query the canvas + # object for all the items with the "node" tag; since the tree is always + # completely redrawn, this list will be in vertical order. + set nodes {} + foreach nodeItem [$win.c find withtag node] { + set node [Tree::_get_node_name $win $nodeItem 2] + if { [Widget::cget $win.$node -selectable] } { + lappend nodes $node + } + } + + # Keyboard navigation is all relative to the current node + # surles: Get the current node for single or multiple selection schemas. + set node [_get_current_node $win] + + switch -exact -- $which { + "up" { + # Up goes to the node that is vertically above the current node + # (NOT necessarily the current node's parent) + if { [string equal $node ""] } { + return + } + set index [lsearch -exact $nodes $node] + incr index -1 + if { $index >= 0 } { + $win selection set [lindex $nodes $index] + _set_current_node $win [lindex $nodes $index] + $win see [lindex $nodes $index] + event generate $win <<TreeSelect>> + return + } + } + "down" { + # Down goes to the node that is vertically below the current node + if { [string equal $node ""] } { + $win selection set [lindex $nodes 0] + _set_current_node $win [lindex $nodes 0] + $win see [lindex $nodes 0] + event generate $win <<TreeSelect>> + return + } + + set index [lsearch -exact $nodes $node] + incr index + if { $index < [llength $nodes] } { + $win selection set [lindex $nodes $index] + _set_current_node $win [lindex $nodes $index] + $win see [lindex $nodes $index] + event generate $win <<TreeSelect>> + return + } + } + "right" { + # On a right arrow, if the current node is closed, open it. + # If the current node is open, go to its first child + if { [string equal $node ""] } { + return + } + set open [$win itemcget $node -open] + if { $open } { + if { [llength [$win nodes $node]] } { + set index [lsearch -exact $nodes $node] + incr index + if { $index < [llength $nodes] } { + $win selection set [lindex $nodes $index] + _set_current_node $win [lindex $nodes $index] + $win see [lindex $nodes $index] + event generate $win <<TreeSelect>> + return + } + } + } else { + $win itemconfigure $node -open 1 + if {[llength [set cmd [Widget::getoption $win -opencmd]]]} { + uplevel \#0 $cmd [list $node] + } + return + } + } + "left" { + # On a left arrow, if the current node is open, close it. + # If the current node is closed, go to its parent. + if { [string equal $node ""] } { + return + } + set open [$win itemcget $node -open] + if { $open } { + $win itemconfigure $node -open 0 + if {[llength [set cmd [Widget::getoption $win -closecmd]]]} { + uplevel \#0 $cmd [list $node] + } + return + } else { + set parent [$win parent $node] + if { [string equal $parent "root"] } { + set parent $node + } else { + while { ![$win itemcget $parent -selectable] } { + set parent [$win parent $parent] + if { [string equal $parent "root"] } { + set parent $node + break + } + } + } + $win selection set $parent + _set_current_node $win $parent + $win see $parent + event generate $win <<TreeSelect>> + return + } + } + "space" { + if { [string equal $node ""] } { + return + } + set open [$win itemcget $node -open] + if { [llength [$win nodes $node]] } { + + # Toggle the open status of the chosen node. + + $win itemconfigure $node -open [expr {$open?0:1}] + + if {$open} { + # Node was open, is now closed. Call the close-cmd + + if {[llength [set cmd [Widget::getoption $win -closecmd]]]} { + uplevel \#0 $cmd [list $node] + } + } else { + # Node was closed, is now open. Call the open-cmd + + if {[llength [set cmd [Widget::getoption $win -opencmd]]]} { + uplevel \#0 $cmd [list $node] + } + } + } + } + } + return +} + +# Tree::_get_current_node -- +# +# Get the current node for either single or multiple +# node selection trees. If the tree allows for +# multiple selection, return the cursor node. Otherwise, +# if there is a selection, return the first node in the +# list. If there is no selection, return the root node. +# +# arguments: +# win name of the tree widget +# +# Results: +# The current node. + +proc Tree::_get_current_node {win} { + if {[info exists selectTree::selectCursor($win)]} { + set result $selectTree::selectCursor($win) + } elseif {[llength [set selList [$win selection get]]]} { + set result [lindex $selList 0] + } else { + set result "" + } + return $result +} + +# Tree::_set_current_node -- +# +# Set the current node for either single or multiple +# node selection trees. +# +# arguments: +# win Name of the tree widget +# node The current node. +# +# Results: +# None. + +proc Tree::_set_current_node {win node} { + if {[info exists selectTree::selectCursor($win)]} { + set selectTree::selectCursor($win) $node + } + return +} + +# Tree::_get_node_name -- +# +# Given a canvas item, get the name of the tree node represented by that +# item. +# +# Arguments: +# path tree to query +# item Optional canvas item to examine; if omitted, +# defaults to "current" +# tagindex Optional tag index, since the n:nodename tag is not +# in the same spot for all canvas items. If omitted, +# defaults to "end-1", so it works with "current" item. +# +# Results: +# node name of the tree node. + +proc Tree::_get_node_name {path {item current} {tagindex end-1} {truename 0}} { + set node [string range [lindex [$path.c gettags $item] $tagindex] 2 end] + if {$truename} { + return [_node_name_rev $path $node] + } + return $node +} + +# Tree::_get_node_padx -- +# +# Given a node in the tree, return it's padx value. If the value is +# less than 0, default to the padx of the entire tree. +# +# Arguments: +# path Tree to query +# node Node in the tree +# +# Results: +# padx The numeric padx value +proc Tree::_get_node_padx {path node} { + set padx [Widget::getoption $path.$node -padx] + if {$padx < 0} { set padx [Widget::getoption $path -padx] } + return $padx +} + +# Tree::_get_node_deltax -- +# +# Given a node in the tree, return it's deltax value. If the value is +# less than 0, default to the deltax of the entire tree. +# +# Arguments: +# path Tree to query +# node Node in the tree +# +# Results: +# deltax The numeric deltax value +proc Tree::_get_node_deltax {path node} { + set deltax [Widget::getoption $path.$node -deltax] + if {$deltax < 0} { set deltax [Widget::getoption $path -deltax] } + return $deltax +} + + +# Tree::_get_node_tags -- +# +# Given a node in the tree, return a list of tags to apply to its +# canvas item. +# +# Arguments: +# path Tree to query +# node Node in the tree +# tags A list of tags to add to the final list +# +# Results: +# list The list of tags to apply to the canvas item +proc Tree::_get_node_tags {path node {tags ""}} { + eval [linsert $tags 0 lappend list TreeItemSentinal] + if {[Widget::getoption $path.$node -helptext] == "" && + [Widget::getoption $path.$node -helpcmd] == ""} { return $list } + + switch -- [Widget::getoption $path.$node -helptype] { + balloon { + lappend list BwHelpBalloon + } + variable { + lappend list BwHelpVariable + } + } + return $list +} + +# Tree::_set_help -- +# +# Register dynamic help for a node in the tree. +# +# Arguments: +# path Tree to query +# node Node in the tree +# force Optional argument to force a reset of the help +# +# Results: +# none +proc Tree::_set_help { path node } { + Widget::getVariable $path help + + set item $path.$node + set opts [list -helptype -helptext -helpvar -helpcmd] + foreach {cty ctx cv cc} [eval [linsert $opts 0 Widget::hasChangedX $item]] break + set text [Widget::getoption $item -helptext] + set cmd [Widget::getoption $item -helpcmd] + + ## If we've never set help for this item before, and text or cmd is not + ## blank, we need to setup help. We also need to reset help if any of the + ## options have changed. + if { (![info exists help($node)] && ($text != "" || $cmd != "")) + || $cty || $ctx || $cv } { + set help($node) 1 + set type [Widget::getoption $item -helptype] + set var [Widget::getoption $item -helpvar] + DynamicHelp::add $path.c -item n:$node -type $type -text $text -variable $var -command $cmd + DynamicHelp::add $path.c -item i:$node -type $type -text $text -variable $var -command $cmd + DynamicHelp::add $path.c -item b:$node -type $type -text $text -variable $var -command $cmd + } +} + +proc Tree::_mouse_select { path cmd args } { + eval [linsert $args 0 selection $path $cmd] + switch -- $cmd { + "add" - "clear" - "remove" - "set" - "toggle" { + event generate $path <<TreeSelect>> + } + } +} + +proc Tree::_node_name { path node } { + # Make sure node names are safe as tags and variable names + set map [list & \1 | \2 ^ \3 ! \4 :: \5] + return [string map $map $node] +} + +proc Tree::_node_name_rev { path node } { + # Allow reverse interpretation of node names + set map [list \1 & \2 | \3 ^ \4 ! \5 ::] + return [string map $map $node] +} + + +# ---------------------------------------------------------------------------- +# Command Tree::_destroy +# ---------------------------------------------------------------------------- +proc Tree::_destroy { path } { + variable $path + upvar 0 $path data + + if { $data(upd,afterid) != "" } { + after cancel $data(upd,afterid) + } + if { $data(dnd,afterid) != "" } { + after cancel $data(dnd,afterid) + } + _subdelete $path [lrange $data(root) 1 end] + Widget::destroy $path + unset data +} diff --git a/modules/tclsci/tcl/BWidget/utils.tcl b/modules/tclsci/tcl/BWidget/utils.tcl new file mode 100755 index 000000000..5fe804f2a --- /dev/null +++ b/modules/tclsci/tcl/BWidget/utils.tcl @@ -0,0 +1,680 @@ +# ---------------------------------------------------------------------------- +# utils.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: utils.tcl,v 1.15.2.1 2009/09/03 17:29:03 oehhar Exp $ +# ---------------------------------------------------------------------------- +# Index of commands: +# - GlobalVar::exists +# - GlobalVar::setvarvar +# - GlobalVar::getvarvar +# - BWidget::assert +# - BWidget::clonename +# - BWidget::get3dcolor +# - BWidget::XLFDfont +# - BWidget::place +# - BWidget::grab +# - BWidget::focus +# ---------------------------------------------------------------------------- + +namespace eval GlobalVar { + proc use {} {} +} + + +namespace eval BWidget { + variable _top + variable _gstack {} + variable _fstack {} + proc use {} {} +} + + +# ---------------------------------------------------------------------------- +# Command GlobalVar::exists +# ---------------------------------------------------------------------------- +proc GlobalVar::exists { varName } { + return [uplevel \#0 [list info exists $varName]] +} + + +# ---------------------------------------------------------------------------- +# Command GlobalVar::setvar +# ---------------------------------------------------------------------------- +proc GlobalVar::setvar { varName value } { + return [uplevel \#0 [list set $varName $value]] +} + + +# ---------------------------------------------------------------------------- +# Command GlobalVar::getvar +# ---------------------------------------------------------------------------- +proc GlobalVar::getvar { varName } { + return [uplevel \#0 [list set $varName]] +} + + +# ---------------------------------------------------------------------------- +# Command GlobalVar::tracevar +# ---------------------------------------------------------------------------- +proc GlobalVar::tracevar { cmd varName args } { + return [uplevel \#0 [list trace $cmd $varName] $args] +} + + + +# ---------------------------------------------------------------------------- +# Command BWidget::lreorder +# ---------------------------------------------------------------------------- +proc BWidget::lreorder { list neworder } { + set pos 0 + set newlist {} + foreach e $neworder { + if { [lsearch -exact $list $e] != -1 } { + lappend newlist $e + set tabelt($e) 1 + } + } + set len [llength $newlist] + if { !$len } { + return $list + } + if { $len == [llength $list] } { + return $newlist + } + set pos 0 + foreach e $list { + if { ![info exists tabelt($e)] } { + set newlist [linsert $newlist $pos $e] + } + incr pos + } + return $newlist +} + + +# ---------------------------------------------------------------------------- +# Command BWidget::assert +# ---------------------------------------------------------------------------- +proc BWidget::assert { exp {msg ""}} { + set res [uplevel 1 expr $exp] + if { !$res} { + if { $msg == "" } { + return -code error "Assertion failed: {$exp}" + } else { + return -code error $msg + } + } +} + + +# ---------------------------------------------------------------------------- +# Command BWidget::clonename +# ---------------------------------------------------------------------------- +proc BWidget::clonename { menu } { + set path "" + set menupath "" + set found 0 + foreach widget [lrange [split $menu "."] 1 end] { + if { $found || [winfo class "$path.$widget"] == "Menu" } { + set found 1 + append menupath "#" $widget + append path "." $menupath + } else { + append menupath "#" $widget + append path "." $widget + } + } + return $path +} + + +# ---------------------------------------------------------------------------- +# Command BWidget::getname +# ---------------------------------------------------------------------------- +proc BWidget::getname { name } { + if { [string length $name] } { + set text [option get . "${name}Name" ""] + if { [string length $text] } { + return [parsetext $text] + } + } + return {} + } + + +# ---------------------------------------------------------------------------- +# Command BWidget::parsetext +# ---------------------------------------------------------------------------- +proc BWidget::parsetext { text } { + set result "" + set index -1 + set start 0 + while { [string length $text] } { + set idx [string first "&" $text] + if { $idx == -1 } { + append result $text + set text "" + } else { + set char [string index $text [expr {$idx+1}]] + if { $char == "&" } { + append result [string range $text 0 $idx] + set text [string range $text [expr {$idx+2}] end] + set start [expr {$start+$idx+1}] + } else { + append result [string range $text 0 [expr {$idx-1}]] + set text [string range $text [expr {$idx+1}] end] + incr start $idx + set index $start + } + } + } + return [list $result $index] +} + + +# ---------------------------------------------------------------------------- +# Command BWidget::get3dcolor +# ---------------------------------------------------------------------------- +proc BWidget::get3dcolor { path bgcolor } { + foreach val [winfo rgb $path $bgcolor] { + lappend dark [expr {60*$val/100}] + set tmp1 [expr {14*$val/10}] + if { $tmp1 > 65535 } { + set tmp1 65535 + } + set tmp2 [expr {(65535+$val)/2}] + lappend light [expr {($tmp1 > $tmp2) ? $tmp1:$tmp2}] + } + return [list [eval format "#%04x%04x%04x" $dark] [eval format "#%04x%04x%04x" $light]] +} + + +# ---------------------------------------------------------------------------- +# Command BWidget::XLFDfont +# ---------------------------------------------------------------------------- +proc BWidget::XLFDfont { cmd args } { + switch -- $cmd { + create { + set font "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" + } + configure { + set font [lindex $args 0] + set args [lrange $args 1 end] + } + default { + return -code error "XLFDfont: commande incorrect: $cmd" + } + } + set lfont [split $font "-"] + if { [llength $lfont] != 15 } { + return -code error "XLFDfont: description XLFD incorrect: $font" + } + + foreach {option value} $args { + switch -- $option { + -foundry { set index 1 } + -family { set index 2 } + -weight { set index 3 } + -slant { set index 4 } + -size { set index 7 } + default { return -code error "XLFDfont: option incorrecte: $option" } + } + set lfont [lreplace $lfont $index $index $value] + } + return [join $lfont "-"] +} + + + +# ---------------------------------------------------------------------------- +# Command BWidget::place +# ---------------------------------------------------------------------------- +# +# Notes: +# For Windows systems with more than one monitor the available screen area may +# have negative positions. Geometry settings with negative numbers are used +# under X to place wrt the right or bottom of the screen. On windows, Tk +# continues to do this. However, a geometry such as 100x100+-200-100 can be +# used to place a window onto a secondary monitor. Passing the + gets Tk +# to pass the remainder unchanged so the Windows manager then handles -200 +# which is a position on the left hand monitor. +# I've tested this for left, right, above and below the primary monitor. +# Currently there is no way to ask Tk the extent of the Windows desktop in +# a multi monitor system. Nor what the legal co-ordinate range might be. +# +proc BWidget::place { path w h args } { + variable _top + + update idletasks + + # If the window is not mapped, it may have any current size. + # Then use required size, but bound it to the screen width. + # This is mostly inexact, because any toolbars will still be removed + # which may reduce size. + if { $w == 0 && [winfo ismapped $path] } { + set w [winfo width $path] + } else { + if { $w == 0 } { + set w [winfo reqwidth $path] + } + set vsw [winfo vrootwidth $path] + if { $w > $vsw } { set w $vsw } + } + + if { $h == 0 && [winfo ismapped $path] } { + set h [winfo height $path] + } else { + if { $h == 0 } { + set h [winfo reqheight $path] + } + set vsh [winfo vrootheight $path] + if { $h > $vsh } { set h $vsh } + } + + set arglen [llength $args] + if { $arglen > 3 } { + return -code error "BWidget::place: bad number of argument" + } + + if { $arglen > 0 } { + set where [lindex $args 0] + set list [list "at" "center" "left" "right" "above" "below"] + set idx [lsearch $list $where] + if { $idx == -1 } { + return -code error [BWidget::badOptionString position $where $list] + } + if { $idx == 0 } { + set err [catch { + # purposely removed the {} around these expressions - [PT] + set x [expr int([lindex $args 1])] + set y [expr int([lindex $args 2])] + }] + if { $err } { + return -code error "BWidget::place: incorrect position" + } + if {$::tcl_platform(platform) == "windows"} { + # handle windows multi-screen. -100 != +-100 + if {[string index [lindex $args 1] 0] != "-"} { + set x "+$x" + } + if {[string index [lindex $args 2] 0] != "-"} { + set y "+$y" + } + } else { + if { $x >= 0 } { + set x "+$x" + } + if { $y >= 0 } { + set y "+$y" + } + } + } else { + if { $arglen == 2 } { + set widget [lindex $args 1] + if { ![winfo exists $widget] } { + return -code error "BWidget::place: \"$widget\" does not exist" + } + } else { + set widget . + } + set sw [winfo screenwidth $path] + set sh [winfo screenheight $path] + if { $idx == 1 } { + if { $arglen == 2 } { + # center to widget + set x0 [expr {[winfo rootx $widget] + ([winfo width $widget] - $w)/2}] + set y0 [expr {[winfo rooty $widget] + ([winfo height $widget] - $h)/2}] + } else { + # center to screen + set x0 [expr {($sw - $w)/2 - [winfo vrootx $path]}] + set y0 [expr {($sh - $h)/2 - [winfo vrooty $path]}] + } + set x "+$x0" + set y "+$y0" + if {$::tcl_platform(platform) != "windows"} { + if { $x0+$w > $sw } {set x "-0"; set x0 [expr {$sw-$w}]} + if { $x0 < 0 } {set x "+0"} + if { $y0+$h > $sh } {set y "-0"; set y0 [expr {$sh-$h}]} + if { $y0 < 0 } {set y "+0"} + } + } else { + set x0 [winfo rootx $widget] + set y0 [winfo rooty $widget] + set x1 [expr {$x0 + [winfo width $widget]}] + set y1 [expr {$y0 + [winfo height $widget]}] + if { $idx == 2 || $idx == 3 } { + set y "+$y0" + if {$::tcl_platform(platform) != "windows"} { + if { $y0+$h > $sh } {set y "-0"; set y0 [expr {$sh-$h}]} + if { $y0 < 0 } {set y "+0"} + } + if { $idx == 2 } { + # try left, then right if out, then 0 if out + if { $x0 >= $w } { + set x [expr {$x0-$w}] + } elseif { $x1+$w <= $sw } { + set x "+$x1" + } else { + set x "+0" + } + } else { + # try right, then left if out, then 0 if out + if { $x1+$w <= $sw } { + set x "+$x1" + } elseif { $x0 >= $w } { + set x [expr {$x0-$w}] + } else { + set x "-0" + } + } + } else { + set x "+$x0" + if {$::tcl_platform(platform) != "windows"} { + if { $x0+$w > $sw } {set x "-0"; set x0 [expr {$sw-$w}]} + if { $x0 < 0 } {set x "+0"} + } + if { $idx == 4 } { + # try top, then bottom, then 0 + if { $h <= $y0 } { + set y [expr {$y0-$h}] + } elseif { $y1+$h <= $sh } { + set y "+$y1" + } else { + set y "+0" + } + } else { + # try bottom, then top, then 0 + if { $y1+$h <= $sh } { + set y "+$y1" + } elseif { $h <= $y0 } { + set y [expr {$y0-$h}] + } else { + set y "-0" + } + } + } + } + } + + ## If there's not a + or - in front of the number, we need to add one. + if {[string is integer [string index $x 0]]} { set x +$x } + if {[string is integer [string index $y 0]]} { set y +$y } + + wm geometry $path "${w}x${h}${x}${y}" + } else { + wm geometry $path "${w}x${h}" + } + update idletasks +} + + +# ---------------------------------------------------------------------------- +# Command BWidget::grab +# ---------------------------------------------------------------------------- +proc BWidget::grab { option path } { + variable _gstack + + if { $option == "release" } { + catch {::grab release $path} + while { [llength $_gstack] } { + set grinfo [lindex $_gstack end] + set _gstack [lreplace $_gstack end end] + foreach {oldg mode} $grinfo { + if { ![string equal $oldg $path] && [winfo exists $oldg] } { + if { $mode == "global" } { + catch {::grab -global $oldg} + } else { + catch {::grab $oldg} + } + return + } + } + } + } else { + set oldg [::grab current] + if { $oldg != "" } { + lappend _gstack [list $oldg [::grab status $oldg]] + } + if { $option == "global" } { + ::grab -global $path + } else { + ::grab $path + } + } +} + + +# ---------------------------------------------------------------------------- +# Command BWidget::focus +# ---------------------------------------------------------------------------- +proc BWidget::focus { option path {refocus 1} } { + variable _fstack + + if { $option == "release" } { + while { [llength $_fstack] } { + set oldf [lindex $_fstack end] + set _fstack [lreplace $_fstack end end] + if { ![string equal $oldf $path] && [winfo exists $oldf] } { + if {$refocus} {catch {::focus -force $oldf}} + return + } + } + } elseif { $option == "set" } { + lappend _fstack [::focus] + ::focus -force $path + } +} + +# BWidget::refocus -- +# +# Helper function used to redirect focus from a container frame in +# a megawidget to a component widget. Only redirects focus if +# focus is already on the container. +# +# Arguments: +# container container widget to redirect from. +# component component widget to redirect to. +# +# Results: +# None. + +proc BWidget::refocus {container component} { + if { [string equal $container [::focus]] } { + ::focus $component + } + return +} + +## These mirror tk::(Set|Restore)FocusGrab + +# BWidget::SetFocusGrab -- +# swap out current focus and grab temporarily (for dialogs) +# Arguments: +# grab new window to grab +# focus window to give focus to +# Results: +# Returns nothing +# +proc BWidget::SetFocusGrab {grab {focus {}}} { + variable _focusGrab + set index "$grab,$focus" + + lappend _focusGrab($index) [::focus] + set oldGrab [::grab current $grab] + lappend _focusGrab($index) $oldGrab + if {[winfo exists $oldGrab]} { + lappend _focusGrab($index) [::grab status $oldGrab] + } + # The "grab" command will fail if another application + # already holds the grab. So catch it. + catch {::grab $grab} + if {[winfo exists $focus]} { + ::focus $focus + } +} + +# BWidget::RestoreFocusGrab -- +# restore old focus and grab (for dialogs) +# Arguments: +# grab window that had taken grab +# focus window that had taken focus +# destroy destroy|withdraw - how to handle the old grabbed window +# Results: +# Returns nothing +# +proc BWidget::RestoreFocusGrab {grab focus {destroy destroy}} { + variable _focusGrab + set index "$grab,$focus" + if {[info exists _focusGrab($index)]} { + foreach {oldFocus oldGrab oldStatus} $_focusGrab($index) break + unset _focusGrab($index) + } else { + set oldGrab "" + } + + catch {::focus $oldFocus} + ::grab release $grab + if {[string equal $destroy "withdraw"]} { + wm withdraw $grab + } else { + ::destroy $grab + } + if {[winfo exists $oldGrab] && [winfo ismapped $oldGrab]} { + if {[string equal $oldStatus "global"]} { + ::grab -global $oldGrab + } else { + ::grab $oldGrab + } + } +} + +# BWidget::badOptionString -- +# +# Helper function to return a proper error string when an option +# doesn't match a list of given options. +# +# Arguments: +# type A string that represents the type of option. +# value The value that is in-valid. +# list A list of valid options. +# +# Results: +# None. +proc BWidget::badOptionString {type value list} { + set last [lindex $list end] + set list [lreplace $list end end] + return "bad $type \"$value\": must be [join $list ", "], or $last" +} + + +proc BWidget::wrongNumArgsString { string } { + return "wrong # args: should be \"$string\"" +} + + +proc BWidget::read_file { file } { + set fp [open $file] + set x [read $fp [file size $file]] + close $fp + return $x +} + + +proc BWidget::classes { class } { + variable use + + ${class}::use + set classes [list $class] + if {![info exists use($class)]} { return } + foreach class $use($class) { + if {![string equal $class "-classonly"]} { + eval lappend classes [classes $class] + } + } + return [lsort -unique $classes] +} + + +proc BWidget::library { args } { + variable use + + set libs [list widget init utils] + set classes [list] + foreach class $args { + ${class}::use + eval lappend classes [classes $class] + } + + eval lappend libs [lsort -unique $classes] + + set library "" + foreach lib $libs { + if {![info exists use($lib,file)]} { + set file [file join $::BWIDGET::LIBRARY $lib.tcl] + } else { + set file [file join $::BWIDGET::LIBRARY $use($lib,file).tcl] + } + append library [read_file $file] + } + + return $library +} + + +proc BWidget::inuse { class } { + variable ::Widget::_inuse + + if {![info exists _inuse($class)]} { return 0 } + return [expr $_inuse($class) > 0] +} + + +proc BWidget::write { filename {mode w} } { + variable use + + if {![info exists use(classes)]} { return } + + set classes [list] + foreach class $use(classes) { + if {![inuse $class]} { continue } + lappend classes $class + } + + set fp [open $filename $mode] + puts $fp [eval library $classes] + close $fp + + return +} + + +# BWidget::bindMouseWheel -- +# +# Bind mouse wheel actions to a given widget. +# +# Arguments: +# widget - The widget to bind. +# +# Results: +# None. +proc BWidget::bindMouseWheel { widget } { + if {[bind all <MouseWheel>] eq ""} { + # style::as and Tk 8.5 have global bindings + # Only enable these if no global binding for MouseWheel exists + bind $widget <MouseWheel> \ + {%W yview scroll [expr {-%D/24}] units} + bind $widget <Shift-MouseWheel> \ + {%W yview scroll [expr {-%D/120}] pages} + bind $widget <Control-MouseWheel> \ + {%W yview scroll [expr {-%D/120}] units} + } + + if {[bind all <Button-4>] eq ""} { + # style::as and Tk 8.5 have global bindings + # Only enable these if no global binding for them exists + bind $widget <Button-4> {event generate %W <MouseWheel> -delta 120} + bind $widget <Button-5> {event generate %W <MouseWheel> -delta -120} + } +} + + diff --git a/modules/tclsci/tcl/BWidget/widget.tcl b/modules/tclsci/tcl/BWidget/widget.tcl new file mode 100755 index 000000000..a0c0fa8fa --- /dev/null +++ b/modules/tclsci/tcl/BWidget/widget.tcl @@ -0,0 +1,1610 @@ +# ---------------------------------------------------------------------------- +# widget.tcl +# This file is part of Unifix BWidget Toolkit +# $Id: widget.tcl,v 1.35 2009/07/02 16:22:18 oehhar Exp $ +# ---------------------------------------------------------------------------- +# Index of commands: +# - Widget::tkinclude +# - Widget::bwinclude +# - Widget::declare +# - Widget::addmap +# - Widget::init +# - Widget::destroy +# - Widget::setoption +# - Widget::configure +# - Widget::cget +# - Widget::subcget +# - Widget::hasChanged +# - Widget::options +# - Widget::_get_tkwidget_options +# - Widget::_test_tkresource +# - Widget::_test_bwresource +# - Widget::_test_synonym +# - Widget::_test_string +# - Widget::_test_flag +# - Widget::_test_enum +# - Widget::_test_int +# - Widget::_test_boolean +# ---------------------------------------------------------------------------- +# Each megawidget gets a namespace of the same name inside the Widget namespace +# Each of these has an array opt, which contains information about the +# megawidget options. It maps megawidget options to a list with this format: +# {optionType defaultValue isReadonly {additionalOptionalInfo}} +# Option types and their additional optional info are: +# TkResource {genericTkWidget genericTkWidgetOptionName} +# BwResource {nothing} +# Enum {list of enumeration values} +# Int {Boundary information} +# Boolean {nothing} +# String {nothing} +# Flag {string of valid flag characters} +# Synonym {nothing} +# Color {nothing} +# +# Next, each namespace has an array map, which maps class options to their +# component widget options: +# map(-foreground) => {.e -foreground .f -foreground} +# +# Each has an array ${path}:opt, which contains the value of each megawidget +# option for a particular instance $path of the megawidget, and an array +# ${path}:mod, which stores the "changed" status of configuration options. + +# Steps for creating a bwidget megawidget: +# 1. parse args to extract subwidget spec +# 2. Create frame with appropriate class and command line options +# 3. Get initialization options from optionDB, using frame +# 4. create subwidgets + +# Uses newer string operations +package require Tcl 8.1.1 + +namespace eval Widget { + variable _optiontype + variable _class + variable _tk_widget + + # This controls whether we try to use themed widgets from Tile + variable _theme 0 + + variable _aqua [expr {($::tcl_version >= 8.4) && + [string equal [tk windowingsystem] "aqua"]}] + + array set _optiontype { + TkResource Widget::_test_tkresource + BwResource Widget::_test_bwresource + Enum Widget::_test_enum + Int Widget::_test_int + Boolean Widget::_test_boolean + String Widget::_test_string + Flag Widget::_test_flag + Synonym Widget::_test_synonym + Color Widget::_test_color + Padding Widget::_test_padding + } + + proc use {} {} +} + + +# ---------------------------------------------------------------------------- +# Command Widget::tkinclude +# Includes tk widget resources to BWidget widget. +# class class name of the BWidget +# tkwidget tk widget to include +# subpath subpath to configure +# args additionnal args for included options +# ---------------------------------------------------------------------------- +proc Widget::tkinclude { class tkwidget subpath args } { + foreach {cmd lopt} $args { + # cmd can be + # include options to include lopt = {opt ...} + # remove options to remove lopt = {opt ...} + # rename options to rename lopt = {opt newopt ...} + # prefix options to prefix lopt = {pref opt opt ..} + # initialize set default value for options lopt = {opt value ...} + # readonly set readonly flag for options lopt = {opt flag ...} + switch -- $cmd { + remove { + foreach option $lopt { + set remove($option) 1 + } + } + include { + foreach option $lopt { + set include($option) 1 + } + } + prefix { + set prefix [lindex $lopt 0] + foreach option [lrange $lopt 1 end] { + set rename($option) "-$prefix[string range $option 1 end]" + } + } + rename - + readonly - + initialize { + array set $cmd $lopt + } + default { + return -code error "invalid argument \"$cmd\"" + } + } + } + + namespace eval $class {} + upvar 0 ${class}::opt classopt + upvar 0 ${class}::map classmap + upvar 0 ${class}::map$subpath submap + upvar 0 ${class}::optionExports exports + + set foo [$tkwidget ".ericFoo###"] + # create resources informations from tk widget resources + foreach optdesc [_get_tkwidget_options $tkwidget] { + set option [lindex $optdesc 0] + if { (![info exists include] || [info exists include($option)]) && + ![info exists remove($option)] } { + if { [llength $optdesc] == 3 } { + # option is a synonym + set syn [lindex $optdesc 1] + if { ![info exists remove($syn)] } { + # original option is not removed + if { [info exists rename($syn)] } { + set classopt($option) [list Synonym $rename($syn)] + } else { + set classopt($option) [list Synonym $syn] + } + } + } else { + if { [info exists rename($option)] } { + set realopt $option + set option $rename($option) + } else { + set realopt $option + } + if { [info exists initialize($option)] } { + set value $initialize($option) + } else { + set value [lindex $optdesc 1] + } + if { [info exists readonly($option)] } { + set ro $readonly($option) + } else { + set ro 0 + } + set classopt($option) \ + [list TkResource $value $ro [list $tkwidget $realopt]] + + # Add an option database entry for this option + set optionDbName ".[lindex [_configure_option $realopt ""] 0]" + if { ![string equal $subpath ":cmd"] } { + set optionDbName "$subpath$optionDbName" + } + option add *${class}$optionDbName $value widgetDefault + lappend exports($option) "$optionDbName" + + # Store the forward and backward mappings for this + # option <-> realoption pair + lappend classmap($option) $subpath "" $realopt + set submap($realopt) $option + } + } + } + ::destroy $foo +} + + +# ---------------------------------------------------------------------------- +# Command Widget::bwinclude +# Includes BWidget resources to BWidget widget. +# class class name of the BWidget +# subclass BWidget class to include +# subpath subpath to configure +# args additionnal args for included options +# ---------------------------------------------------------------------------- +proc Widget::bwinclude { class subclass subpath args } { + foreach {cmd lopt} $args { + # cmd can be + # include options to include lopt = {opt ...} + # remove options to remove lopt = {opt ...} + # rename options to rename lopt = {opt newopt ...} + # prefix options to prefix lopt = {prefix opt opt ...} + # initialize set default value for options lopt = {opt value ...} + # readonly set readonly flag for options lopt = {opt flag ...} + switch -- $cmd { + remove { + foreach option $lopt { + set remove($option) 1 + } + } + include { + foreach option $lopt { + set include($option) 1 + } + } + prefix { + set prefix [lindex $lopt 0] + foreach option [lrange $lopt 1 end] { + set rename($option) "-$prefix[string range $option 1 end]" + } + } + rename - + readonly - + initialize { + array set $cmd $lopt + } + default { + return -code error "invalid argument \"$cmd\"" + } + } + } + + namespace eval $class {} + upvar 0 ${class}::opt classopt + upvar 0 ${class}::map classmap + upvar 0 ${class}::map$subpath submap + upvar 0 ${class}::optionExports exports + upvar 0 ${subclass}::opt subclassopt + upvar 0 ${subclass}::optionExports subexports + + # create resources informations from BWidget resources + foreach {option optdesc} [array get subclassopt] { + set subOption $option + if { (![info exists include] || [info exists include($option)]) && + ![info exists remove($option)] } { + set type [lindex $optdesc 0] + if { [string equal $type "Synonym"] } { + # option is a synonym + set syn [lindex $optdesc 1] + if { ![info exists remove($syn)] } { + if { [info exists rename($syn)] } { + set classopt($option) [list Synonym $rename($syn)] + } else { + set classopt($option) [list Synonym $syn] + } + } + } else { + if { [info exists rename($option)] } { + set realopt $option + set option $rename($option) + } else { + set realopt $option + } + if { [info exists initialize($option)] } { + set value $initialize($option) + } else { + set value [lindex $optdesc 1] + } + if { [info exists readonly($option)] } { + set ro $readonly($option) + } else { + set ro [lindex $optdesc 2] + } + set classopt($option) \ + [list $type $value $ro [lindex $optdesc 3]] + + # Add an option database entry for this option + foreach optionDbName $subexports($subOption) { + if { ![string equal $subpath ":cmd"] } { + set optionDbName "$subpath$optionDbName" + } + # Only add the option db entry if we are overriding the + # normal widget default + if { [info exists initialize($option)] } { + option add *${class}$optionDbName $value \ + widgetDefault + } + lappend exports($option) "$optionDbName" + } + + # Store the forward and backward mappings for this + # option <-> realoption pair + lappend classmap($option) $subpath $subclass $realopt + set submap($realopt) $option + } + } + } +} + + +# ---------------------------------------------------------------------------- +# Command Widget::declare +# Declares new options to BWidget class. +# ---------------------------------------------------------------------------- +proc Widget::declare { class optlist } { + variable _optiontype + + namespace eval $class {} + upvar 0 ${class}::opt classopt + upvar 0 ${class}::optionExports exports + upvar 0 ${class}::optionClass optionClass + + foreach optdesc $optlist { + set option [lindex $optdesc 0] + set optdesc [lrange $optdesc 1 end] + set type [lindex $optdesc 0] + + if { ![info exists _optiontype($type)] } { + # invalid resource type + return -code error "invalid option type \"$type\"" + } + + if { [string equal $type "Synonym"] } { + # test existence of synonym option + set syn [lindex $optdesc 1] + if { ![info exists classopt($syn)] } { + return -code error "unknow option \"$syn\" for Synonym \"$option\"" + } + set classopt($option) [list Synonym $syn] + continue + } + + # all other resource may have default value, readonly flag and + # optional arg depending on type + set value [lindex $optdesc 1] + set ro [lindex $optdesc 2] + set arg [lindex $optdesc 3] + + if { [string equal $type "BwResource"] } { + # We don't keep BwResource. We simplify to type of sub BWidget + set subclass [lindex $arg 0] + set realopt [lindex $arg 1] + if { ![string length $realopt] } { + set realopt $option + } + + upvar 0 ${subclass}::opt subclassopt + if { ![info exists subclassopt($realopt)] } { + return -code error "unknow option \"$realopt\"" + } + set suboptdesc $subclassopt($realopt) + if { $value == "" } { + # We initialize default value + set value [lindex $suboptdesc 1] + } + set type [lindex $suboptdesc 0] + set ro [lindex $suboptdesc 2] + set arg [lindex $suboptdesc 3] + set optionDbName ".[lindex [_configure_option $option ""] 0]" + option add *${class}${optionDbName} $value widgetDefault + set exports($option) $optionDbName + set classopt($option) [list $type $value $ro $arg] + continue + } + + # retreive default value for TkResource + if { [string equal $type "TkResource"] } { + set tkwidget [lindex $arg 0] + set foo [$tkwidget ".ericFoo##"] + set realopt [lindex $arg 1] + if { ![string length $realopt] } { + set realopt $option + } + set tkoptions [_get_tkwidget_options $tkwidget] + if { ![string length $value] } { + # We initialize default value + set ind [lsearch $tkoptions [list $realopt *]] + set value [lindex [lindex $tkoptions $ind] end] + } + set optionDbName ".[lindex [_configure_option $option ""] 0]" + option add *${class}${optionDbName} $value widgetDefault + set exports($option) $optionDbName + set classopt($option) [list TkResource $value $ro \ + [list $tkwidget $realopt]] + set optionClass($option) [lindex [$foo configure $realopt] 1] + ::destroy $foo + continue + } + + set optionDbName ".[lindex [_configure_option $option ""] 0]" + option add *${class}${optionDbName} $value widgetDefault + set exports($option) $optionDbName + # for any other resource type, we keep original optdesc + set classopt($option) [list $type $value $ro $arg] + } +} + + +proc Widget::define { class filename args } { + variable ::BWidget::use + set use($class) $args + set use($class,file) $filename + lappend use(classes) $class + + if {[set x [lsearch -exact $args "-classonly"]] > -1} { + set args [lreplace $args $x $x] + } else { + interp alias {} ::${class} {} ${class}::create + proc ::${class}::use {} {} + + bind $class <Destroy> [list Widget::destroy %W] + } + + foreach class $args { ${class}::use } +} + + +proc Widget::create { class path {rename 1} } { + if {$rename} { rename $path ::$path:cmd } + proc ::$path { cmd args } \ + [subst {return \[eval \[linsert \$args 0 ${class}::\$cmd [list $path]\]\]}] + return $path +} + + +# ---------------------------------------------------------------------------- +# Command Widget::addmap +# ---------------------------------------------------------------------------- +proc Widget::addmap { class subclass subpath options } { + upvar 0 ${class}::opt classopt + upvar 0 ${class}::optionExports exports + upvar 0 ${class}::optionClass optionClass + upvar 0 ${class}::map classmap + upvar 0 ${class}::map$subpath submap + + foreach {option realopt} $options { + if { ![string length $realopt] } { + set realopt $option + } + set val [lindex $classopt($option) 1] + set optDb ".[lindex [_configure_option $realopt ""] 0]" + if { ![string equal $subpath ":cmd"] } { + set optDb "$subpath$optDb" + } + option add *${class}${optDb} $val widgetDefault + lappend exports($option) $optDb + # Store the forward and backward mappings for this + # option <-> realoption pair + lappend classmap($option) $subpath $subclass $realopt + set submap($realopt) $option + } +} + + +# ---------------------------------------------------------------------------- +# Command Widget::syncoptions +# ---------------------------------------------------------------------------- +proc Widget::syncoptions { class subclass subpath options } { + upvar 0 ${class}::sync classync + + foreach {option realopt} $options { + if { ![string length $realopt] } { + set realopt $option + } + set classync($option) [list $subpath $subclass $realopt] + } +} + + +# ---------------------------------------------------------------------------- +# Command Widget::init +# ---------------------------------------------------------------------------- +proc Widget::init { class path options } { + variable _inuse + variable _class + variable _optiontype + + upvar 0 ${class}::opt classopt + upvar 0 ${class}::$path:opt pathopt + upvar 0 ${class}::$path:mod pathmod + upvar 0 ${class}::map classmap + upvar 0 ${class}::$path:init pathinit + + if { [info exists pathopt] } { + unset pathopt + } + if { [info exists pathmod] } { + unset pathmod + } + # We prefer to use the actual widget for option db queries, but if it + # doesn't exist yet, do the next best thing: create a widget of the + # same class and use that. + set fpath $path + set rdbclass [string map [list :: ""] $class] + if { ![winfo exists $path] } { + set fpath ".#BWidget.#Class#$class" + # encapsulation frame to not pollute '.' childspace + if {![winfo exists ".#BWidget"]} { frame ".#BWidget" } + if { ![winfo exists $fpath] } { + frame $fpath -class $rdbclass + } + } + foreach {option optdesc} [array get classopt] { + set pathmod($option) 0 + if { [info exists classmap($option)] } { + continue + } + set type [lindex $optdesc 0] + if { [string equal $type "Synonym"] } { + continue + } + if { [string equal $type "TkResource"] } { + set alt [lindex [lindex $optdesc 3] 1] + } else { + set alt "" + } + set optdb [lindex [_configure_option $option $alt] 0] + set def [option get $fpath $optdb $rdbclass] + if { [string length $def] } { + set pathopt($option) $def + } else { + set pathopt($option) [lindex $optdesc 1] + } + } + + if {![info exists _inuse($class)]} { set _inuse($class) 0 } + incr _inuse($class) + + set _class($path) $class + foreach {option value} $options { + if { ![info exists classopt($option)] } { + unset pathopt + unset pathmod + return -code error "unknown option \"$option\"" + } + set optdesc $classopt($option) + set type [lindex $optdesc 0] + if { [string equal $type "Synonym"] } { + set option [lindex $optdesc 1] + set optdesc $classopt($option) + set type [lindex $optdesc 0] + } + # this may fail if a wrong enum element was used + if {[catch { + $_optiontype($type) $option $value [lindex $optdesc 3] + } msg]} { + if {[info exists pathopt]} { + unset pathopt + } + unset pathmod + return -code error $msg + } + set pathopt($option) $msg + set pathinit($option) $pathopt($option) + } +} + +# Bastien Chevreux (bach@mwgdna.com) +# +# copyinit performs basically the same job as init, but it uses a +# existing template to initialize its values. So, first a perferct copy +# from the template is made just to be altered by any existing options +# afterwards. +# But this still saves time as the first initialization parsing block is +# skipped. +# As additional bonus, items that differ in just a few options can be +# initialized faster by leaving out the options that are equal. + +# This function is currently used only by ListBox::multipleinsert, but other +# calls should follow :) + +# ---------------------------------------------------------------------------- +# Command Widget::copyinit +# ---------------------------------------------------------------------------- +proc Widget::copyinit { class templatepath path options } { + variable _class + variable _optiontype + upvar 0 ${class}::opt classopt \ + ${class}::$path:opt pathopt \ + ${class}::$path:mod pathmod \ + ${class}::$path:init pathinit \ + ${class}::$templatepath:opt templatepathopt \ + ${class}::$templatepath:mod templatepathmod \ + ${class}::$templatepath:init templatepathinit + + if { [info exists pathopt] } { + unset pathopt + } + if { [info exists pathmod] } { + unset pathmod + } + + # We use the template widget for option db copying, but it has to exist! + array set pathmod [array get templatepathmod] + array set pathopt [array get templatepathopt] + array set pathinit [array get templatepathinit] + + set _class($path) $class + foreach {option value} $options { + if { ![info exists classopt($option)] } { + unset pathopt + unset pathmod + return -code error "unknown option \"$option\"" + } + set optdesc $classopt($option) + set type [lindex $optdesc 0] + if { [string equal $type "Synonym"] } { + set option [lindex $optdesc 1] + set optdesc $classopt($option) + set type [lindex $optdesc 0] + } + set pathopt($option) [$_optiontype($type) $option $value [lindex $optdesc 3]] + set pathinit($option) $pathopt($option) + } +} + +# Widget::parseArgs -- +# +# Given a widget class and a command-line spec, cannonize and validate +# the given options, and return a keyed list consisting of the +# component widget and its masked portion of the command-line spec, and +# one extra entry consisting of the portion corresponding to the +# megawidget itself. +# +# Arguments: +# class widget class to parse for. +# options command-line spec +# +# Results: +# result keyed list of portions of the megawidget and that segment of +# the command line in which that portion is interested. + +proc Widget::parseArgs {class options} { + variable _optiontype + upvar 0 ${class}::opt classopt + upvar 0 ${class}::map classmap + + foreach {option val} $options { + if { ![info exists classopt($option)] } { + error "unknown option \"$option\"" + } + set optdesc $classopt($option) + set type [lindex $optdesc 0] + if { [string equal $type "Synonym"] } { + set option [lindex $optdesc 1] + set optdesc $classopt($option) + set type [lindex $optdesc 0] + } + if { [string equal $type "TkResource"] } { + # Make sure that the widget used for this TkResource exists + Widget::_get_tkwidget_options [lindex [lindex $optdesc 3] 0] + } + set val [$_optiontype($type) $option $val [lindex $optdesc 3]] + + if { [info exists classmap($option)] } { + foreach {subpath subclass realopt} $classmap($option) { + lappend maps($subpath) $realopt $val + } + } else { + lappend maps($class) $option $val + } + } + return [array get maps] +} + +# Widget::initFromODB -- +# +# Initialize a megawidgets options with information from the option +# database and from the command-line arguments given. +# +# Arguments: +# class class of the widget. +# path path of the widget -- should already exist. +# options command-line arguments. +# +# Results: +# None. + +proc Widget::initFromODB {class path options} { + variable _inuse + variable _class + + upvar 0 ${class}::$path:opt pathopt + upvar 0 ${class}::$path:mod pathmod + upvar 0 ${class}::map classmap + + if { [info exists pathopt] } { + unset pathopt + } + if { [info exists pathmod] } { + unset pathmod + } + # We prefer to use the actual widget for option db queries, but if it + # doesn't exist yet, do the next best thing: create a widget of the + # same class and use that. + set fpath [_get_window $class $path] + set rdbclass [string map [list :: ""] $class] + if { ![winfo exists $path] } { + set fpath ".#BWidget.#Class#$class" + # encapsulation frame to not pollute '.' childspace + if {![winfo exists ".#BWidget"]} { frame ".#BWidget" } + if { ![winfo exists $fpath] } { + frame $fpath -class $rdbclass + } + } + + foreach {option optdesc} [array get ${class}::opt] { + set pathmod($option) 0 + if { [info exists classmap($option)] } { + continue + } + set type [lindex $optdesc 0] + if { [string equal $type "Synonym"] } { + continue + } + if { [string equal $type "TkResource"] } { + set alt [lindex [lindex $optdesc 3] 1] + } else { + set alt "" + } + set optdb [lindex [_configure_option $option $alt] 0] + set def [option get $fpath $optdb $rdbclass] + if { [string length $def] } { + set pathopt($option) $def + } else { + set pathopt($option) [lindex $optdesc 1] + } + } + + if {![info exists _inuse($class)]} { set _inuse($class) 0 } + incr _inuse($class) + + set _class($path) $class + array set pathopt $options +} + + + +# ---------------------------------------------------------------------------- +# Command Widget::destroy +# ---------------------------------------------------------------------------- +proc Widget::destroy { path } { + variable _class + variable _inuse + + if {![info exists _class($path)]} { return } + + set class $_class($path) + upvar 0 ${class}::$path:opt pathopt + upvar 0 ${class}::$path:mod pathmod + upvar 0 ${class}::$path:init pathinit + + if {[info exists _inuse($class)]} { incr _inuse($class) -1 } + + if {[info exists pathopt]} { + unset pathopt + } + if {[info exists pathmod]} { + unset pathmod + } + if {[info exists pathinit]} { + unset pathinit + } + + if {![string equal [info commands $path] ""]} { rename $path "" } + + ## Unset any variables used in this widget. + foreach var [info vars ::${class}::$path:*] { unset $var } + + unset _class($path) +} + + +# ---------------------------------------------------------------------------- +# Command Widget::configure +# ---------------------------------------------------------------------------- +proc Widget::configure { path options } { + set len [llength $options] + if { $len <= 1 } { + return [_get_configure $path $options] + } elseif { $len % 2 == 1 } { + return -code error "incorrect number of arguments" + } + + variable _class + variable _optiontype + + set class $_class($path) + upvar 0 ${class}::opt classopt + upvar 0 ${class}::map classmap + upvar 0 ${class}::$path:opt pathopt + upvar 0 ${class}::$path:mod pathmod + + set window [_get_window $class $path] + foreach {option value} $options { + if { ![info exists classopt($option)] } { + return -code error "unknown option \"$option\"" + } + set optdesc $classopt($option) + set type [lindex $optdesc 0] + if { [string equal $type "Synonym"] } { + set option [lindex $optdesc 1] + set optdesc $classopt($option) + set type [lindex $optdesc 0] + } + if { ![lindex $optdesc 2] } { + set newval [$_optiontype($type) $option $value [lindex $optdesc 3]] + if { [info exists classmap($option)] } { + set window [_get_window $class $window] + foreach {subpath subclass realopt} $classmap($option) { + # Interpretation of special pointers: + # | subclass | subpath | widget | path | class | + # +----------+---------+------------------+----------------+-context-+ + # | :cmd | :cmd | herited widget | window:cmd |window | + # | :cmd | * | subwidget | window.subpath | window | + # | "" | :cmd | herited widget | window:cmd | window | + # | "" | * | own | window | window | + # | * | :cmd | own | window | current | + # | * | * | subwidget | window.subpath | current | + if { [string length $subclass] && ! [string equal $subclass ":cmd"] } { + if { [string equal $subpath ":cmd"] } { + set subpath "" + } + set curval [${subclass}::cget $window$subpath $realopt] + ${subclass}::configure $window$subpath $realopt $newval + } else { + set curval [$window$subpath cget $realopt] + $window$subpath configure $realopt $newval + } + } + } else { + set curval $pathopt($option) + set pathopt($option) $newval + } + set pathmod($option) [expr {![string equal $newval $curval]}] + } + } + + return {} +} + + +# ---------------------------------------------------------------------------- +# Command Widget::cget +# ---------------------------------------------------------------------------- +proc Widget::cget { path option } { + variable _class + if { ![info exists _class($path)] } { + return -code error "unknown widget $path" + } + + set class $_class($path) + if { ![info exists ${class}::opt($option)] } { + return -code error "unknown option \"$option\"" + } + + set optdesc [set ${class}::opt($option)] + set type [lindex $optdesc 0] + if {[string equal $type "Synonym"]} { + set option [lindex $optdesc 1] + } + + if { [info exists ${class}::map($option)] } { + foreach {subpath subclass realopt} [set ${class}::map($option)] {break} + set path "[_get_window $class $path]$subpath" + return [$path cget $realopt] + } + upvar 0 ${class}::$path:opt pathopt + set pathopt($option) +} + + +# ---------------------------------------------------------------------------- +# Command Widget::subcget +# ---------------------------------------------------------------------------- +proc Widget::subcget { path subwidget } { + variable _class + set class $_class($path) + upvar 0 ${class}::$path:opt pathopt + upvar 0 ${class}::map$subwidget submap + upvar 0 ${class}::$path:init pathinit + + set result {} + foreach realopt [array names submap] { + if { [info exists pathinit($submap($realopt))] } { + lappend result $realopt $pathopt($submap($realopt)) + } + } + return $result +} + + +# ---------------------------------------------------------------------------- +# Command Widget::hasChanged +# ---------------------------------------------------------------------------- +proc Widget::hasChanged { path option pvalue } { + variable _class + upvar $pvalue value + set class $_class($path) + upvar 0 ${class}::$path:mod pathmod + + set value [Widget::cget $path $option] + set result $pathmod($option) + set pathmod($option) 0 + + return $result +} + +proc Widget::hasChangedX { path option args } { + variable _class + set class $_class($path) + upvar 0 ${class}::$path:mod pathmod + + set result $pathmod($option) + set pathmod($option) 0 + foreach option $args { + lappend result $pathmod($option) + set pathmod($option) 0 + } + + set result +} + + +# ---------------------------------------------------------------------------- +# Command Widget::setoption +# ---------------------------------------------------------------------------- +proc Widget::setoption { path option value } { +# variable _class + +# set class $_class($path) +# upvar 0 ${class}::$path:opt pathopt + +# set pathopt($option) $value + Widget::configure $path [list $option $value] +} + + +# ---------------------------------------------------------------------------- +# Command Widget::getoption +# ---------------------------------------------------------------------------- +proc Widget::getoption { path option } { +# set class $::Widget::_class($path) +# upvar 0 ${class}::$path:opt pathopt + +# return $pathopt($option) + return [Widget::cget $path $option] +} + +# Widget::getMegawidgetOption -- +# +# Bypass the superfluous checks in cget and just directly peer at the +# widget's data space. This is much more fragile than cget, so it +# should only be used with great care, in places where speed is critical. +# +# Arguments: +# path widget to lookup options for. +# option option to retrieve. +# +# Results: +# value option value. + +proc Widget::getMegawidgetOption {path option} { + variable _class + set class $_class($path) + upvar 0 ${class}::${path}:opt pathopt + set pathopt($option) +} + +# Widget::setMegawidgetOption -- +# +# Bypass the superfluous checks in cget and just directly poke at the +# widget's data space. This is much more fragile than configure, so it +# should only be used with great care, in places where speed is critical. +# +# Arguments: +# path widget to lookup options for. +# option option to retrieve. +# value option value. +# +# Results: +# value option value. + +proc Widget::setMegawidgetOption {path option value} { + variable _class + set class $_class($path) + upvar 0 ${class}::${path}:opt pathopt + set pathopt($option) $value +} + +# ---------------------------------------------------------------------------- +# Command Widget::_get_window +# returns the window corresponding to widget path +# ---------------------------------------------------------------------------- +proc Widget::_get_window { class path } { + set idx [string last "#" $path] + if { $idx != -1 && [string equal [string range $path [expr {$idx+1}] end] $class] } { + return [string range $path 0 [expr {$idx-1}]] + } else { + return $path + } +} + + +# ---------------------------------------------------------------------------- +# Command Widget::_get_configure +# returns the configuration list of options +# (as tk widget do - [$w configure ?option?]) +# ---------------------------------------------------------------------------- +proc Widget::_get_configure { path options } { + variable _class + + set class $_class($path) + upvar 0 ${class}::opt classopt + upvar 0 ${class}::map classmap + upvar 0 ${class}::$path:opt pathopt + upvar 0 ${class}::$path:mod pathmod + + set len [llength $options] + if { !$len } { + set result {} + foreach option [lsort [array names classopt]] { + set optdesc $classopt($option) + set type [lindex $optdesc 0] + if { [string equal $type "Synonym"] } { + set syn $option + set option [lindex $optdesc 1] + set optdesc $classopt($option) + set type [lindex $optdesc 0] + } else { + set syn "" + } + if { [string equal $type "TkResource"] } { + set alt [lindex [lindex $optdesc 3] 1] + } else { + set alt "" + } + set res [_configure_option $option $alt] + if { $syn == "" } { + lappend result [concat $option $res [list [lindex $optdesc 1]] [list [cget $path $option]]] + } else { + lappend result [list $syn [lindex $res 0]] + } + } + return $result + } elseif { $len == 1 } { + set option [lindex $options 0] + if { ![info exists classopt($option)] } { + return -code error "unknown option \"$option\"" + } + set optdesc $classopt($option) + set type [lindex $optdesc 0] + if { [string equal $type "Synonym"] } { + set option [lindex $optdesc 1] + set optdesc $classopt($option) + set type [lindex $optdesc 0] + } + if { [string equal $type "TkResource"] } { + set alt [lindex [lindex $optdesc 3] 1] + } else { + set alt "" + } + set res [_configure_option $option $alt] + return [concat $option $res [list [lindex $optdesc 1]] [list [cget $path $option]]] + } +} + + +# ---------------------------------------------------------------------------- +# Command Widget::_configure_option +# ---------------------------------------------------------------------------- +proc Widget::_configure_option { option altopt } { + variable _optiondb + variable _optionclass + + if { [info exists _optiondb($option)] } { + set optdb $_optiondb($option) + } else { + set optdb [string range $option 1 end] + } + if { [info exists _optionclass($option)] } { + set optclass $_optionclass($option) + } elseif { [string length $altopt] } { + if { [info exists _optionclass($altopt)] } { + set optclass $_optionclass($altopt) + } else { + set optclass [string range $altopt 1 end] + } + } else { + set optclass [string range $option 1 end] + } + return [list $optdb $optclass] +} + + +# ---------------------------------------------------------------------------- +# Command Widget::_get_tkwidget_options +# ---------------------------------------------------------------------------- +proc Widget::_get_tkwidget_options { tkwidget } { + variable _tk_widget + variable _optiondb + variable _optionclass + + set widget ".#BWidget.#$tkwidget" + # encapsulation frame to not pollute '.' childspace + if {![winfo exists ".#BWidget"]} { frame ".#BWidget" } + if { ![winfo exists $widget] || ![info exists _tk_widget($tkwidget)] } { + set widget [$tkwidget $widget] + # JDC: Withdraw toplevels, otherwise visible + if {[string equal $tkwidget "toplevel"]} { + wm withdraw $widget + } + set config [$widget configure] + foreach optlist $config { + set opt [lindex $optlist 0] + if { [llength $optlist] == 2 } { + set refsyn [lindex $optlist 1] + # search for class + set idx [lsearch $config [list * $refsyn *]] + if { $idx == -1 } { + if { [string index $refsyn 0] == "-" } { + # search for option (tk8.1b1 bug) + set idx [lsearch $config [list $refsyn * *]] + } else { + # last resort + set idx [lsearch $config [list -[string tolower $refsyn] * *]] + } + if { $idx == -1 } { + # fed up with "can't read classopt()" + return -code error "can't find option of synonym $opt" + } + } + set syn [lindex [lindex $config $idx] 0] + # JDC: used 4 (was 3) to get def from optiondb + set def [lindex [lindex $config $idx] 4] + lappend _tk_widget($tkwidget) [list $opt $syn $def] + } else { + # JDC: used 4 (was 3) to get def from optiondb + set def [lindex $optlist 4] + lappend _tk_widget($tkwidget) [list $opt $def] + set _optiondb($opt) [lindex $optlist 1] + set _optionclass($opt) [lindex $optlist 2] + } + } + } + return $_tk_widget($tkwidget) +} + + +# ---------------------------------------------------------------------------- +# Command Widget::_test_tkresource +# ---------------------------------------------------------------------------- +proc Widget::_test_tkresource { option value arg } { +# set tkwidget [lindex $arg 0] +# set realopt [lindex $arg 1] + foreach {tkwidget realopt} $arg break + set path ".#BWidget.#$tkwidget" + set old [$path cget $realopt] + $path configure $realopt $value + set res [$path cget $realopt] + $path configure $realopt $old + + return $res +} + + +# ---------------------------------------------------------------------------- +# Command Widget::_test_bwresource +# ---------------------------------------------------------------------------- +proc Widget::_test_bwresource { option value arg } { + return -code error "bad option type BwResource in widget" +} + + +# ---------------------------------------------------------------------------- +# Command Widget::_test_synonym +# ---------------------------------------------------------------------------- +proc Widget::_test_synonym { option value arg } { + return -code error "bad option type Synonym in widget" +} + +# ---------------------------------------------------------------------------- +# Command Widget::_test_color +# ---------------------------------------------------------------------------- +proc Widget::_test_color { option value arg } { + if {[catch {winfo rgb . $value} color]} { + return -code error "bad $option value \"$value\": must be a colorname \ + or #RRGGBB triplet" + } + + return $value +} + + +# ---------------------------------------------------------------------------- +# Command Widget::_test_string +# ---------------------------------------------------------------------------- +proc Widget::_test_string { option value arg } { + set value +} + + +# ---------------------------------------------------------------------------- +# Command Widget::_test_flag +# ---------------------------------------------------------------------------- +proc Widget::_test_flag { option value arg } { + set len [string length $value] + set res "" + for {set i 0} {$i < $len} {incr i} { + set c [string index $value $i] + if { [string first $c $arg] == -1 } { + return -code error "bad [string range $option 1 end] value \"$value\": characters must be in \"$arg\"" + } + if { [string first $c $res] == -1 } { + append res $c + } + } + return $res +} + + +# ----------------------------------------------------------------------------- +# Command Widget::_test_enum +# ----------------------------------------------------------------------------- +proc Widget::_test_enum { option value arg } { + if { [lsearch $arg $value] == -1 } { + set last [lindex $arg end] + set sub [lreplace $arg end end] + if { [llength $sub] } { + set str "[join $sub ", "] or $last" + } else { + set str $last + } + return -code error "bad [string range $option 1 end] value \"$value\": must be $str" + } + return $value +} + + +# ----------------------------------------------------------------------------- +# Command Widget::_test_int +# ----------------------------------------------------------------------------- +proc Widget::_test_int { option value arg } { + if { ![string is int -strict $value] || \ + ([string length $arg] && \ + ![expr [string map [list %d $value] $arg]]) } { + return -code error "bad $option value\ + \"$value\": must be integer ($arg)" + } + return $value +} + + +# ----------------------------------------------------------------------------- +# Command Widget::_test_boolean +# ----------------------------------------------------------------------------- +proc Widget::_test_boolean { option value arg } { + if { ![string is boolean -strict $value] } { + return -code error "bad $option value \"$value\": must be boolean" + } + + # Get the canonical form of the boolean value (1 for true, 0 for false) + return [string is true $value] +} + + +# ----------------------------------------------------------------------------- +# Command Widget::_test_padding +# ----------------------------------------------------------------------------- +proc Widget::_test_padding { option values arg } { + set len [llength $values] + if {$len < 1 || $len > 2} { + return -code error "bad pad value \"$values\":\ + must be positive screen distance" + } + + foreach value $values { + if { ![string is int -strict $value] || \ + ([string length $arg] && \ + ![expr [string map [list %d $value] $arg]]) } { + return -code error "bad pad value \"$value\":\ + must be positive screen distance ($arg)" + } + } + return $values +} + + +# Widget::_get_padding -- +# +# Return the requesting padding value for a padding option. +# +# Arguments: +# path Widget to get the options for. +# option The name of the padding option. +# index The index of the padding. If the index is empty, +# the first padding value is returned. +# +# Results: +# Return a numeric value that can be used for padding. +proc Widget::_get_padding { path option {index 0} } { + set pad [Widget::cget $path $option] + set val [lindex $pad $index] + if {$val == ""} { set val [lindex $pad 0] } + return $val +} + + +# ----------------------------------------------------------------------------- +# Command Widget::focusNext +# Same as tk_focusNext, but call Widget::focusOK +# ----------------------------------------------------------------------------- +proc Widget::focusNext { w } { + set cur $w + while 1 { + + # Descend to just before the first child of the current widget. + + set parent $cur + set children [winfo children $cur] + set i -1 + + # Look for the next sibling that isn't a top-level. + + while 1 { + incr i + if {$i < [llength $children]} { + set cur [lindex $children $i] + if {[string equal [winfo toplevel $cur] $cur]} { + continue + } else { + break + } + } + + # No more siblings, so go to the current widget's parent. + # If it's a top-level, break out of the loop, otherwise + # look for its next sibling. + + set cur $parent + if {[string equal [winfo toplevel $cur] $cur]} { + break + } + set parent [winfo parent $parent] + set children [winfo children $parent] + set i [lsearch -exact $children $cur] + } + if {[string equal $cur $w] || [focusOK $cur]} { + return $cur + } + } +} + + +# ----------------------------------------------------------------------------- +# Command Widget::focusPrev +# Same as tk_focusPrev, except: +# + Don't traverse from a child to a direct ancestor +# + Call Widget::focusOK instead of tk::focusOK +# ----------------------------------------------------------------------------- +proc Widget::focusPrev { w } { + set cur $w + set origParent [winfo parent $w] + while 1 { + + # Collect information about the current window's position + # among its siblings. Also, if the window is a top-level, + # then reposition to just after the last child of the window. + + if {[string equal [winfo toplevel $cur] $cur]} { + set parent $cur + set children [winfo children $cur] + set i [llength $children] + } else { + set parent [winfo parent $cur] + set children [winfo children $parent] + set i [lsearch -exact $children $cur] + } + + # Go to the previous sibling, then descend to its last descendant + # (highest in stacking order. While doing this, ignore top-levels + # and their descendants. When we run out of descendants, go up + # one level to the parent. + + while {$i > 0} { + incr i -1 + set cur [lindex $children $i] + if {[string equal [winfo toplevel $cur] $cur]} { + continue + } + set parent $cur + set children [winfo children $parent] + set i [llength $children] + } + set cur $parent + if {[string equal $cur $w]} { + return $cur + } + # If we are just at the original parent of $w, skip it as a + # potential focus accepter. Extra safety in this is to see if + # that parent is also a proc (not a C command), which is what + # BWidgets makes for any megawidget. Could possibly also check + # for '[info commands ::${origParent}:cmd] != ""'. [Bug 765667] + if {[string equal $cur $origParent] + && [info procs ::$origParent] != ""} { + continue + } + if {[focusOK $cur]} { + return $cur + } + } +} + + +# ---------------------------------------------------------------------------- +# Command Widget::focusOK +# Same as tk_focusOK, but handles -editable option and whole tags list. +# ---------------------------------------------------------------------------- +proc Widget::focusOK { w } { + set code [catch {$w cget -takefocus} value] + if { $code == 1 } { + return 0 + } + if {($code == 0) && ($value != "")} { + if {$value == 0} { + return 0 + } elseif {$value == 1} { + return [winfo viewable $w] + } else { + set value [uplevel \#0 $value $w] + if {$value != ""} { + return $value + } + } + } + if {![winfo viewable $w]} { + return 0 + } + set code [catch {$w cget -state} value] + if {($code == 0) && ($value == "disabled")} { + return 0 + } + set code [catch {$w cget -editable} value] + if {($code == 0) && ($value == 0)} { + return 0 + } + + set top [winfo toplevel $w] + foreach tags [bindtags $w] { + if { ![string equal $tags $top] && + ![string equal $tags "all"] && + [regexp Key [bind $tags]] } { + return 1 + } + } + return 0 +} + + +proc Widget::traverseTo { w } { + set focus [focus] + if {![string equal $focus ""]} { + event generate $focus <<TraverseOut>> + } + focus $w + + event generate $w <<TraverseIn>> +} + + +# Widget::varForOption -- +# +# Retrieve a fully qualified variable name for the option specified. +# If the option is not one for which a variable exists, throw an error +# (ie, those options that map directly to widget options). +# +# Arguments: +# path megawidget to get an option var for. +# option option to get a var for. +# +# Results: +# varname name of the variable, fully qualified, suitable for tracing. + +proc Widget::varForOption {path option} { + variable _class + variable _optiontype + + set class $_class($path) + upvar 0 ${class}::$path:opt pathopt + + if { ![info exists pathopt($option)] } { + error "unable to find variable for option \"$option\"" + } + set varname "::Widget::${class}::$path:opt($option)" + return $varname +} + +# Widget::getVariable -- +# +# Get a variable from within the namespace of the widget. +# +# Arguments: +# path Megawidget to get the variable for. +# varName The variable name to retrieve. +# newVarName The variable name to refer to in the calling proc. +# +# Results: +# Creates a reference to newVarName in the calling proc. +proc Widget::getVariable { path varName {newVarName ""} } { + variable _class + set class $_class($path) + if {![string length $newVarName]} { set newVarName $varName } + uplevel 1 [list upvar \#0 ${class}::$path:$varName $newVarName] +} + +# Widget::options -- +# +# Return a key-value list of options for a widget. This can +# be used to serialize the options of a widget and pass them +# on to a new widget with the same options. +# +# Arguments: +# path Widget to get the options for. +# args A list of options. If empty, all options are returned. +# +# Results: +# Returns list of options as: -option value -option value ... +proc Widget::options { path args } { + if {[llength $args]} { + foreach option $args { + lappend options [_get_configure $path $option] + } + } else { + set options [_get_configure $path {}] + } + + set result [list] + foreach list $options { + if {[llength $list] < 5} { continue } + lappend result [lindex $list 0] [lindex $list end] + } + return $result +} + + +# Widget::getOption -- +# +# Given a list of widgets, determine which option value to use. +# The widgets are given to the command in order of highest to +# lowest. Starting with the lowest widget, whichever one does +# not match the default option value is returned as the value. +# If all the widgets are default, we return the highest widget's +# value. +# +# Arguments: +# option The option to check. +# default The default value. If any widget in the list +# does not match this default, its value is used. +# args A list of widgets. +# +# Results: +# Returns the value of the given option to use. +# +proc Widget::getOption { option default args } { + for {set i [expr [llength $args] -1]} {$i >= 0} {incr i -1} { + set widget [lindex $args $i] + set value [Widget::cget $widget $option] + if {[string equal $value $default]} { continue } + return $value + } + return $value +} + + +proc Widget::nextIndex { path node } { + Widget::getVariable $path autoIndex + if {![info exists autoIndex]} { set autoIndex -1 } + return [string map [list #auto [incr autoIndex]] $node] +} + + +proc Widget::exists { path } { + variable _class + return [info exists _class($path)] +} + +proc Widget::theme {{bool {}}} { + # Private, *experimental* API that may change at any time - JH + variable _theme + if {[llength [info level 0]] == 2} { + # set theme-ability + if {[catch {package require Tk 8.5a6}] + && [catch {package require tile 0.6}] + && [catch {package require tile 1}]} { + return -code error "BWidget's theming requires tile 0.6+" + } else { + catch {style default BWSlim.Toolbutton -padding 0} + } + set _theme [string is true -strict $bool] + } + return $_theme +} diff --git a/modules/tclsci/tcl/BWidget/wizard.tcl b/modules/tclsci/tcl/BWidget/wizard.tcl new file mode 100755 index 000000000..b2fe80d90 --- /dev/null +++ b/modules/tclsci/tcl/BWidget/wizard.tcl @@ -0,0 +1,1028 @@ +# ------------------------------------------------------------------------------ +# wizard.tcl +# +# ------------------------------------------------------------------------------ +# Index of commands: +# +# Public commands +# - Wizard::create +# - Wizard::configure +# - Wizard::cget +# +# Private commands (event bindings) +# - Wizard::_destroy +# ------------------------------------------------------------------------------ + +namespace eval Wizard { + Widget::define Wizard wizard ButtonBox Separator PagesManager + + namespace eval Step { + Widget::declare Wizard::Step { + {-type String "step" 1 } + {-data String "" 0 } + {-title String "" 0 } + {-default String "next" 0 } + {-text1 String "" 0 } + {-text2 String "" 0 } + {-text3 String "" 0 } + {-text4 String "" 0 } + {-text5 String "" 0 } + {-icon String "" 0 } + {-image String "" 0 } + {-bitmap String "" 0 } + {-iconbitmap String "" 0 } + + {-create Boolean "0" 1 } + {-appendorder Boolean "1" 0 } + + {-nexttext String "Next >" 0 } + {-backtext String "< Back" 0 } + {-helptext String "Help" 0 } + {-canceltext String "Cancel" 0 } + {-finishtext String "Finish" 0 } + {-separatortext String "" 0 } + + {-createcommand String "" 0 } + {-raisecommand String "" 0 } + {-nextcommand String "" 0 } + {-backcommand String "" 0 } + {-helpcommand String "" 0 } + {-cancelcommand String "" 0 } + {-finishcommand String "" 0 } + + } + } + + namespace eval Branch { + Widget::declare Wizard::Branch { + {-type String "branch" 1 } + {-command String "" 0 } + {-action Enum "merge" 0 {merge terminate} } + } + } + + namespace eval Widget { + Widget::declare Wizard::Widget { + {-type String "widget" 1 } + {-step String "" 1 } + {-widget String "" 1 } + } + } + + namespace eval layout {} + + Widget::tkinclude Wizard frame :cmd \ + include { -width -height -background -foreground -cursor } + + Widget::declare Wizard { + {-type Enum "dialog" 1 {dialog frame} } + {-width TkResource "450" 0 frame} + {-height TkResource "300" 0 frame} + {-relief TkResource "flat" 0 frame} + {-borderwidth TkResource "0" 0 frame} + {-background TkResource "" 0 frame} + {-foreground String "black" 0 } + {-title String "Wizard" 0 } + + {-autobuttons Boolean "1" 0 } + {-helpbutton Boolean "0" 1 } + {-finishbutton Boolean "0" 1 } + {-resizable String "0 0" 0 } + {-separator Boolean "1" 1 } + {-parent String "." 1 } + {-transient Boolean "1" 1 } + {-place Enum "center" 1 + {none center left right above below}} + + {-icon String "" 0 } + {-image String "" 0 } + {-bitmap String "" 0 } + {-iconbitmap String "" 0 } + {-raisecommand String "" 0 } + {-createcommand String "" 0 } + {-separatortext String "" 0 } + + {-fg Synonym -foreground } + {-bg Synonym -background } + {-bd Synonym -borderwidth } + } + + image create photo Wizard::none + + Widget::addmap Wizard "" :cmd { -background {} -relief {} -borderwidth {} } + + Widget::addmap Wizard "" .steps { -width {} -height {} } + + bind Wizard <Destroy> [list Wizard::_destroy %W] +} + + +# ------------------------------------------------------------------------------ +# Command Wizard::create +# ------------------------------------------------------------------------------ +proc Wizard::create { path args } { + array set maps [list Wizard {} :cmd {}] + array set maps [Widget::parseArgs Wizard $args] + + Widget::initFromODB Wizard $path $maps(Wizard) + + Widget::getVariable $path data + Widget::getVariable $path branches + + array set data { + steps "" + buttons "" + order "" + current "" + } + + array set branches { + root "" + } + + set frame $path + + set type [Widget::cget $path -type] + + if {[string equal $type "dialog"]} { + set top $path + eval [list toplevel $path] $maps(:cmd) -class Wizard + wm withdraw $path + wm protocol $path WM_DELETE_WINDOW [list $path cancel] + if {[Widget::cget $path -transient]} { + wm transient $path [Widget::cget $path -parent] + } + eval wm resizable $path [Widget::cget $path -resizable] + + bind $path <Escape> [list $path cancel] + bind $path <<WizardFinish>> [list destroy $path] + bind $path <<WizardCancel>> [list destroy $path] + } else { + set top [winfo toplevel $path] + eval [list frame $path] $maps(:cmd) -class Wizard + } + + wm title $top [Widget::cget $path -title] + + PagesManager $path.steps + pack $path.steps -expand 1 -fill both + + widgets $path set steps -widget $path.steps + + if {[Widget::cget $path -separator]} { + frame $path.separator + pack $path.separator -fill x + + label $path.separator.l -text [Widget::cget $path -separatortext] + pack $path.separator.l -side left + + Separator $path.separator.s -orient horizontal + pack $path.separator.s -side left -expand 1 -fill x -pady 2 + + widgets $path set separator -widget $path.separator.s + widgets $path set separatortext -widget $path.separator.l + widgets $path set separatorframe -widget $path.separator + } + + ButtonBox $path.buttons -spacing 2 -homogeneous 1 + pack $path.buttons -anchor se -padx 10 -pady 5 + + widgets $path set buttons -widget $path.buttons + + insert $path button end back -text "< Back" -command "$path back" -width 12 + insert $path button end next -text "Next >" -command "$path next" + if {[Widget::cget $path -finishbutton]} { + insert $path button end finish -text "Finish" -command "$path finish" + } + insert $path button end cancel -text "Cancel" -command "$path cancel" + + if {[Widget::cget $path -helpbutton]} { + $path.buttons configure -spacing 10 + insert $path button 0 help -text "Help" -command "$path help" + $path.buttons configure -spacing 2 + } + + return [Widget::create Wizard $path] +} + + +# ------------------------------------------------------------------------------ +# Command Wizard::configure +# ------------------------------------------------------------------------------ +proc Wizard::configure { path args } { + set res [Widget::configure $path $args] + + if {[Widget::hasChanged $path -title title]} { + wm title [winfo toplevel $path] $title + } + + if {[Widget::hasChanged $path -resizable resize]} { + eval wm resizable [winfo toplevel $path] $resize + } + + return $res +} + + +# ------------------------------------------------------------------------------ +# Command Wizard::cget +# ------------------------------------------------------------------------------ +proc Wizard::cget { path option } { + return [Widget::cget $path $option] +} + + +proc Wizard::itemcget { path item option } { + Widget::getVariable $path items + Widget::getVariable $path steps + Widget::getVariable $path buttons + Widget::getVariable $path widgets + + if {![exists $path $item]} { + ## It's not an item. Just pass the configure to the widget. + set item [$path widgets get $item] + return [eval $item configure $args] + } + + if {[_is_step $path $item]} { + ## It's a step + return [Widget::cget $items($item) $option] + } + + if {[_is_branch $path $item]} { + ## It's a branch + return [Widget::cget $items($item) $option] + } + + if {[info exists buttons($item)]} { + ## It's a button + return [$path.buttons itemcget $items($item) $option] + } + + return -code error "item \"$item\" does not exist" +} + + +proc Wizard::itemconfigure { path item args } { + Widget::getVariable $path items + Widget::getVariable $path steps + Widget::getVariable $path buttons + Widget::getVariable $path widgets + + if {![exists $path $item]} { + ## It's not an item. Just pass the configure to the widget. + set item [$path widgets get $item] + return [eval $item configure $args] + } + + if {[info exists steps($item)]} { + ## It's a step. + set res [Widget::configure $items($item) $args] + + if {$item == [$path step current]} { + if {[Widget::hasChanged $items($item) -title title]} { + wm title [winfo toplevel $path] $title + } + } + + return $res + } + + if {[_is_branch $path $item]} { + ## It's a branch + return [Widget::configure $items($item) $args] + } + + if {[info exists buttons($item)]} { + ## It's a button. + return [eval $path.buttons itemconfigure [list $items($item)] $args] + } + + return -code error "item \"$item\" does not exist" +} + + +proc Wizard::show { path } { + wm deiconify [winfo toplevel $path] +} + + +proc Wizard::invoke { path button } { + Widget::getVariable $path buttons + if {![info exists buttons($button)]} { + return -code error "button \"$button\" does not exist" + } + [$path widgets get $button] invoke +} + + +proc Wizard::insert { path type idx args } { + Widget::getVariable $path items + Widget::getVariable $path widgets + Widget::getVariable $path branches + + switch -- $type { + "button" { + set node [lindex $args 0] + } + + "step" - "branch" { + set node [lindex $args 1] + set branch [lindex $args 0] + + if {![info exists branches($branch)]} { + return -code error "branch \"$branch\" does not exist" + } + } + + default { + set types [list button branch step] + set err [BWidget::badOptionString option $type $types] + return -code error $err + } + } + + if {[exists $path $node]} { + return -code error "item \"$node\" already exists" + } + + eval _insert_$type $path $idx $args +} + + +proc Wizard::back { path } { + Widget::getVariable $path data + Widget::getVariable $path items + set step [$path raise] + if {![string equal $step ""]} { + set cmd [Widget::cget $items($step) -backcommand] + if {![string equal $cmd ""]} { + set res [uplevel #0 $cmd] + if {!$res} { return } + } + } + + set data(order) [lreplace $data(order) end end] + set item [lindex $data(order) end] + + $path raise $item + + event generate $path <<WizardStep>> + event generate $path <<WizardBack>> + + return $item +} + + +proc Wizard::next { path } { + Widget::getVariable $path data + Widget::getVariable $path items + + set step [$path raise] + if {![string equal $step ""]} { + set cmd [Widget::cget $items($step) -nextcommand] + if {![string equal $cmd ""]} { + set res [uplevel #0 $cmd] + if {!$res} { return } + } + } + + set item [step $path next] + + if {[Widget::cget $items($item) -appendorder]} { + lappend data(order) $item + } + + $path raise $item + + event generate $path <<WizardStep>> + event generate $path <<WizardNext>> + + return $item +} + + +proc Wizard::cancel { path } { + Widget::getVariable $path items + set step [$path raise] + if {![string equal $step ""]} { + set cmd [Widget::cget $items($step) -cancelcommand] + if {![string equal $cmd ""]} { + set res [uplevel #0 $cmd] + if {!$res} { return } + } + } + + event generate $path <<WizardCancel>> +} + + +proc Wizard::finish { path } { + Widget::getVariable $path items + set step [$path raise] + if {![string equal $step ""]} { + set cmd [Widget::cget $items($step) -finishcommand] + if {![string equal $cmd ""]} { + set res [uplevel #0 $cmd] + if {!$res} { return } + } + } + + event generate $path <<WizardFinish>> +} + + +proc Wizard::help { path } { + Widget::getVariable $path items + set step [$path raise] + if {![string equal $step ""]} { + set cmd [Widget::cget $items($step) -helpcommand] + if {![string equal $cmd ""]} { + uplevel #0 $cmd + } + } + + event generate $path <<WizardHelp>> +} + + +proc Wizard::step { path node {start ""} {traverse 1} } { + Widget::getVariable $path data + Widget::getVariable $path items + Widget::getVariable $path branches + + if {![string equal $start ""]} { + if {![exists $path $start]} { + return -code error "item \"$start\" does not exist" + } + } + + switch -- $node { + "current" { + set item [$path raise] + } + + "end" - "last" { + ## Keep looping through 'next' until we hit the end. + set item [$path step next] + while {![string equal $item ""]} { + set last $item + set item [$path step next $item] + } + set item $last + } + + "back" - "previous" { + if {[string equal $start ""]} { + set item [lindex $data(order) end-1] + } else { + set idx [lsearch $data(order) $start] + incr idx -1 + if {$idx < 0} { return } + set item [lindex $data(order) $idx] + } + } + + "next" { + set step [$path raise] + if {![string equal $start ""]} { set step $start } + + set branch [$path branch $step] + if {$traverse && [_is_branch $path $step]} { + ## This step is a branch. Let's figure out where to go next. + if {[traverse $path $step]} { + ## It's ok to traverse into this branch. + ## Set step to null so that we'll end up finding the + ## first step in the branch. + set branch $step + set step "" + } + } + + set idx [lsearch $branches($branch) $step] + incr idx + + set item [lindex $branches($branch) $idx] + + if {$idx >= [llength $branches($branch)]} { + ## We've reached the end of this branch. + ## If it's the root branch, or this branch terminates we return. + if {[string equal $branch "root"] + || [Widget::cget $items($branch) -action] == "terminate"} { + return + } + + ## We want to merge back with our parent branch. + set item [step $path next $branch 0] + } + + ## If this step is a branch, find the next step after it. + if {$traverse && [_is_branch $path $item]} { + set item [$path step next $item] + } + } + + default { + if {![exists $path $node]} { + return -code error "item \"$node\" does not exist" + } + set item $node + } + } + + return $item +} + + +proc Wizard::nodes { path branch {first ""} {last ""} } { + Widget::getVariable $path data + Widget::getVariable $path branches + if {$first == ""} { return $branches($branch) } + if {$last == ""} { return [lindex $branches($branch) $first] } + return [lrange $data(steps) $first $last] +} + + +proc Wizard::index { path item } { + Widget::getVariable $path branches + set branch [$path branch $item] + return [lsearch $branches($branch) $item] +} + + +proc Wizard::raise { path {item ""} } { + Widget::getVariable $path data + Widget::getVariable $path items + + set steps $path.steps + set buttons $path.buttons + + if {[string equal $item ""]} { return $data(current) } + + $path createStep $item + + ## Eval the global raisecommand if we have one, appending the item. + set cmd [Widget::cget $path -raisecommand] + if {![string equal $cmd ""]} { + uplevel #0 $cmd [list $item] + } + + ## Eval this item's raisecommand if we have one. + set cmd [Widget::cget $items($item) -raisecommand] + if {![string equal $cmd ""]} { + uplevel #0 $cmd + } + + set title [getoption $path $item -title] + wm title [winfo toplevel $path] $title + + if {[Widget::cget $path -separator]} { + set txt [getoption $path $item -separatortext] + $path itemconfigure separatortext -text $txt + } + + set default [Widget::cget $items($item) -default] + set button [lsearch $data(buttons) $default] + $buttons setfocus $button + + $steps raise $item + + set data(current) $item + + set back [$path step back] + set next [$path step next] + + if {[Widget::cget $path -autobuttons]} { + set txt [Widget::cget $items($item) -backtext] + $path itemconfigure back -text $txt -state normal + set txt [Widget::cget $items($item) -nexttext] + $path itemconfigure next -text $txt -state normal + set txt [Widget::cget $items($item) -canceltext] + $path itemconfigure cancel -text $txt -state normal + if {[Widget::cget $path -helpbutton]} { + set txt [Widget::cget $items($item) -helptext] + $path itemconfigure help -text $txt + } + + if {[Widget::cget $path -finishbutton]} { + set txt [Widget::cget $items($item) -finishtext] + $path itemconfigure finish -text $txt -state disabled + } + + if {[string equal $back ""]} { + $path itemconfigure back -state disabled + } + + if {[string equal $next ""]} { + if {[Widget::cget $path -finishbutton]} { + $path itemconfigure next -state disabled + $path itemconfigure finish -state normal + } else { + set txt [Widget::cget $items($item) -finishtext] + $path itemconfigure next -text $txt -command [list $path finish] + } + $path itemconfigure back -state disabled + $path itemconfigure cancel -state disabled + } else { + set txt [Widget::cget $items($item) -nexttext] + $path itemconfigure next -text $txt -command [list $path next] + } + } + + event generate $path <<WizardStep>> + + if {[string equal $next ""]} { event generate $path <<WizardLastStep>> } + if {[string equal $back ""]} { event generate $path <<WizardFirstStep>> } + + return $item +} + + +proc Wizard::widgets { path command args } { + Widget::getVariable $path items + Widget::getVariable $path widgets + Widget::getVariable $path stepWidgets + + switch -- $command { + "set" { + set node [lindex $args 0] + if {[string equal $node ""]} { + set err [BWidget::wrongNumArgsString \ + "$path widgets set <name> ?option ..?"] + return -code error $err + } + set args [lreplace $args 0 0] + set item $path.#widget#$node + + Widget::init Wizard::Widget $item $args + set step [Widget::cget $item -step] + set widget [Widget::cget $item -widget] + if {[string equal $step ""]} { + set widgets($node) $widget + } else { + set stepWidgets($step,$node) $widget + } + return $widget + } + + "get" { + set node [lindex $args 0] + if {[string equal $node ""]} { + return [array names widgets] + } + set args [lreplace $args 0 0] + + array set map [list Wizard::Widget {}] + array set map [Widget::parseArgs Wizard::Widget $args] + array set data $map(Wizard::Widget) + + if {[info exists data(-step)]} { + set step $data(-step) + } else { + set step [$path step current] + } + + ## If a widget exists for this step, return it. + if {[info exists stepWidgets($step,$node)]} { + return $stepWidgets($step,$node) + } + + ## See if a widget exists on the global level. + if {![info exists widgets($node)]} { + return -code error "item \"$node\" does not exist" + } + return $widgets($node) + } + + default { + set err [BWidget::badOptionString option $command [list get set]] + return -code error $err + } + } +} + + +proc Wizard::variable { path step option } { + set item $path.$step + return [Widget::varForOption $item $option] +} + + +proc Wizard::branch { path {node "current"} } { + Widget::getVariable $path data + if {[string equal $node "current"]} { set item [$path step current] } + if {[string equal $node ""]} { return "root" } + if {[info exists data($node,branch)]} { return $data($node,branch) } + return -code error "item \"$node\" does not exist" +} + + +proc Wizard::traverse { path node } { + Widget::getVariable $path items + + if {$node == "root"} { return 1 } + + if {![_is_branch $path $node]} { + return -code error "branch \"$node\" does not exist" + } + + set cmd [Widget::cget $items($node) -command] + if {[string equal $cmd ""]} { return 1 } + return [uplevel #0 $cmd] +} + + +proc Wizard::exists { path item } { + Widget::getVariable $path items + return [info exists items($item)] +} + + +proc Wizard::createStep { path item {delete 0} } { + Widget::getVariable $path data + Widget::getVariable $path items + Widget::getVariable $path steps + + if {![_is_step $path $item]} { return } + + if {$delete} { + if {[$path.steps exists $item]} { + $path.steps delete $item + } + if {[info exists data($item,realized)]} { + unset data($item,realized) + } + } + + if {![info exists data($item,realized)]} { + ## Eval the global createcommand if we have one, appending the item. + set cmd [Widget::cget $path -createcommand] + if {![string equal $cmd ""]} { + uplevel #0 $cmd [list $item] + } + + ## Eval this item's createcommand if we have one. + set cmd [Widget::cget $items($item) -createcommand] + if {![string equal $cmd ""]} { + uplevel #0 $cmd + } + + set data($item,realized) 1 + } + + return +} + + +proc Wizard::getoption { path item option } { + Widget::getVariable $path items + return [Widget::getOption $option "" $path $items($item)] +} + + +proc Wizard::reorder { path parent nodes } { + Widget::getVariable $path branches + set branches($parent) $nodes +} + + +proc Wizard::_insert_button { path idx node args } { + Widget::getVariable $path data + Widget::getVariable $path items + Widget::getVariable $path buttons + Widget::getVariable $path widgets + + set buttons($node) 1 + set widgets($node) [eval $path.buttons insert $idx $args] + set item [string map [list $path.buttons.b {}] $widgets($node)] + set items($node) $item + return $widgets($node) +} + + +proc Wizard::_insert_step { path idx branch node args } { + Widget::getVariable $path data + Widget::getVariable $path steps + Widget::getVariable $path items + Widget::getVariable $path widgets + Widget::getVariable $path branches + + set steps($node) 1 + lappend data(steps) $node + set data($node,branch) $branch + if {$idx == "end"} { + lappend branches($branch) $node + } else { + set branches($branch) [linsert $branches($branch) $idx $node] + } + + set items($node) $path.$node + Widget::init Wizard::Step $items($node) $args + set widgets($node) [$path.steps add $node] + if {[Widget::cget $items($node) -create]} { $path createStep $node } + return $widgets($node) +} + + +proc Wizard::_insert_branch { path idx branch node args } { + Widget::getVariable $path data + Widget::getVariable $path items + Widget::getVariable $path branches + + set branches($node) [list] + lappend data(branches) $node + set data($node,branch) $branch + if {$idx == "end"} { + lappend branches($branch) $node + } else { + set branches($branch) [linsert $branches($branch) $idx $node] + } + + set items($node) $path.$node + Widget::init Wizard::Branch $items($node) $args +} + + +proc Wizard::_is_step { path node } { + Widget::getVariable $path steps + return [info exists steps($node)] +} + + +proc Wizard::_is_branch { path node } { + Widget::getVariable $path branches + return [info exists branches($node)] +} + + +# ------------------------------------------------------------------------------ +# Command Wizard::_destroy +# ------------------------------------------------------------------------------ +proc Wizard::_destroy { path } { + Widget::destroy $path +} + + +proc SimpleWizard { path args } { + option add *WizLayoutSimple*Label.padX 5 interactive + option add *WizLayoutSimple*Label.anchor nw interactive + option add *WizLayoutSimple*Label.justify left interactive + option add *WizLayoutSimple*Label.borderWidth 0 interactive + option add *WizLayoutSimple*Label.highlightThickness 0 interactive + + set cmd [list Wizard::layout::simple $path] + return [eval [list Wizard $path] $args [list -createcommand $cmd]] +} + + +proc ClassicWizard { path args } { + option add *WizLayoutClassic*Label.padX 5 interactive + option add *WizLayoutClassic*Label.anchor nw interactive + option add *WizLayoutClassic*Label.justify left interactive + option add *WizLayoutClassic*Label.borderWidth 0 interactive + option add *WizLayoutClassic*Label.highlightThickness 0 interactive + + set cmd [list Wizard::layout::classic $path] + return [eval [list Wizard $path] $args [list -createcommand $cmd]] +} + + +proc Wizard::layout::simple { wizard step } { + set frame [$wizard widgets get $step] + + set layout [$wizard widgets set layout -widget $frame.layout -step $step] + + foreach w [list titleframe pretext posttext clientArea] { + set $w [$wizard widgets set $w -widget $layout.$w -step $step] + } + + foreach w [list title subtitle icon] { + set $w [$wizard widgets set $w -widget $titleframe.$w -step $step] + } + + frame $layout -class WizLayoutSimple + + pack $layout -expand 1 -fill both + + # Client area. This is where the caller places its widgets. + frame $clientArea -bd 8 -relief flat + + Separator $layout.sep1 -relief groove -orient horizontal + + # title and subtitle and icon + frame $titleframe -bd 4 -relief flat -background white + label $title -background white -textvariable [$wizard variable $step -text1] + label $subtitle -height 2 -background white -padx 15 -width 40 \ + -textvariable [$wizard variable $step -text2] + + label $icon -borderwidth 0 -background white -anchor c + set iconImage [$wizard getoption $step -icon] + if {![string equal $iconImage ""]} { $icon configure -image $iconImage } + + set labelfont [font actual [$title cget -font]] + $title configure -font [concat $labelfont -weight bold] + + # put the title, subtitle and icon inside the frame we've built for them + grid $title -in $titleframe -row 0 -column 0 -sticky nsew + grid $subtitle -in $titleframe -row 1 -column 0 -sticky nsew + grid $icon -in $titleframe -row 0 -column 1 -rowspan 2 -padx 8 + grid columnconfigure $titleframe 0 -weight 1 + grid columnconfigure $titleframe 1 -weight 0 + + # pre and post text. + label $pretext -textvariable [$wizard variable $step -text3] + label $posttext -textvariable [$wizard variable $step -text4] + + # when our label widgets change size we want to reset the + # wraplength to that same size. + foreach widget {title subtitle pretext posttext} { + bind [set $widget] <Configure> { + # yeah, I know this looks weird having two after idle's, but + # it helps prevent the geometry manager getting into a tight + # loop under certain circumstances + # + # note that subtracting 10 is just a somewhat arbitrary number + # to provide a little padding... + after idle {after idle {%W configure -wraplength [expr {%w -10}]}} + } + } + + grid $titleframe -row 0 -column 0 -sticky nsew -padx 0 + grid $layout.sep1 -row 1 -sticky ew + grid $pretext -row 2 -sticky nsew -padx 8 -pady 8 + grid $clientArea -row 3 -sticky nsew -padx 8 -pady 8 + grid $posttext -row 4 -sticky nsew -padx 8 -pady 8 + + grid columnconfigure $layout 0 -weight 1 + grid rowconfigure $layout 0 -weight 0 + grid rowconfigure $layout 1 -weight 0 + grid rowconfigure $layout 2 -weight 0 + grid rowconfigure $layout 3 -weight 1 + grid rowconfigure $layout 4 -weight 0 +} + +proc Wizard::layout::classic { wizard step } { + set frame [$wizard widgets get $step] + + set layout [$wizard widgets set layout -widget $frame.layout -step $step] + foreach w [list title subtitle icon pretext posttext clientArea] { + set $w [$wizard widgets set $w -widget $layout.$w -step $step] + } + + frame $layout -class WizLayoutClassic + + pack $layout -expand 1 -fill both + + # Client area. This is where the caller places its widgets. + frame $clientArea -bd 8 -relief flat + + Separator $layout.sep1 -relief groove -orient vertical + + # title and subtitle + label $title -textvariable [$wizard variable $step -text1] + label $subtitle -textvariable [$wizard variable $step -text2] -height 2 + + array set labelfont [font actual [$title cget -font]] + incr labelfont(-size) 6 + set labelfont(-weight) bold + $title configure -font [array get labelfont] + + # pre and post text. + label $pretext -textvariable [$wizard variable $step -text3] + label $posttext -textvariable [$wizard variable $step -text4] + + # when our label widgets change size we want to reset the + # wraplength to that same size. + foreach widget {title subtitle pretext posttext} { + bind [set $widget] <Configure> { + # yeah, I know this looks weird having two after idle's, but + # it helps prevent the geometry manager getting into a tight + # loop under certain circumstances + # + # note that subtracting 10 is just a somewhat arbitrary number + # to provide a little padding... + after idle {after idle {%W configure -wraplength [expr {%w -10}]}} + } + } + + label $icon -borderwidth 1 -relief sunken -background white \ + -anchor c -width 96 -image Wizard::none + set iconImage [$wizard getoption $step -icon] + if {![string equal $iconImage ""]} { $icon configure -image $iconImage } + + grid $icon -row 0 -column 0 -sticky nsew -padx 8 -pady 8 -rowspan 5 + grid $title -row 0 -column 1 -sticky ew -padx 8 -pady 8 + grid $subtitle -row 1 -column 1 -sticky ew -padx 8 -pady 8 + grid $pretext -row 2 -column 1 -sticky ew -padx 8 + grid $clientArea -row 3 -column 1 -sticky nsew -padx 8 + grid $posttext -row 4 -column 1 -sticky ew -padx 8 -pady 24 + + grid columnconfigure $layout 0 -weight 0 + grid columnconfigure $layout 1 -weight 1 + + grid rowconfigure $layout 0 -weight 0 + grid rowconfigure $layout 1 -weight 0 + grid rowconfigure $layout 2 -weight 0 + grid rowconfigure $layout 3 -weight 1 + grid rowconfigure $layout 4 -weight 0 +} diff --git a/modules/tclsci/tcl/BWidget/xpm2image.tcl b/modules/tclsci/tcl/BWidget/xpm2image.tcl new file mode 100755 index 000000000..7df22c59b --- /dev/null +++ b/modules/tclsci/tcl/BWidget/xpm2image.tcl @@ -0,0 +1,115 @@ +# ---------------------------------------------------------------------------- +# xpm2image.tcl +# Slightly modified xpm-to-image command +# $Id: xpm2image.tcl,v 1.5 2004/09/09 22:17:03 hobbs Exp $ +# ------------------------------------------------------------------------------ +# +# Copyright 1996 by Roger E. Critchlow Jr., San Francisco, California +# All rights reserved, fair use permitted, caveat emptor. +# rec@elf.org +# +# ---------------------------------------------------------------------------- + +proc xpm-to-image { file } { + set f [open $file] + set string [read $f] + close $f + + # + # parse the strings in the xpm data + # + set xpm {} + foreach line [split $string "\n"] { + if {[regexp {^"([^\"]*)"} $line all meat]} { + if {[string first XPMEXT $meat] == 0} { + break + } + lappend xpm $meat + } + } + # + # extract the sizes in the xpm data + # + set sizes [lindex $xpm 0] + set nsizes [llength $sizes] + if { $nsizes == 4 || $nsizes == 6 || $nsizes == 7 } { + set data(width) [lindex $sizes 0] + set data(height) [lindex $sizes 1] + set data(ncolors) [lindex $sizes 2] + set data(chars_per_pixel) [lindex $sizes 3] + set data(x_hotspot) 0 + set data(y_hotspot) 0 + if {[llength $sizes] >= 6} { + set data(x_hotspot) [lindex $sizes 4] + set data(y_hotspot) [lindex $sizes 5] + } + } else { + error "size line {$sizes} in $file did not compute" + } + + # + # extract the color definitions in the xpm data + # + foreach line [lrange $xpm 1 $data(ncolors)] { + set colors [split $line \t] + set cname [lindex $colors 0] + lappend data(cnames) $cname + if { [string length $cname] != $data(chars_per_pixel) } { + error "color definition {$line} in file $file has a bad size color name" + } + foreach record [lrange $colors 1 end] { + set key [lindex $record 0] + set color [string tolower [join [lrange $record 1 end] { }]] + set data(color-$key-$cname) $color + if { [string equal -nocase $color "none"] } { + set data(transparent) $cname + } + } + foreach key {c g g4 m} { + if {[info exists data(color-$key-$cname)]} { + set color $data(color-$key-$cname) + set data(color-$cname) $color + set data(cname-$color) $cname + lappend data(colors) $color + break + } + } + if { ![info exists data(color-$cname)] } { + error "color definition {$line} in $file failed to define a color" + } + } + + # + # extract the image data in the xpm data + # + set image [image create photo -width $data(width) -height $data(height)] + set y 0 + foreach line [lrange $xpm [expr {1+$data(ncolors)}] [expr {1+$data(ncolors)+$data(height)}]] { + set x 0 + set pixels {} + while { [string length $line] > 0 } { + set pixel [string range $line 0 [expr {$data(chars_per_pixel)-1}]] + set c $data(color-$pixel) + if { [string equal $c none] } { + if { [string length $pixels] } { + $image put [list $pixels] -to [expr {$x-[llength $pixels]}] $y + set pixels {} + } + } else { + lappend pixels $c + } + set line [string range $line $data(chars_per_pixel) end] + incr x + } + if { [llength $pixels] } { + $image put [list $pixels] -to [expr {$x-[llength $pixels]}] $y + } + incr y + } + + # + # return the image + # + return $image +} + |