File: bmb.tcl

package info (click to toggle)
tkman 2.2-4
  • links: PTS
  • area: main
  • in suites: lenny, squeeze
  • size: 948 kB
  • ctags: 290
  • sloc: tcl: 8,264; sh: 470; makefile: 241
file content (106 lines) | stat: -rw-r--r-- 3,168 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#
# ButtonMenubutton
#    act like a button for quick clicks
#    act like a menu if hold down button
#
# 1997 July 22 by Tom Phelps (phelps@ACM.org),
#    on top of Tk's button and menubutton bindings
# 2003 March 12 updated for Tk 8.4 (tkPriv => ::tk::Priv)
#

# To use, create a menubutton and pass it and the command to execute
#    if it's invoked as a button to the proc "buttonmenubutton"
#
# To convert to button-only operation,
#    <widget-name> configure -menu ""
# To convert to menu-only operation,
#    set bmb(<widget-name>) to ""
# If you save the former value, you can reverse these conversions
#    by restoring the former values.
# If you disable the original menubutton, both button and menubutton
#    behaviors are disabled.


set bmb(menubutton-delay) 250
set bmb(type) ""
set bmb(after) ""
set bmb(relief) ""
set bmb(w) ""
set bmb(x) ""; set bmb(y) ""
#set bmb(<widget-name>) <button-command>

proc buttonmenubutton {mb {cmd ""}} {
	global bmb

	if {[winfo class $mb] ne "Menubutton"} {error "$mb must be a menubutton"}

	# store commands
	set bmb($mb) $cmd

	# on Button-1, assume it's a click, correct later according to timer
	bind $mb <Button-1> {if [catch {bmbB1Down %W %X %Y}] break}
	bind $mb <B1-Motion> {if {$bmb(type) eq "button"} break}
	bind $mb <ButtonRelease-1> {if [catch {bmbB1Up %W}] break}
}

proc bmbB1Down {w x y} {
	global bmb

	# would be nice if break and continue could be thrown as exceptions
	# to be recognized in bindings
	if {$::tk::Priv(postedMb) ne ""} {::tk::MbButtonUp $w; return -code break}
	if {$bmb(type) ne ""} {return -code break}

	set bmb(w) $w; set bmb(relief) [$w cget -relief]
	set bmb(x) $x; set bmb(y) $y

	# if no command, treat as a menu straight away
	if {$bmb($w) eq ""} {set bmb(type) ""; return}; # continue with menubutton bindings

	# pretend you're a button at first
	set bmb(type) "button"
	catch {[::tk::ButtonDown $w]}; # brute force: -repeatdelay on button only not menubutton
	# if have a menu, possibility of converting to menubutton operation
	if {[$w cget -menu] ne "" && [[$w cget -menu] index end] ne "none"} {
		set bmb(after) [after $bmb(menubutton-delay) bmbConvert]
	}
	return -code break
}

proc bmbB1Up {w} {
	global bmb

	if {$bmb(type) eq "button"} {bmbButtonUp $w} else {::tk::MbButtonUp $w}
	# clean up for button
	set bmb(type) ""
	if {$bmb(after) ne ""} {after cancel $bmb(after)}
	set bmb(after) ""
	$bmb(w) configure -relief $bmb(relief)
	return -code break
}

proc bmbConvert {} {
	global bmb

	# if already finished as button, we're done
	if {$bmb(type) eq ""} return
	set ::tk::Priv(buttonWindow) ""; # clean up
	set bmb(after) ""

	$bmb(w) configure -relief $bmb(relief)
	set bmb(type) ""; # give control over to the menu system
	set ::tk::Priv(inMenubutton) $bmb(w)
	::tk::MbPost $bmb(w) $bmb(x) $bmb(y)
	$bmb(w) configure -relief sunken; # that's how Netscape does it
}

proc bmbButtonUp {w} {
	global bmb

	if {$w eq $::tk::Priv(buttonWindow)} {
		set ::tk::Priv(buttonWindow) ""
		if {[$w cget -state] ne "disabled"} {
			uplevel #0 $bmb($w)
		}
	}
}