entry.tcl 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. # ------------------------------------------------------------------------------
  2. # entry.tcl
  3. # This file is part of Unifix BWidget Toolkit
  4. # $Id$
  5. # ------------------------------------------------------------------------------
  6. # Index of commands:
  7. # - Entry::create
  8. # - Entry::configure
  9. # - Entry::cget
  10. # - Entry::_destroy
  11. # - Entry::_init_drag_cmd
  12. # - Entry::_end_drag_cmd
  13. # - Entry::_drop_cmd
  14. # - Entry::_over_cmd
  15. # - Entry::_auto_scroll
  16. # - Entry::_scroll
  17. # ------------------------------------------------------------------------------
  18. namespace eval Entry {
  19. Widget::tkinclude Entry entry :cmd \
  20. remove {-state -cursor -foreground -textvariable}
  21. Widget::declare Entry {
  22. {-foreground TkResource "" 0 entry}
  23. {-disabledforeground TkResource "" 0 button}
  24. {-state Enum normal 0 {normal disabled}}
  25. {-text String "" 0}
  26. {-textvariable String "" 0}
  27. {-editable Boolean 1 0}
  28. {-command String "" 0}
  29. {-relief TkResource "" 0 entry}
  30. {-borderwidth TkResource "" 0 entry}
  31. {-fg Synonym -foreground}
  32. {-bd Synonym -borderwidth}
  33. }
  34. DynamicHelp::include Entry balloon
  35. DragSite::include Entry "" 3
  36. DropSite::include Entry {
  37. TEXT {move {}}
  38. FGCOLOR {move {}}
  39. BGCOLOR {move {}}
  40. COLOR {move {}}
  41. }
  42. foreach event [bind Entry] {
  43. bind BwEntry $event [bind Entry $event]
  44. }
  45. bind BwEntry <Return> {Entry::invoke %W}
  46. bind BwEntry <Destroy> {Entry::_destroy %W}
  47. bind BwDisabledEntry <Destroy> {Entry::_destroy %W}
  48. proc ::Entry { path args } { return [eval Entry::create $path $args] }
  49. proc use {} {}
  50. }
  51. # ------------------------------------------------------------------------------
  52. # Command Entry::create
  53. # ------------------------------------------------------------------------------
  54. proc Entry::create { path args } {
  55. variable $path
  56. upvar 0 $path data
  57. Widget::init Entry $path $args
  58. set data(afterid) ""
  59. if { [set varname [Widget::getoption $path -textvariable]] != "" } {
  60. set data(varname) $varname
  61. } else {
  62. set data(varname) Entry::$path\(var\)
  63. }
  64. if { [GlobalVar::exists $data(varname)] } {
  65. set curval [GlobalVar::getvar $data(varname)]
  66. Widget::setoption $path -text $curval
  67. } else {
  68. set curval [Widget::getoption $path -text]
  69. GlobalVar::setvar $data(varname) $curval
  70. }
  71. eval entry $path [Widget::subcget $path :cmd]
  72. uplevel \#0 $path configure -textvariable [list $data(varname)]
  73. set state [Widget::getoption $path -state]
  74. set editable [Widget::getoption $path -editable]
  75. if { $editable && ![string compare $state "normal"] } {
  76. bindtags $path [list $path BwEntry [winfo toplevel $path] all]
  77. $path configure -takefocus 1
  78. } else {
  79. bindtags $path [list $path BwDisabledEntry [winfo toplevel $path] all]
  80. $path configure -takefocus 0
  81. }
  82. if { $editable == 0 } {
  83. $path configure -cursor left_ptr
  84. }
  85. if { ![string compare $state "disabled"] } {
  86. $path configure -foreground [Widget::getoption $path -disabledforeground]
  87. }
  88. DragSite::setdrag $path $path Entry::_init_drag_cmd Entry::_end_drag_cmd 1
  89. DropSite::setdrop $path $path Entry::_over_cmd Entry::_drop_cmd 1
  90. DynamicHelp::sethelp $path $path 1
  91. rename $path ::$path:cmd
  92. proc ::$path { cmd args } "return \[Entry::_path_command $path \$cmd \$args\]"
  93. return $path
  94. }
  95. # ------------------------------------------------------------------------------
  96. # Command Entry::configure
  97. # ------------------------------------------------------------------------------
  98. proc Entry::configure { path args } {
  99. variable $path
  100. upvar 0 $path data
  101. Widget::setoption $path -text [$path:cmd get]
  102. set res [Widget::configure $path $args]
  103. set chstate [Widget::hasChanged $path -state state]
  104. set cheditable [Widget::hasChanged $path -editable editable]
  105. set chfg [Widget::hasChanged $path -foreground fg]
  106. set chdfg [Widget::hasChanged $path -disabledforeground dfg]
  107. if { $chstate || $cheditable } {
  108. set btags [bindtags $path]
  109. if { $editable && ![string compare $state "normal"] } {
  110. set idx [lsearch $btags BwDisabledEntry]
  111. if { $idx != -1 } {
  112. bindtags $path [lreplace $btags $idx $idx BwEntry]
  113. }
  114. $path:cmd configure -takefocus 1
  115. } else {
  116. set idx [lsearch $btags BwEntry]
  117. if { $idx != -1 } {
  118. bindtags $path [lreplace $btags $idx $idx BwDisabledEntry]
  119. }
  120. $path:cmd configure -takefocus 0
  121. if { ![string compare [focus] $path] } {
  122. focus .
  123. }
  124. }
  125. }
  126. if { $chstate || $chfg || $chdfg } {
  127. if { ![string compare $state "disabled"] } {
  128. $path:cmd configure -fg $dfg
  129. } else {
  130. $path:cmd configure -fg $fg
  131. }
  132. }
  133. if { $cheditable } {
  134. if { $editable } {
  135. $path:cmd configure -cursor xterm
  136. } else {
  137. $path:cmd configure -cursor left_ptr
  138. }
  139. }
  140. if { [Widget::hasChanged $path -textvariable varname] } {
  141. if { [string length $varname] } {
  142. set data(varname) $varname
  143. } else {
  144. catch {unset data(var)}
  145. set data(varname) Entry::$path\(var\)
  146. }
  147. if { [GlobalVar::exists $data(varname)] } {
  148. set curval [GlobalVar::getvar $data(varname)]
  149. Widget::setoption $path -text $curval
  150. } else {
  151. Widget::hasChanged $path -text curval
  152. GlobalVar::setvar $data(varname) $curval
  153. }
  154. uplevel \#0 $path:cmd configure -textvariable [list $data(varname)]
  155. }
  156. if { [Widget::hasChanged $path -text curval] } {
  157. if { [Widget::getoption $path -textvariable] == "" } {
  158. GlobalVar::setvar $data(varname) $curval
  159. } else {
  160. Widget::setoption $path -text [GlobalVar::getvar $data(varname)]
  161. }
  162. }
  163. DragSite::setdrag $path $path Entry::_init_drag_cmd Entry::_end_drag_cmd
  164. DropSite::setdrop $path $path Entry::_over_cmd Entry::_drop_cmd
  165. DynamicHelp::sethelp $path $path
  166. return $res
  167. }
  168. # ------------------------------------------------------------------------------
  169. # Command Entry::cget
  170. # ------------------------------------------------------------------------------
  171. proc Entry::cget { path option } {
  172. Widget::setoption $path -text [$path:cmd get]
  173. return [Widget::cget $path $option]
  174. }
  175. # ------------------------------------------------------------------------------
  176. # Command Entry::invoke
  177. # ------------------------------------------------------------------------------
  178. proc Entry::invoke { path } {
  179. if { [set cmd [Widget::getoption $path -command]] != "" } {
  180. uplevel \#0 $cmd
  181. }
  182. }
  183. # ------------------------------------------------------------------------------
  184. # Command Entry::_path_command
  185. # ------------------------------------------------------------------------------
  186. proc Entry::_path_command { path cmd larg } {
  187. if { ![string compare $cmd "configure"] || ![string compare $cmd "cget"] } {
  188. return [eval Entry::$cmd $path $larg]
  189. } else {
  190. return [eval $path:cmd $cmd $larg]
  191. }
  192. }
  193. # ------------------------------------------------------------------------------
  194. # Command Entry::_destroy
  195. # ------------------------------------------------------------------------------
  196. proc Entry::_destroy { path } {
  197. variable $path
  198. upvar 0 $path data
  199. Widget::destroy $path
  200. rename $path {}
  201. unset data
  202. }
  203. # ------------------------------------------------------------------------------
  204. # Command Entry::_init_drag_cmd
  205. # ------------------------------------------------------------------------------
  206. proc Entry::_init_drag_cmd { path X Y top } {
  207. variable $path
  208. upvar 0 $path data
  209. if { [set cmd [Widget::getoption $path -draginitcmd]] != "" } {
  210. return [uplevel \#0 $cmd [list $path $X $Y $top]]
  211. }
  212. set type [Widget::getoption $path -dragtype]
  213. if { $type == "" } {
  214. set type "TEXT"
  215. }
  216. if { [set drag [$path get]] != "" } {
  217. if { [$path:cmd selection present] } {
  218. set idx [$path:cmd index @[expr $X-[winfo rootx $path]]]
  219. set sel0 [$path:cmd index sel.first]
  220. set sel1 [expr [$path:cmd index sel.last]-1]
  221. if { $idx >= $sel0 && $idx <= $sel1 } {
  222. set drag [string range $drag $sel0 $sel1]
  223. set data(dragstart) $sel0
  224. set data(dragend) [expr {$sel1+1}]
  225. if { ![Widget::getoption $path -editable] ||
  226. [Widget::getoption $path -state] == "disabled" } {
  227. return [list $type {copy} $drag]
  228. } else {
  229. return [list $type {copy move} $drag]
  230. }
  231. }
  232. } else {
  233. set data(dragstart) 0
  234. set data(dragend) end
  235. if { ![Widget::getoption $path -editable] ||
  236. [Widget::getoption $path -state] == "disabled" } {
  237. return [list $type {copy} $drag]
  238. } else {
  239. return [list $type {copy move} $drag]
  240. }
  241. }
  242. }
  243. }
  244. # ------------------------------------------------------------------------------
  245. # Command Entry::_end_drag_cmd
  246. # ------------------------------------------------------------------------------
  247. proc Entry::_end_drag_cmd { path target op type dnddata result } {
  248. variable $path
  249. upvar 0 $path data
  250. if { [set cmd [Widget::getoption $path -dragendcmd]] != "" } {
  251. return [uplevel \#0 $cmd [list $path $target $op $type $dnddata $result]]
  252. }
  253. if { $result && $op == "move" && $path != $target } {
  254. $path:cmd delete $data(dragstart) $data(dragend)
  255. }
  256. }
  257. # ------------------------------------------------------------------------------
  258. # Command Entry::_drop_cmd
  259. # ------------------------------------------------------------------------------
  260. proc Entry::_drop_cmd { path source X Y op type dnddata } {
  261. variable $path
  262. upvar 0 $path data
  263. if { $data(afterid) != "" } {
  264. after cancel $data(afterid)
  265. set data(afterid) ""
  266. }
  267. if { [set cmd [Widget::getoption $path -dropcmd]] != "" } {
  268. set idx [$path:cmd index @[expr $X-[winfo rootx $path]]]
  269. return [uplevel \#0 $cmd [list $path $source $idx $op $type $dnddata]]
  270. }
  271. if { $type == "COLOR" || $type == "FGCOLOR" } {
  272. configure $path -foreground $dnddata
  273. } elseif { $type == "BGCOLOR" } {
  274. configure $path -background $dnddata
  275. } else {
  276. $path:cmd icursor @[expr $X-[winfo rootx $path]]
  277. if { $op == "move" && $path == $source } {
  278. $path:cmd delete $data(dragstart) $data(dragend)
  279. }
  280. set sel0 [$path index insert]
  281. $path:cmd insert insert $dnddata
  282. set sel1 [$path index insert]
  283. $path:cmd selection range $sel0 $sel1
  284. }
  285. return 1
  286. }
  287. # ------------------------------------------------------------------------------
  288. # Command Entry::_over_cmd
  289. # ------------------------------------------------------------------------------
  290. proc Entry::_over_cmd { path source event X Y op type dnddata } {
  291. variable $path
  292. upvar 0 $path data
  293. set x [expr $X-[winfo rootx $path]]
  294. if { ![string compare $event "leave"] } {
  295. if { [string length $data(afterid)] } {
  296. after cancel $data(afterid)
  297. set data(afterid) ""
  298. }
  299. } elseif { [_auto_scroll $path $x] } {
  300. return 2
  301. }
  302. if { [set cmd [Widget::getoption $path -dropovercmd]] != "" } {
  303. set x [expr $X-[winfo rootx $path]]
  304. set idx [$path:cmd index @$x]
  305. set res [uplevel \#0 $cmd [list $path $source $event $idx $op $type $dnddata]]
  306. return $res
  307. }
  308. if { ![string compare $type "COLOR"] ||
  309. ![string compare $type "FGCOLOR"] ||
  310. ![string compare $type "BGCOLOR"] } {
  311. DropSite::setcursor based_arrow_down
  312. return 1
  313. }
  314. if { [Widget::getoption $path -editable] && ![string compare [Widget::getoption $path -state] "normal"] } {
  315. if { [string compare $event "leave"] } {
  316. $path:cmd selection clear
  317. $path:cmd icursor @$x
  318. DropSite::setcursor based_arrow_down
  319. return 3
  320. }
  321. }
  322. DropSite::setcursor dot
  323. return 0
  324. }
  325. # ------------------------------------------------------------------------------
  326. # Command Entry::_auto_scroll
  327. # ------------------------------------------------------------------------------
  328. proc Entry::_auto_scroll { path x } {
  329. variable $path
  330. upvar 0 $path data
  331. set xmax [winfo width $path]
  332. if { $x <= 10 && [$path:cmd index @0] > 0 } {
  333. if { $data(afterid) == "" } {
  334. set data(afterid) [after 100 "Entry::_scroll $path -1 $x $xmax"]
  335. DropSite::setcursor sb_left_arrow
  336. }
  337. return 1
  338. } else {
  339. if { $x >= $xmax-10 && [$path:cmd index @$xmax] < [$path:cmd index end] } {
  340. if { $data(afterid) == "" } {
  341. set data(afterid) [after 100 "Entry::_scroll $path 1 $x $xmax"]
  342. DropSite::setcursor sb_right_arrow
  343. }
  344. return 1
  345. } else {
  346. if { $data(afterid) != "" } {
  347. after cancel $data(afterid)
  348. set data(afterid) ""
  349. }
  350. }
  351. }
  352. return 0
  353. }
  354. # ------------------------------------------------------------------------------
  355. # Command Entry::_scroll
  356. # ------------------------------------------------------------------------------
  357. proc Entry::_scroll { path dir x xmax } {
  358. variable $path
  359. upvar 0 $path data
  360. $path:cmd xview scroll $dir units
  361. $path:cmd icursor @$x
  362. if { ($dir == -1 && [$path:cmd index @0] > 0) ||
  363. ($dir == 1 && [$path:cmd index @$xmax] < [$path:cmd index end]) } {
  364. set data(afterid) [after 100 "Entry::_scroll $path $dir $x $xmax"]
  365. } else {
  366. set data(afterid) ""
  367. DropSite::setcursor dot
  368. }
  369. }