Event.tcl 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. # -*- mode: TCL; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
  2. #
  3. # $Id: Event.tcl,v 1.6 2004/04/09 21:37:01 hobbs Exp $
  4. #
  5. # Event.tcl --
  6. #
  7. # Handles the event bindings of the -command and -browsecmd options
  8. # (and various of others such as -validatecmd).
  9. #
  10. # Copyright (c) 1993-1999 Ioi Kim Lam.
  11. # Copyright (c) 2000-2001 Tix Project Group.
  12. # Copyright (c) 2004 ActiveState
  13. #
  14. # See the file "license.terms" for information on usage and redistribution
  15. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  16. #
  17. #----------------------------------------------------------------------
  18. # Evaluate high-level bindings (-command, -browsecmd, etc):
  19. # with % subsitution or without (compatibility mode)
  20. #
  21. #
  22. # BUG : if a -command is intercepted by a hook, the hook must use
  23. # the same record name as the issuer of the -command. For the time
  24. # being, you must use the name "bind" as the record name!!!!!
  25. #
  26. #----------------------------------------------------------------------
  27. namespace eval ::tix {
  28. variable event_flags ""
  29. set evs [list % \# a b c d f h k m o p s t w x y A B E K N R S T W X Y]
  30. foreach ev $evs {
  31. lappend event_flags "%$ev"
  32. }
  33. # This is a "name stack" for storing the "bind" structures
  34. #
  35. # The bottom of the event stack is usually a raw event (generated by
  36. # tixBind) but it may also be a programatically triggered (caused by
  37. # tixEvalCmdBinding)
  38. variable EVENT
  39. set EVENT(nameStack) ""
  40. set EVENT(stackLevel) 0
  41. }
  42. proc tixBind {tag event action} {
  43. set cmd [linsert $::tix::event_flags 0 _tixRecordFlags $event]
  44. append cmd "; $action; _tixDeleteFlags;"
  45. bind $tag $event $cmd
  46. }
  47. proc tixPushEventStack {} {
  48. variable ::tix::EVENT
  49. set lastEvent [lindex $EVENT(nameStack) 0]
  50. incr EVENT(stackLevel)
  51. set thisEvent ::tix::_event$EVENT(stackLevel)
  52. set EVENT(nameStack) [list $thisEvent $EVENT(nameStack)]
  53. if {$lastEvent == ""} {
  54. upvar #0 $thisEvent this
  55. set this(type) <Application>
  56. } else {
  57. upvar #0 $lastEvent last
  58. upvar #0 $thisEvent this
  59. foreach name [array names last] {
  60. set this($name) $last($name)
  61. }
  62. }
  63. return $thisEvent
  64. }
  65. proc tixPopEventStack {varName} {
  66. variable ::tix::EVENT
  67. if {$varName ne [lindex $EVENT(nameStack) 0]} {
  68. error "unmatched tixPushEventStack and tixPopEventStack calls"
  69. }
  70. incr EVENT(stackLevel) -1
  71. set EVENT(nameStack) [lindex $EVENT(nameStack) 1]
  72. global $varName
  73. unset $varName
  74. }
  75. # Events triggered by tixBind
  76. #
  77. proc _tixRecordFlags [concat event $::tix::event_flags] {
  78. set thisName [tixPushEventStack]; upvar #0 $thisName this
  79. set this(type) $event
  80. foreach f $::tix::event_flags {
  81. set this($f) [set $f]
  82. }
  83. }
  84. proc _tixDeleteFlags {} {
  85. variable ::tix::EVENT
  86. tixPopEventStack [lindex $EVENT(nameStack) 0]
  87. }
  88. # programatically trigged events
  89. #
  90. proc tixEvalCmdBinding {w cmd {subst ""} args} {
  91. global tixPriv tix
  92. variable ::tix::EVENT
  93. set thisName [tixPushEventStack]; upvar #0 $thisName this
  94. if {$subst != ""} {
  95. upvar $subst bind
  96. if {[info exists bind(specs)]} {
  97. foreach spec $bind(specs) {
  98. set this($spec) $bind($spec)
  99. }
  100. }
  101. if {[info exists bind(type)]} {
  102. set this(type) $bind(type)
  103. }
  104. }
  105. if {[catch {
  106. if {![info exists tix(-extracmdargs)]
  107. || [string is true -strict $tix(-extracmdargs)]} {
  108. # Compatibility mode
  109. set ret [uplevel \#0 $cmd $args]
  110. } else {
  111. set ret [uplevel 1 $cmd]
  112. }
  113. } error]} {
  114. if {[catch {tixCmdErrorHandler $error} error]} {
  115. # double fault: just print out
  116. tixBuiltInCmdErrorHandler $error
  117. }
  118. tixPopEventStack $thisName
  119. return ""
  120. } else {
  121. tixPopEventStack $thisName
  122. return $ret
  123. }
  124. }
  125. proc tixEvent {option args} {
  126. global tixPriv
  127. variable ::tix::EVENT
  128. set varName [lindex $EVENT(nameStack) 0]
  129. if {$varName == ""} {
  130. error "tixEvent called when no event is being processed"
  131. } else {
  132. upvar #0 $varName event
  133. }
  134. switch -exact -- $option {
  135. type {
  136. return $event(type)
  137. }
  138. value {
  139. if {[info exists event(%V)]} {
  140. return $event(%V)
  141. } else {
  142. return ""
  143. }
  144. }
  145. flag {
  146. set f %[lindex $args 0]
  147. if {[info exists event($f)]} {
  148. return $event($f)
  149. }
  150. error "The flag \"[lindex $args 0]\" does not exist"
  151. }
  152. match {
  153. return [string match [lindex $args 0] $event(type)]
  154. }
  155. default {
  156. error "unknown option \"$option\""
  157. }
  158. }
  159. }
  160. # tixBuiltInCmdErrorHandler --
  161. #
  162. # Default method to report command handler errors. This procedure is
  163. # also called if double-fault happens (command handler causes error,
  164. # then tixCmdErrorHandler causes error).
  165. #
  166. proc tixBuiltInCmdErrorHandler {errorMsg} {
  167. global errorInfo tcl_platform
  168. if {![info exists errorInfo]} {
  169. set errorInfo "???"
  170. }
  171. if {$tcl_platform(platform) eq "windows"} {
  172. bgerror "Tix Error: $errorMsg"
  173. } else {
  174. puts "Error:\n $errorMsg\n$errorInfo"
  175. }
  176. }
  177. # tixCmdErrorHandler --
  178. #
  179. # You can redefine this command to handle the errors that occur
  180. # in the command handlers. See the programmer's documentation
  181. # for details
  182. #
  183. if {![llength [info commands tixCmdErrorHandler]]} {
  184. proc tixCmdErrorHandler {errorMsg} {
  185. tixBuiltInCmdErrorHandler $errorMsg
  186. }
  187. }