diff options
Diffstat (limited to 'ext/tk/sample/editable_listbox.rb')
-rw-r--r-- | ext/tk/sample/editable_listbox.rb | 131 |
1 files changed, 105 insertions, 26 deletions
diff --git a/ext/tk/sample/editable_listbox.rb b/ext/tk/sample/editable_listbox.rb index 553d400e24..7a9ad4450b 100644 --- a/ext/tk/sample/editable_listbox.rb +++ b/ext/tk/sample/editable_listbox.rb @@ -1,5 +1,5 @@ # -# Editable_TkListbox class +# Tk::RbWidget::Editable_Listbox class # # When "DoubleClick-1" on a listbox item, the entry box is opend on the # item. And when hit "Return" key on the entry box after modifying the @@ -10,19 +10,106 @@ # require 'tk' -class Editable_TkListbox < TkListbox - def _ebox_placer(coord_y) - idx = self.nearest(coord_y) - x, y, w, h = self.bbox(idx) +module Tk + module RbWidget + class Editable_Listbox < TkListbox + end + end +end + + +class Tk::RbWidget::Editable_Listbox < TkListbox + #------------------------------------ + BindTag = TkBindTag.new_by_name(self.to_s.gsub(/::/, '#')) + + BindTag.bind('FocusIn', :widget){|w| + w.instance_eval{ + if idx = @ebox.pos + see(idx) if bbox(idx).empty? + @ebox.focus(true) + end + } + } + + BindTag.bind('Double-1', :widget, :y){|w, y| + w.instance_eval{ _ebox_placer(nearest(y)) } + } + + BindTag.bind('Return', :widget){|w| + w.instance_eval{ + if idx = index(:active) + _ebox_placer(idx) + end + } + } + #------------------------------------ + + def configure(*args) + ret = super + + case cget(:state) + when 'normal' + # do nothing + when 'disabled' + _ebox_erase + else # unknown + # do nothing + + end + + ret + end + + def _ebox_move(idx) + return nil if cget(:state) == 'disabled' + x, y, w, h = bbox(idx) + return nil unless y && h @ebox.place(:x => 0, :relwidth => 1.0, - :y => y - self.selectborderwidth, - :height => h + 2 * self.selectborderwidth) + :y => y - selectborderwidth, + :height => h + 2 * selectborderwidth) @ebox.pos = idx - @ebox.value = self.listvariable.list[idx] @ebox.focus end - private :_ebox_placer + def _ebox_placer(idx) + return nil unless _ebox_move(idx) + @ebox.value = listvariable.list[idx] + @ebox.xview_moveto(self.xview[0]) + end + + def _ebox_erase + @ebox.place_forget + @ebox.pos = nil + end + private :_ebox_move, :_ebox_placer, :_ebox_erase + + def _setup_ebox_bindings + # bindings for entry + @ebox.bind('Return'){ + list = listvariable.list + list[@ebox.pos] = @ebox.value if @ebox.pos + listvariable.value = list + _ebox_erase + focus + } + + @ebox.bind('Escape'){ _ebox_erase } + end + def _setup_listbox_bindings + # bindings for listbox + tags = bindtags + bindtags(tags.insert(tags.index(self) + 1, self.class::BindTag)) + end + private :_setup_ebox_bindings, :_setup_listbox_bindings + + def yview(*args) + if !@ebox.pos || bbox(@ebox.pos).empty? + @ebox.place_forget + else + _ebox_move(@ebox.pos) + end + super + end def create_self(keys) super(keys) @@ -32,38 +119,30 @@ class Editable_TkListbox < TkListbox end @ebox = TkEntry.new(self){ - @pos = -1 + @pos = nil def self.pos; @pos; end def self.pos=(idx); @pos = idx; end } - @ebox.bind('Return'){ - list = self.listvariable.list - list[@ebox.pos] = @ebox.value - self.listvariable.value = list - @ebox.place_forget - @ebox.pos = -1 - } - - @ebox.bind('Escape'){ - @ebox.place_forget - @ebox.pos = -1 - } - - self.bind('Double-1', '%y'){|y| _ebox_placer(y) } + _setup_ebox_bindings + _setup_listbox_bindings end end if $0 == __FILE__ + #lbox0 = TkListbox.new.pack(:side=>:left) + #lbox0.insert(:end, 0,1,2,3,4,5,6,7,8,9,0,1,2,3) + scr = TkScrollbar.new.pack(:side=>:right, :fill=>:y) - lbox1 = Editable_TkListbox.new.pack(:side=>:left) - lbox2 = Editable_TkListbox.new.pack(:side=>:left) + lbox1 = Tk::RbWidget::Editable_Listbox.new.pack(:side=>:left) + lbox2 = Tk::RbWidget::Editable_Listbox.new.pack(:side=>:left) scr.assign(lbox1, lbox2) lbox1.insert(:end, *%w(a b c d e f g h i j k l m n)) lbox2.insert(:end, 0,1,2,3,4,5,6,7,8,9,0,1,2,3) + Tk.mainloop end |