diff options
-rw-r--r-- | ext/tk/ChangeLog.tkextlib | 10 | ||||
-rw-r--r-- | ext/tk/sample/tkextlib/tile/demo.rb | 40 | ||||
-rw-r--r-- | ext/tk/sample/tkextlib/tile/repeater.tcl | 117 |
3 files changed, 159 insertions, 8 deletions
diff --git a/ext/tk/ChangeLog.tkextlib b/ext/tk/ChangeLog.tkextlib index 85b4cf6191..c16daadb40 100644 --- a/ext/tk/ChangeLog.tkextlib +++ b/ext/tk/ChangeLog.tkextlib @@ -1,12 +1,18 @@ 2005-08-01 ocean <ocean@ruby-lang.org> + * sample/tkextlib/tile/demo.rb: added repeating buttons demo. + + * sample/tkextlib/tile/repeater.tcl: ditto. (new file) + +2005-08-01 ocean <ocean@ruby-lang.org> + * lib/tkextlib/tile.rb: fixed autoload for Treeview. * lib/tkextlib/tile/treeview.rb: replaced `ary2tk_list(items)' with `*items'. - * sample/tkextlib/tile: added treeview demo. (tile 0.5 or later is - needed) [ruby-dev:26668] + * sample/tkextlib/tile/demo.rb: added treeview demo. (tile 0.5 or + later is required) [ruby-dev:26668] 2005-08-01 ocean <ocean@ruby-lang.org> diff --git a/ext/tk/sample/tkextlib/tile/demo.rb b/ext/tk/sample/tkextlib/tile/demo.rb index 473e5b4bde..7c58704c56 100644 --- a/ext/tk/sample/tkextlib/tile/demo.rb +++ b/ext/tk/sample/tkextlib/tile/demo.rb @@ -10,6 +10,7 @@ Tk::AUTO_PATH.lappend('.', demodir, File.join(demodir, 'themes')) require 'tkextlib/tile' Tk.load_tclscript(File.join(demodir, 'toolbutton.tcl')) +Tk.load_tclscript(File.join(demodir, 'repeater.tcl')) # This forces an update of the available packages list. It's required # for package names to find the themes in demos/themes/*.tcl @@ -307,10 +308,6 @@ def makeNotebook nb.add(tree, :text=>'Tree') others = Tk::Tile::TFrame.new(nb) nb.add(others, :text=>'Others', :underline=>4) - nb.add(Tk::Tile::TLabel.new(nb, :text=>'Nothing to see here...'), - :text=>'Stuff', :sticky=>:new) - nb.add(Tk::Tile::TLabel.new(nb, :text=>'Nothing to see here either.'), - :text=>'More Stuff', :sticky=>:se) [nb, client, combo, tree, others] end @@ -624,7 +621,11 @@ showDescription.bind('Leave', proc{|w| msg.text('')}, '%W') "Shows how Tile and standard scrollbars differ when they're sized too large" ], [ :trackFocus, "Track keyboard focus..." , - "Display the name of the widget that currently has focus" ] + "Display the name of the widget that currently has focus" ], + + [ :repeatDemo, "Repeating buttons...", + "Demonstrates custom classes (see demos/repeater.tcl)" ] + ].each{|demo_cmd, label, description| b = Tk::Tile::TButton.new(others, :text=>label, :command=>proc{ self.__send__(demo_cmd) }) @@ -722,7 +723,6 @@ end # # Widget state demo: # - $Widget = TkVariable.new TkBindTag::ALL.bind('Control-Shift-ButtonPress-1', @@ -808,4 +808,32 @@ def changeState(st) end end +# +# Repeating buttons demo: +# +def repeatDemo + if defined?($repeatDemo) && $repeatDemo.exist? + $repeatDemo.deiconify; return + end + $repeatDemo = TkToplevel.new(:title=>'Repeating button') + + f = Tk::Tile::TFrame.new($repeatDemo) + b = Tk::Tile::TButton.new(f, :class=>'Repeater', :text=>'Press and hold') + begin + p = Tk::Tile::TProgressbar.new(f, :orient=>:horizontal, :maximum=>10) + rescue # progressbar is not supported (tile 0.4) + p = Tk::Tile::TLabel.new(f, :text=>0) + def p.step + i = self.text.to_i + 1 + i = 0 if i >= 10 + self.text(i.to_s) + end + end + b.command {p.step} + + b.pack(:side=>:left, :expand=>false, :fill=>:none, :padx=>6, :pady=>6) + p.pack(:side=>:right, :expand=>true, :fill=>:x, :padx=>6, :pady=>6) + f.pack(:expand=>true, :fill=>:both) +end + Tk.mainloop diff --git a/ext/tk/sample/tkextlib/tile/repeater.tcl b/ext/tk/sample/tkextlib/tile/repeater.tcl new file mode 100644 index 0000000000..652ba8ab17 --- /dev/null +++ b/ext/tk/sample/tkextlib/tile/repeater.tcl @@ -0,0 +1,117 @@ +# +# $Id$ +# +# Demonstration of custom classes. +# +# The Tile button doesn't have built-in support for autorepeat. +# Instead of adding -repeatdelay and -repeatinterval options, +# and all the extra binding scripts required to deal with them, +# we create a custom widget class for autorepeating buttons. +# +# Usage: +# ttk::button .b -class Repeater [... other options ...] +# +# TODO: +# Use system settings for repeat interval and initial delay. +# +# Notes: +# Repeater buttons work more like scrollbar arrows than +# Tk repeating buttons: they fire once immediately when +# first pressed, and $State(delay) specifies the initial +# interval before the button starts autorepeating. +# + +namespace eval tile::Repeater { + variable State + set State(timer) {} ;# [after] id of repeat script + set State(interval) 100 ;# interval between repetitions + set State(delay) 300 ;# delay after initial invocation +} + +### Class bindings. +# + +bind Repeater <Enter> { %W state active } +bind Repeater <Leave> { %W state !active } + +bind Repeater <Key-space> { tile::Repeater::Activate %W } +bind Repeater <<Invoke>> { tile::Repeater::Activate %W } + +bind Repeater <ButtonPress-1> { tile::Repeater::Press %W } +bind Repeater <ButtonRelease-1> { tile::Repeater::Release %W } +bind Repeater <B1-Leave> { tile::Repeater::Pause %W } +bind Repeater <B1-Enter> { tile::Repeater::Resume %W } ;# @@@ see below + +# @@@ Workaround for metacity-induced bug: +bind Repeater <B1-Enter> \ + { if {"%d" ne "NotifyUngrab"} { tile::Repeater::Resume %W } } + +### Binding procedures. +# + +## Activate -- Keyboard activation binding. +# Simulate clicking the button, and invoke the command once. +# +proc tile::Repeater::Activate {w} { + $w instate disabled { return } + set oldState [$w state pressed] + update idletasks; after 100 + $w state $oldState + after idle [list $w invoke] +} + +## Press -- ButtonPress-1 binding. +# Invoke the command once and start autorepeating after +# $State(delay) milliseconds. +# +proc tile::Repeater::Press {w} { + variable State + $w instate disabled { return } + $w state pressed + $w invoke + after cancel $State(timer) + set State(timer) [after $State(delay) [list tile::Repeater::Repeat $w]] +} + +## Release -- ButtonRelease binding. +# Stop repeating. +# +proc tile::Repeater::Release {w} { + variable State + $w state !pressed + after cancel $State(timer) +} + +## Pause -- B1-Leave binding +# Temporarily suspend autorepeat. +# +proc tile::Repeater::Pause {w} { + variable State + $w state !pressed + after cancel $State(timer) +} + +## Resume -- B1-Enter binding +# Resume autorepeat. +# +proc tile::Repeater::Resume {w} { + variable State + $w instate disabled { return } + $w state pressed + $w invoke + after cancel $State(timer) + set State(timer) [after $State(interval) [list tile::Repeater::Repeat $w]] +} + +## Repeat -- Timer script +# Invoke the command and reschedule another repetition +# after $State(interval) milliseconds. +# +proc tile::Repeater::Repeat {w} { + variable State + $w instate disabled { return } + $w invoke + set State(timer) [after $State(interval) [list tile::Repeater::Repeat $w]] +} + +#*EOF* |