mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* ext/tk/lib/tk.rb: add Tk.grab_release and fix bug of TkComposite
* ext/tk/lib/tkafter.rb: bug fix * ext/tk/sample/tkcombobox.rb: new sample script * ext/tcltklib/tcltklib.c: add native thread check git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5007 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
448b1af751
commit
615a54e77d
6 changed files with 438 additions and 4 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
Sat Nov 22 22:48:46 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
|
||||
|
||||
* ext/tk/lib/tk.rb: add Tk.grab_release and fix bug of TkComposite
|
||||
|
||||
* ext/tk/lib/tkafter.rb: bug fix of TkAfter#start
|
||||
|
||||
* ext/tk/sample/tkcombobox.rb: new sample script
|
||||
|
||||
* ext/tcltklib/tcltklib.c: add native thread check
|
||||
|
||||
Sat Nov 22 18:49:47 2003 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* ext/curses/curses.c (window_nodelay): nodelay() of NetBSD's
|
||||
|
|
|
@ -503,7 +503,9 @@ lib_eventloop_core(check_root, check_var)
|
|||
rb_trap_exec();
|
||||
} else {
|
||||
DUMP1("thread scheduling");
|
||||
rb_thread_schedule();
|
||||
if (is_ruby_native_thread()) {
|
||||
rb_thread_schedule();
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
|
|
@ -26,6 +26,7 @@ sample/safe-tk.rb
|
|||
sample/tkballoonhelp.rb
|
||||
sample/tkbiff.rb
|
||||
sample/tkbrowse.rb
|
||||
sample/tkcombobox.rb
|
||||
sample/tkdialog.rb
|
||||
sample/tkfrom.rb
|
||||
sample/tkhello.rb
|
||||
|
|
|
@ -4261,6 +4261,9 @@ class TkWindow<TkObject
|
|||
def grab_current
|
||||
grab('current')
|
||||
end
|
||||
def grab_release
|
||||
grab('release')
|
||||
end
|
||||
def grab_set
|
||||
grab('set')
|
||||
end
|
||||
|
@ -5681,8 +5684,8 @@ module TkComposite
|
|||
|
||||
if parent.kind_of? Hash
|
||||
keys = _symbolkey2str(parent)
|
||||
parent = keys['parent']
|
||||
keys['parent'] = @frame = TkFrame.new(parent)
|
||||
parent = keys.delete('parent')
|
||||
@frame = TkFrame.new(parent)
|
||||
@delegates['DEFAULT'] = @frame
|
||||
@path = @epath = @frame.path
|
||||
initialize_composite(keys)
|
||||
|
|
|
@ -306,7 +306,7 @@ class TkTimer
|
|||
fail format("%s need to be Proc", @init_proc.inspect)
|
||||
end
|
||||
@current_proc = @init_proc
|
||||
set_callback(sleep, @init_args)
|
||||
set_callback(@init_sleep, @init_args)
|
||||
@set_next = false if @in_callback
|
||||
else
|
||||
set_next_callback(@init_args)
|
||||
|
|
418
ext/tk/sample/tkcombobox.rb
Normal file
418
ext/tk/sample/tkcombobox.rb
Normal file
|
@ -0,0 +1,418 @@
|
|||
#
|
||||
# tkcombobox.rb : TkAutoScrollbox & TkCombobox
|
||||
#
|
||||
# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
|
||||
#
|
||||
require 'tk'
|
||||
|
||||
class TkAutoScrollbox < TkListbox
|
||||
include TkComposite
|
||||
|
||||
@@up_bmp = TkBitmapImage.new(:data=><<EOD)
|
||||
#define up_arrow_width 9
|
||||
#define up_arrow_height 9
|
||||
static unsigned char up_arrow_bits[] = {
|
||||
0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x38, 0x00, 0x38, 0x00, 0x7c, 0x00,
|
||||
0x7c, 0x00, 0xfe, 0x00, 0x00, 0x00};
|
||||
EOD
|
||||
|
||||
@@down_bmp = TkBitmapImage.new(:data=><<EOD)
|
||||
#define up_arrow_width 9
|
||||
#define up_arrow_height 9
|
||||
static unsigned char down_arrow_bits[] = {
|
||||
0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x38, 0x00,
|
||||
0x10, 0x00, 0x10, 0x00, 0x00, 0x00};
|
||||
EOD
|
||||
|
||||
def initialize_composite(keys={})
|
||||
keys = _symbolkey2str(keys)
|
||||
|
||||
@initwait = keys.delete('startwait'){300}
|
||||
@interval = keys.delete('interval'){150}
|
||||
@initwait -= @interval
|
||||
@initwait = 0 if @initwait < 0
|
||||
|
||||
@lbox = TkListbox.new(@frame, :borderwidth=>0)
|
||||
@path = @lbox.path
|
||||
TkPack.propagate(@lbox, false)
|
||||
|
||||
@scr = TkScrollbar.new(@frame, :width=>10)
|
||||
|
||||
@lbox.yscrollcommand(proc{|*args| @scr.set(*args); _config_proc})
|
||||
@scr.command(proc{|*args| @lbox.yview(*args); _config_proc})
|
||||
|
||||
@up_arrow = TkLabel.new(@lbox, :image=>@@up_bmp,
|
||||
:relief=>:raised, :borderwidth=>1)
|
||||
@down_arrow = TkLabel.new(@lbox, :image=>@@down_bmp,
|
||||
:relief=>:raised, :borderwidth=>1)
|
||||
|
||||
_init_binding
|
||||
|
||||
@lbox.pack(:side=>:left, :fill=>:both, :expand=>:true)
|
||||
|
||||
delegate('DEFAULT', @lbox)
|
||||
delegate('background', @frame, @scr)
|
||||
delegate('activebackground', @scr)
|
||||
delegate('troughcolor', @scr)
|
||||
delegate('repeatdelay', @scr)
|
||||
delegate('repeatinterval', @scr)
|
||||
delegate('relief', @frame)
|
||||
delegate('borderwidth', @frame)
|
||||
|
||||
scrollbar(keys.delete('scrollbar')){false}
|
||||
|
||||
configure keys unless keys.empty?
|
||||
end
|
||||
|
||||
############################
|
||||
private
|
||||
############################
|
||||
def _show_up_arrow
|
||||
unless @up_arrow.winfo_mapped?
|
||||
@up_arrow.pack(:side=>:top, :fill=>:x)
|
||||
end
|
||||
end
|
||||
|
||||
def _show_down_arrow
|
||||
unless @down_arrow.winfo_mapped?
|
||||
@down_arrow.pack(:side=>:bottom, :fill=>:x)
|
||||
end
|
||||
end
|
||||
|
||||
def _set_sel(idx)
|
||||
@lbox.activate(idx)
|
||||
@lbox.selection_clear(0, 'end')
|
||||
@lbox.selection_set(idx)
|
||||
end
|
||||
|
||||
def _check_sel(cidx, tidx = nil, bidx = nil)
|
||||
_set_sel(cidx)
|
||||
unless tidx
|
||||
tidx = @lbox.nearest(0)
|
||||
tidx += 1 if tidx > 0
|
||||
end
|
||||
unless bidx
|
||||
bidx = @lbox.nearest(10000)
|
||||
bidx -= 1 if bidx < @lbox.index('end') - 1
|
||||
end
|
||||
if cidx > bidx
|
||||
_set_sel(bidx)
|
||||
end
|
||||
if cidx < tidx
|
||||
_set_sel(tidx)
|
||||
end
|
||||
end
|
||||
|
||||
def _up_proc
|
||||
cidx = @lbox.curselection[0]
|
||||
idx = @lbox.nearest(0)
|
||||
if idx >= 0
|
||||
@lbox.see(idx - 1)
|
||||
_set_sel(idx)
|
||||
@up_arrow.pack_forget if idx == 1
|
||||
@up_timer.stop if idx == 0
|
||||
_show_down_arrow if @lbox.bbox('end') == []
|
||||
end
|
||||
if cidx && cidx > 0 && (idx == 0 || cidx == @lbox.nearest(10000))
|
||||
_set_sel(cidx - 1)
|
||||
end
|
||||
end
|
||||
|
||||
def _down_proc
|
||||
cidx = @lbox.curselection[0]
|
||||
eidx = @lbox.index('end') - 1
|
||||
idx = @lbox.nearest(10000)
|
||||
if idx <= eidx
|
||||
@lbox.see(idx + 1)
|
||||
_set_sel(cidx + 1) if cidx < eidx
|
||||
@down_arrow.pack_forget if idx + 1 == eidx
|
||||
@down_timer.stop if idx == eidx
|
||||
_show_up_arrow if @lbox.bbox(0) == []
|
||||
end
|
||||
if cidx && cidx < eidx && (eidx == idx || cidx == @lbox.nearest(0))
|
||||
_set_sel(cidx + 1)
|
||||
end
|
||||
end
|
||||
|
||||
def _key_UP_proc
|
||||
cidx = @lbox.curselection[0]
|
||||
_set_sel(cidx = @lbox.index('activate')) unless cidx
|
||||
cidx -= 1
|
||||
if cidx == 0
|
||||
@up_arrow.pack_forget
|
||||
elsif cidx == @lbox.nearest(0)
|
||||
@lbox.see(cidx - 1)
|
||||
end
|
||||
end
|
||||
|
||||
def _key_DOWN_proc
|
||||
cidx = @lbox.curselection[0]
|
||||
_set_sel(cidx = @lbox.index('activate')) unless cidx
|
||||
cidx += 1
|
||||
if cidx == @lbox.index('end') - 1
|
||||
@down_arrow.pack_forget
|
||||
elsif cidx == @lbox.nearest(10000)
|
||||
@lbox.see(cidx + 1)
|
||||
end
|
||||
end
|
||||
|
||||
def _config_proc
|
||||
if @lbox.size == 0
|
||||
@up_arrow.pack_forget
|
||||
@down_arrow.pack_forget
|
||||
return
|
||||
end
|
||||
tidx = @lbox.nearest(0)
|
||||
bidx = @lbox.nearest(10000)
|
||||
if tidx > 0
|
||||
_show_up_arrow
|
||||
tidx += 1
|
||||
else
|
||||
@up_arrow.pack_forget unless @up_timer.running?
|
||||
end
|
||||
if bidx < @lbox.index('end') - 1
|
||||
_show_down_arrow
|
||||
bidx -= 1
|
||||
else
|
||||
@down_arrow.pack_forget unless @down_timer.running?
|
||||
end
|
||||
cidx = @lbox.curselection[0]
|
||||
_check_sel(cidx, tidx, bidx) if cidx
|
||||
end
|
||||
|
||||
def _init_binding
|
||||
@up_timer = TkAfter.new(@interval, -1, proc{_up_proc})
|
||||
@down_timer = TkAfter.new(@interval, -1, proc{_down_proc})
|
||||
|
||||
@up_timer.set_start_proc(@initwait, proc{})
|
||||
@down_timer.set_start_proc(@initwait, proc{})
|
||||
|
||||
@up_arrow.bind('Enter', proc{@up_timer.start})
|
||||
@up_arrow.bind('Leave', proc{@up_timer.stop if @up_arrow.winfo_mapped?})
|
||||
@down_arrow.bind('Enter', proc{@down_timer.start})
|
||||
@down_arrow.bind('Leave', proc{@down_timer.stop if @down_arrow.winfo_mapped?})
|
||||
|
||||
@lbox.bind('Configure', proc{_config_proc})
|
||||
@lbox.bind('Enter', proc{|y| _set_sel(@lbox.nearest(y))}, '%y')
|
||||
@lbox.bind('Motion', proc{|y|
|
||||
@up_timer.stop if @up_timer.running?
|
||||
@down_timer.stop if @down_timer.running?
|
||||
_check_sel(@lbox.nearest(y))
|
||||
}, '%y')
|
||||
|
||||
@lbox.bind('Up', proc{_key_UP_proc})
|
||||
@lbox.bind('Down', proc{_key_DOWN_proc})
|
||||
end
|
||||
|
||||
############################
|
||||
public
|
||||
############################
|
||||
def scrollbar(mode)
|
||||
if mode
|
||||
@scr.pack(:side=>:right, :fill=>:y)
|
||||
else
|
||||
@scr.pack_forget
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
################################################
|
||||
|
||||
class TkCombobox < TkEntry
|
||||
include TkComposite
|
||||
|
||||
@@down_btn_bmp = TkBitmapImage.new(:data=><<EOD)
|
||||
#define down_arrow_width 11
|
||||
#define down_arrow_height 11
|
||||
static unsigned char down_arrow_bits[] = {
|
||||
0x00, 0x00, 0xfe, 0x03, 0xfc, 0x01, 0xfc, 0x01, 0xf8, 0x00, 0xf8, 0x00,
|
||||
0x70, 0x00, 0x70, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00};
|
||||
EOD
|
||||
|
||||
@@up_btn_bmp = TkBitmapImage.new(:data=><<EOD)
|
||||
#define up_arrow_width 11
|
||||
#define up_arrow_height 11
|
||||
static unsigned char up_arrow_bits[] = {
|
||||
0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x70, 0x00, 0x70, 0x00, 0xf8, 0x00,
|
||||
0xf8, 0x00, 0xfc, 0x01, 0xfc, 0x01, 0xfe, 0x03, 0x00, 0x00};
|
||||
EOD
|
||||
|
||||
def _button_proc(dir = true)
|
||||
@btn.relief(:sunken)
|
||||
x = @frame.winfo_rootx
|
||||
y = @frame.winfo_rooty
|
||||
if dir
|
||||
@top.geometry("+#{x}+#{y + @frame.winfo_height}")
|
||||
else
|
||||
@btn.image(@@up_btn_bmp)
|
||||
@top.geometry("+#{x}+#{y - @top.winfo_reqheight}")
|
||||
end
|
||||
@top.deiconify
|
||||
@lst.focus
|
||||
|
||||
if (idx = values.index(@ent.value))
|
||||
@lst.see(idx - 1)
|
||||
@lst.activate(idx)
|
||||
@lst.selection_set(idx)
|
||||
elsif @lst.size > 0
|
||||
@lst.see(0)
|
||||
@lst.activate(0)
|
||||
@lst.selection_set(0)
|
||||
end
|
||||
@top.grab
|
||||
|
||||
begin
|
||||
@var.tkwait
|
||||
if (idx = @var.to_i) >= 0
|
||||
@ent.value = @lst.get(idx)
|
||||
end
|
||||
@top.withdraw
|
||||
@btn.relief(:raised)
|
||||
@btn.image(@@down_btn_bmp)
|
||||
rescue
|
||||
ensure
|
||||
begin
|
||||
@top.grab(:release)
|
||||
@ent.focus
|
||||
rescue
|
||||
end
|
||||
end
|
||||
end
|
||||
private :_button_proc
|
||||
|
||||
def _init_bindings
|
||||
@btn.bind('1', proc{_button_proc(true)})
|
||||
@btn.bind('3', proc{_button_proc(false)})
|
||||
|
||||
@lst.bind('1', proc{|y| @var.value = @lst.nearest(y)}, '%y')
|
||||
@lst.bind('Return', proc{@var.value = @lst.curselection[0]})
|
||||
|
||||
cancel = TkVirtualEvent.new('2', '3', 'Escape')
|
||||
@lst.bind(cancel, proc{@var.value = -1})
|
||||
end
|
||||
private :_init_bindings
|
||||
|
||||
def initialize_composite(keys={})
|
||||
keys = _symbolkey2str(keys)
|
||||
|
||||
@btn = TkLabel.new(@frame, :relief=>:raised, :borderwidth=>3,
|
||||
:image=>@@down_btn_bmp).pack(:side=>:right,
|
||||
:ipadx=>2, :fill=>:y)
|
||||
@ent = TkEntry.new(@frame).pack(:side=>:left)
|
||||
@path = @ent.path
|
||||
|
||||
@top = TkToplevel.new(@btn, :borderwidth=>1, :relief=>:raised) {
|
||||
withdraw
|
||||
transient
|
||||
overrideredirect(true)
|
||||
}
|
||||
|
||||
startwait = keys.delete('startwait'){300}
|
||||
interval = keys.delete('interval'){150}
|
||||
@lst = TkAutoScrollbox.new(@top,
|
||||
:startwait=>startwait,
|
||||
:interval=>interval).pack(:fill=>:both,
|
||||
:expand=>true)
|
||||
@ent_list = []
|
||||
|
||||
@var = TkVariable.new
|
||||
|
||||
_init_bindings
|
||||
|
||||
delegate('DEFAULT', @ent)
|
||||
delegate('height', @lst)
|
||||
delegate('relief', @frame)
|
||||
delegate('borderwidth', @frame)
|
||||
|
||||
if mode = keys.delete('scrollbar')
|
||||
scrollbar(mode)
|
||||
end
|
||||
|
||||
configure keys unless keys.empty?
|
||||
end
|
||||
|
||||
def scrollbar(mode)
|
||||
@lst.scrollbar(mode)
|
||||
end
|
||||
|
||||
def _reset_width
|
||||
len = @ent.width
|
||||
@lst.get(0, 'end').each{|l| len = l.length if l.length > len}
|
||||
@lst.width(len + 1)
|
||||
end
|
||||
private :_reset_width
|
||||
|
||||
def add(ent)
|
||||
ent = ent.to_s
|
||||
unless @ent_list.index(ent)
|
||||
@ent_list << ent
|
||||
@lst.insert('end', ent)
|
||||
end
|
||||
_reset_width
|
||||
self
|
||||
end
|
||||
|
||||
def remove(ent)
|
||||
ent = ent.to_s
|
||||
@ent_list.delete(ent)
|
||||
if idx = @lst.get(0, 'end').index(ent)
|
||||
@lst.delete(idx)
|
||||
end
|
||||
_reset_width
|
||||
self
|
||||
end
|
||||
|
||||
def values(ary = nil)
|
||||
if ary
|
||||
@lst.delete(0, 'end')
|
||||
@ent_list.clear
|
||||
ary.each{|ent| add(ent)}
|
||||
_reset_width
|
||||
self
|
||||
else
|
||||
@lst.get(0, 'end')
|
||||
end
|
||||
end
|
||||
|
||||
def see(idx)
|
||||
@lst.see(@lst.index(idx) - 1)
|
||||
end
|
||||
|
||||
def list_index(idx)
|
||||
@lst.index(idx)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
################################################
|
||||
# test
|
||||
################################################
|
||||
if __FILE__ == $0
|
||||
v = TkVariable.new
|
||||
e = TkCombobox.new(:height=>7, :scrollbar=>true, :textvariable=>v,
|
||||
:startwait=>400, :interval=>200).pack
|
||||
e.values(%w(aa bb cc dd ee ff gg hh ii jj kk ll mm nn oo pp qq rr ss tt uu))
|
||||
#e.see(e.list_index('end') - 2)
|
||||
e.value = 'cc'
|
||||
TkFrame.new{|f|
|
||||
fnt = TkFont.new('Helvetica 10')
|
||||
TkLabel.new(f, :font=>fnt, :text=>'TkCombobox value :').pack(:side=>:left)
|
||||
TkLabel.new(f, :font=>fnt, :textvariable=>v).pack(:side=>:left)
|
||||
}.pack
|
||||
|
||||
TkFrame.new(:relief=>:raised, :borderwidth=>2,
|
||||
:height=>3).pack(:fill=>:x, :expand=>true, :padx=>5, :pady=>3)
|
||||
|
||||
l = TkAutoScrollbox.new(nil, :relief=>:groove, :borderwidth=>4,
|
||||
:width=>20).pack(:fill=>:both, :expand=>true)
|
||||
(0..20).each{|i| l.insert('end', "line #{i}")}
|
||||
|
||||
TkFrame.new(:relief=>:ridge, :borderwidth=>3){
|
||||
TkButton.new(self, :text=>'ON',
|
||||
:command=>proc{l.scrollbar(true)}).pack(:side=>:left)
|
||||
TkButton.new(self, :text=>'OFF',
|
||||
:command=>proc{l.scrollbar(false)}).pack(:side=>:right)
|
||||
pack(:fill=>:x)
|
||||
}
|
||||
Tk.mainloop
|
||||
end
|
Loading…
Add table
Reference in a new issue