|
@@ -0,0 +1,972 @@
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# widget.tcl
|
|
|
+# This file is part of Unifix BWidget Toolkit
|
|
|
+# $Id$
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# 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::_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
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+
|
|
|
+namespace eval Widget {
|
|
|
+ variable _optiontype
|
|
|
+ variable _class
|
|
|
+ variable _tk_widget
|
|
|
+
|
|
|
+ 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
|
|
|
+ }
|
|
|
+
|
|
|
+ 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 = {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
|
|
|
+
|
|
|
+ # 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]]
|
|
|
+ lappend classmap($option) $subpath "" $realopt
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# 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 ${subclass}::opt subclassopt
|
|
|
+
|
|
|
+ # create resources informations from BWidget resources
|
|
|
+ foreach {option optdesc} [array get subclassopt] {
|
|
|
+ if { (![info exists include] || [info exists include($option)]) &&
|
|
|
+ ![info exists remove($option)] } {
|
|
|
+ set type [lindex $optdesc 0]
|
|
|
+ if { ![string compare $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]]
|
|
|
+ lappend classmap($option) $subpath $subclass $realopt
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# Command Widget::declare
|
|
|
+# Declares new options to BWidget class.
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+proc Widget::declare { class optlist } {
|
|
|
+ variable _optiontype
|
|
|
+
|
|
|
+ namespace eval $class {}
|
|
|
+ upvar 0 ${class}::opt classopt
|
|
|
+
|
|
|
+ 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 compare $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 compare $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 classopt($option) [list $type $value $ro $arg]
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ # retreive default value for TkResource
|
|
|
+ if { ![string compare $type "TkResource"] } {
|
|
|
+ set tkwidget [lindex $arg 0]
|
|
|
+ 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 value [lindex [lindex $tkoptions [lsearch $tkoptions [list $realopt *]]] end]
|
|
|
+ }
|
|
|
+ set classopt($option) [list TkResource $value $ro [list $tkwidget $realopt]]
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ # for any other resource type, we keep original optdesc
|
|
|
+ set classopt($option) [list $type $value $ro $arg]
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# Command Widget::addmap
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+proc Widget::addmap { class subclass subpath options } {
|
|
|
+ upvar 0 ${class}::map classmap
|
|
|
+
|
|
|
+ foreach {option realopt} $options {
|
|
|
+ if { ![string length $realopt] } {
|
|
|
+ set realopt $option
|
|
|
+ }
|
|
|
+ lappend classmap($option) $subpath $subclass $realopt
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# 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 _class
|
|
|
+ variable _optiontype
|
|
|
+
|
|
|
+ upvar 0 ${class}::opt classopt
|
|
|
+ upvar 0 ${class}::map classmap
|
|
|
+ upvar 0 ${class}::$path:opt pathopt
|
|
|
+ upvar 0 ${class}::$path:mod pathmod
|
|
|
+
|
|
|
+ catch {unset pathopt}
|
|
|
+ catch {unset pathmod}
|
|
|
+ set fpath ".#BWidgetClass#$class"
|
|
|
+ regsub -all "::" $class "" rdbclass
|
|
|
+ if { ![winfo exists $fpath] } {
|
|
|
+ frame $fpath -class $rdbclass
|
|
|
+ }
|
|
|
+ foreach {option optdesc} [array get classopt] {
|
|
|
+ set type [lindex $optdesc 0]
|
|
|
+ if { ![string compare $type "Synonym"] } {
|
|
|
+ set option [lindex $optdesc 1]
|
|
|
+ set optdesc $classopt($option)
|
|
|
+ set type [lindex $optdesc 0]
|
|
|
+ }
|
|
|
+ if { ![string compare $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]
|
|
|
+ }
|
|
|
+ set pathmod($option) 0
|
|
|
+ }
|
|
|
+
|
|
|
+ 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 compare $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]]
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# Command Widget::destroy
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+proc Widget::destroy { path } {
|
|
|
+ variable _class
|
|
|
+
|
|
|
+ set class $_class($path)
|
|
|
+ upvar 0 ${class}::$path:opt pathopt
|
|
|
+ upvar 0 ${class}::$path:mod pathmod
|
|
|
+
|
|
|
+ catch {unset pathopt}
|
|
|
+ catch {unset pathmod}
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# 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 compare $type "Synonym"] } {
|
|
|
+ set option [lindex $optdesc 1]
|
|
|
+ set optdesc $classopt($option)
|
|
|
+ set type [lindex $optdesc 0]
|
|
|
+ }
|
|
|
+ if { ![lindex $optdesc 2] } {
|
|
|
+ set curval $pathopt($option)
|
|
|
+ set newval [$_optiontype($type) $option $value [lindex $optdesc 3]]
|
|
|
+ if { [info exists classmap($option)] } {
|
|
|
+ foreach {subpath subclass realopt} $classmap($option) {
|
|
|
+ if { [string length $subclass] } {
|
|
|
+ ${subclass}::configure $window$subpath $realopt $newval
|
|
|
+ } else {
|
|
|
+ $window$subpath configure $realopt $newval
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ set pathopt($option) $newval
|
|
|
+ set pathmod($option) [expr {[string compare $newval $curval] != 0}]
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ 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)
|
|
|
+ upvar 0 ${class}::opt classopt
|
|
|
+ upvar 0 ${class}::sync classync
|
|
|
+ upvar 0 ${class}::$path:opt pathopt
|
|
|
+
|
|
|
+ if { ![info exists classopt($option)] } {
|
|
|
+ return -code error "unknown option \"$option\""
|
|
|
+ }
|
|
|
+ set optdesc $classopt($option)
|
|
|
+ set type [lindex $optdesc 0]
|
|
|
+ if { ![string compare $type "Synonym"] } {
|
|
|
+ set option [lindex $optdesc 1]
|
|
|
+ }
|
|
|
+
|
|
|
+ if { [info exists classync($option)] } {
|
|
|
+ set window [_get_window $class $path]
|
|
|
+ foreach {subpath subclass realopt} $classync($option) {
|
|
|
+ if { [string length $subclass] } {
|
|
|
+ set pathopt($option) [${subclass}::cget $window$subpath $realopt]
|
|
|
+ } else {
|
|
|
+ set pathopt($option) [$window$subpath cget $realopt]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return $pathopt($option)
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# Command Widget::subcget
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+proc Widget::subcget { path subwidget } {
|
|
|
+ variable _class
|
|
|
+
|
|
|
+ set class $_class($path)
|
|
|
+ upvar 0 ${class}::map classmap
|
|
|
+ upvar 0 ${class}::$path:opt pathopt
|
|
|
+
|
|
|
+ set result {}
|
|
|
+ foreach {option map} [array get classmap] {
|
|
|
+ foreach {subpath subclass realopt} $map {
|
|
|
+ if { ![string compare $subpath $subwidget] } {
|
|
|
+ lappend result $realopt $pathopt($option)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return $result
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# Command Widget::hasChanged
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+proc Widget::hasChanged { path option pvalue } {
|
|
|
+ upvar $pvalue value
|
|
|
+ variable _class
|
|
|
+
|
|
|
+ set class $_class($path)
|
|
|
+ upvar 0 ${class}::$path:opt pathopt
|
|
|
+ upvar 0 ${class}::$path:mod pathmod
|
|
|
+
|
|
|
+ set value $pathopt($option)
|
|
|
+ set result $pathmod($option)
|
|
|
+ set pathmod($option) 0
|
|
|
+
|
|
|
+ return $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
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# Command Widget::getoption
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+proc Widget::getoption { path option } {
|
|
|
+ variable _class
|
|
|
+
|
|
|
+ set class $_class($path)
|
|
|
+ upvar 0 ${class}::$path:opt pathopt
|
|
|
+
|
|
|
+ return $pathopt($option)
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# 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 compare [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 compare $type "Synonym"] } {
|
|
|
+ set syn $option
|
|
|
+ set option [lindex $optdesc 1]
|
|
|
+ set optdesc $classopt($option)
|
|
|
+ set type [lindex $optdesc 0]
|
|
|
+ } else {
|
|
|
+ set syn ""
|
|
|
+ }
|
|
|
+ if { ![string compare $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 compare $type "Synonym"] } {
|
|
|
+ set option [lindex $optdesc 1]
|
|
|
+ set optdesc $classopt($option)
|
|
|
+ set type [lindex $optdesc 0]
|
|
|
+ }
|
|
|
+ if { ![string compare $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
|
|
|
+
|
|
|
+ if { ![info exists _tk_widget($tkwidget)] } {
|
|
|
+ set widget [$tkwidget ".#BWidget#$tkwidget"]
|
|
|
+ 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]
|
|
|
+ set def [lindex [lindex $config $idx] 3]
|
|
|
+ lappend _tk_widget($tkwidget) [list $opt $syn $def]
|
|
|
+ } else {
|
|
|
+ set def [lindex $optlist 3]
|
|
|
+ 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]
|
|
|
+ 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_string
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+proc Widget::_test_string { option value arg } {
|
|
|
+ return $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 } {
|
|
|
+ set binf [lindex $arg 0]
|
|
|
+ set bsup [lindex $arg 1]
|
|
|
+ if { $binf != "" } {set binf ">$binf"}
|
|
|
+ if { $bsup != "" } {set bsup "<$bsup"}
|
|
|
+ if { [catch {expr $value}] || $value != int($value) ||
|
|
|
+ !($binf == "" || [expr $value$binf]) ||
|
|
|
+ !($bsup == "" || [expr $value$bsup]) } {
|
|
|
+ return -code error "bad [string range $option 1 end] value \"$value\": must be integer $binf $bsup"
|
|
|
+ }
|
|
|
+ return $value
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# Command Widget::_test_boolean
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+proc Widget::_test_boolean { option value arg } {
|
|
|
+ if { $value == 1 ||
|
|
|
+ ![string compare $value "true"] ||
|
|
|
+ ![string compare $value "yes"] } {
|
|
|
+ set value 1
|
|
|
+ } elseif { $value == 0 ||
|
|
|
+ ![string compare $value "false"] ||
|
|
|
+ ![string compare $value "no"] } {
|
|
|
+ set value 0
|
|
|
+ } else {
|
|
|
+ return -code error "bad [string range $option 1 end] value \"$value\": must be boolean"
|
|
|
+ }
|
|
|
+ return $value
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# 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 {[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 {[winfo toplevel $cur] == $cur} {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ set parent [winfo parent $parent]
|
|
|
+ set children [winfo children $parent]
|
|
|
+ set i [lsearch -exact $children $cur]
|
|
|
+ }
|
|
|
+ if {($cur == $w) || [focusOK $cur]} {
|
|
|
+ return $cur
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+# Command Widget::focusPrev
|
|
|
+# Same as tk_focusPrev, but call Widget::focusOK
|
|
|
+# ------------------------------------------------------------------------------
|
|
|
+proc Widget::focusPrev { w } {
|
|
|
+ set cur $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 {[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 {[winfo toplevel $cur] == $cur} {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ set parent $cur
|
|
|
+ set children [winfo children $parent]
|
|
|
+ set i [llength $children]
|
|
|
+ }
|
|
|
+ set cur $parent
|
|
|
+ if {($cur == $w) || [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} {
|
|
|
+ return 0
|
|
|
+ }
|
|
|
+
|
|
|
+ set top [winfo toplevel $w]
|
|
|
+ foreach tags [bindtags $w] {
|
|
|
+ if { [string compare $tags $top] &&
|
|
|
+ [string compare $tags "all"] &&
|
|
|
+ [regexp Key [bind $tags]] } {
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0
|
|
|
+}
|