diff options
95 files changed, 5897 insertions, 208 deletions
@@ -1,3 +1,46 @@ +Sat Mar 26 22:51:33 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb (_callback_entry_class?): add for checking whether + a class is available for a callback entry. + + * ext/tk/lib/tk.rb (after_cancel): add Tk.after_cancel(afterID) method. + + * ext/tk/lib/tk.rb (array2tk_list): change from private module method + of TkComm to public module method. + + * ext/tk/lib/tk.rb (cget): add check that slot argument is not + empty string. + + * ext/tk/lib/tk.rb (configinfo): ditto. + + * ext/tk/lib/tk/itemconfig.rb (itemcget): add check that slot argument + is not empty string. + + * ext/tk/lib/tk/itemconfig.rb (itemconfiginfo): ditto. + + * ext/tk/lib/tk/entry.rb: add TkEntry#icursor and icursor= (alias of + cursor and cursor= method). + + * ext/tk/lib/tk/font.rb: improve font treatment when the font name is + empty string. + + * ext/tk/lib/tk/variable.rb: add :variable, :window and :procedure + type. + + * ext/tk/lib/tk/variable.rb: improve treatment of array-type + tkvariable. + + * ext/tk/lib/tkextlib/blt.rb: add commands for zooming. + + * ext/tk/lib/tkextlib/blt/*: bug fix. + + * ext/tk/lib/tkextlib/treectrl/tktreectrl.rb: bug fix and add methods + to call TreeCtrl commands for bindings. + + * ext/tk/sample/tkextlib/blt/*: new sample scritps. + + * ext/tk/sample/tkextlib/treectrl/*: ditto. + Fri Mar 25 10:53:16 2005 WATANABE Hirofumi <eban@ruby-lang.org> * configure.in (WIN32_LEAN_AND_MEAN): removed because a lot of diff --git a/ext/tk/ChangeLog.tkextlib b/ext/tk/ChangeLog.tkextlib index c27ada6d0..85fd938e3 100644 --- a/ext/tk/ChangeLog.tkextlib +++ b/ext/tk/ChangeLog.tkextlib @@ -1,3 +1,35 @@ +2005-03-26 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * lib/tkextlib/blt.rb: add commands for zooming. + + * lib/tkextlib/blt/bitmap.rb (new_with_name): add for using + given name. + + * lib/tkextlib/blt/busy.rb: bug fix on Tk::BLT::Busy::Shild class. + + * lib/tkextlib/blt/component.rb: typo fix. + + * lib/tkextlib/blt/component.rb: fix lack of *_create methods + + * lib/tkextlib/blt/component.rb: proper call on xaxis_* and so on. + + * lib/tkextlib/blt/htext.rb: add TkVariable object to access + special Tcl variables. + + * ext/tk/lib/tkextlib/treectrl/tktreectrl.rb: typo fix. + + * ext/tk/lib/tkextlib/treectrl/tktreectrl.rb: proper treatment + of 'font' option of element_configure. + + * ext/tk/lib/tkextlib/treectrl/tktreectrl.rb: bug fix on item_sort. + + * ext/tk/lib/tkextlib/treectrl/tktreectrl.rb: add methods to + call TreeCtrl commands for bindings. + + * ext/tk/sample/tkextlib/blt/*: add some sample scripts. + + * ext/tk/sample/tkextlib/treectrl/*: add some sample scripts. + 2005-03-18 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> * lib/tkextlib/treectrl/tktreectrl.rb: bug fix and define some diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb index d246cd9a0..61e76c29b 100644 --- a/ext/tk/lib/tk.rb +++ b/ext/tk/lib/tk.rb @@ -448,7 +448,7 @@ end private_class_method :tk_split_escstr, :tk_split_sublist private_class_method :tk_split_list, :tk_split_simplelist - private_class_method :array2tk_list +# private_class_method :array2tk_list =begin ### --> definition is moved to TkUtil module @@ -583,6 +583,12 @@ end private :_toUTF8, :_fromUTF8 module_function :_toUTF8, :_fromUTF8 + def _callback_entry_class?(cls) + cls <= Proc || cls <= Method || cls <= TkCallbackEntry + end + private :_callback_entry_class? + module_function :_callback_entry_class? + def _callback_entry?(obj) obj.kind_of?(Proc) || obj.kind_of?(Method) || obj.kind_of?(TkCallbackEntry) end @@ -1301,6 +1307,10 @@ module TkCore tk_call_without_enc('after','idle',cmdid) end + def after_cancel(afterId) + tk_call_without_enc('after','cancel',afterId) + end + def windowingsystem tk_call_without_enc('tk', 'windowingsystem') end @@ -2612,7 +2622,12 @@ module TkConfigMethod end def cget(slot) + orig_slot = slot slot = slot.to_s + + if slot.length == 0 + fail ArgumentError, "Invalid option `#{orig_slot.inspect}'" + end if ( method = _symbolkey2str(__methodcall_optkeys)[slot] ) return self.__send__(method) @@ -2698,7 +2713,12 @@ module TkConfigMethod end else + orig_slot = slot slot = slot.to_s + if slot.length == 0 + fail ArgumentError, "Invalid option `#{orig_slot.inspect}'" + end + if ( conf = __keyonly_optkeys.find{|k, v| k.to_s == slot} ) defkey, undefkey = conf if value @@ -2727,7 +2747,8 @@ module TkConfigMethod def configinfo(slot = nil) if TkComm::GET_CONFIGINFO_AS_ARRAY - if (slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) + if (slot && + slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) fontkey = $2 conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")))) conf[__configinfo_struct[:key]] = @@ -2984,7 +3005,8 @@ module TkConfigMethod end else # ! TkComm::GET_CONFIGINFO_AS_ARRAY - if (slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) + if (slot && + slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) fontkey = $2 conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")))) conf[__configinfo_struct[:key]] = @@ -4002,7 +4024,7 @@ end #Tk.freeze module Tk - RELEASE_DATE = '2005-03-14'.freeze + RELEASE_DATE = '2005-03-26'.freeze autoload :AUTO_PATH, 'tk/variable' autoload :TCL_PACKAGE_PATH, 'tk/variable' diff --git a/ext/tk/lib/tk/entry.rb b/ext/tk/lib/tk/entry.rb index 0fe553d55..63051979e 100644 --- a/ext/tk/lib/tk/entry.rb +++ b/ext/tk/lib/tk/entry.rb @@ -27,11 +27,13 @@ class TkEntry<TkLabel def cursor number(tk_send_without_enc('index', 'insert')) end + alias icursor cursor def cursor=(index) tk_send_without_enc('icursor', index) #self index end + alias icursor= cursor= def index(idx) number(tk_send_without_enc('index', idx)) end diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb index 389f001f4..8e63558ca 100644 --- a/ext/tk/lib/tk/font.rb +++ b/ext/tk/lib/tk/font.rb @@ -164,6 +164,7 @@ class TkFont # class methods ################################### def TkFont.actual(fnt, option=nil) + fnt = '{}' if fnt == '' if fnt.kind_of?(TkFont) fnt.actual(option) else @@ -172,6 +173,7 @@ class TkFont end def TkFont.actual_displayof(fnt, win, option=nil) + fnt = '{}' if fnt == '' if fnt.kind_of?(TkFont) fnt.actual_displayof(win, option) else @@ -206,6 +208,7 @@ class TkFont end def TkFont.measure(fnt, text) + fnt = '{}' if fnt == '' if fnt.kind_of?(TkFont) fnt.measure(text) else @@ -214,6 +217,7 @@ class TkFont end def TkFont.measure_displayof(fnt, win, text) + fnt = '{}' if fnt == '' if fnt.kind_of?(TkFont) fnt.measure_displayof(win, text) else @@ -223,6 +227,7 @@ class TkFont end def TkFont.metrics(fnt, option=nil) + fnt = '{}' if fnt == '' if fnt.kind_of?(TkFont) fnt.metrics(option) else @@ -231,6 +236,7 @@ class TkFont end def TkFont.metrics_displayof(fnt, win, option=nil) + fnt = '{}' if fnt == '' if fnt.kind_of?(TkFont) font.metrics_displayof(win, option=nil) else @@ -338,13 +344,17 @@ class TkFont fnt = nil if fnt == [] || fnt == "" unless fnt - TkFont.new(nil, nil).call_font_configure([path, key], *args) + # create dummy + # TkFont.new(nil, nil).call_font_configure([path, key], *args) + dummy_fnt = TkFont.allocate + dummy_fnt.instance_eval{ init_dummy_fontobj() } + dummy_fnt else begin compound = tk_split_simplelist( Hash[*tk_split_simplelist(tk_call('font', 'configure', - fnt))].collect{|key,value| - [key[1..-1], value] + fnt))].collect{|k,v| + [k[1..-1], v] }.assoc('compound')[1]) rescue compound = [] @@ -381,7 +391,51 @@ class TkFont ################################### private ################################### + def init_dummy_fontobj + @id = Tk_FontID.join(TkCore::INTERP._ip_id_) + Tk_FontID[1].succ! + Tk_FontNameTBL[@id] = self + + @latin_desscendant = nil + @kanji_desscendant = nil + + case (Tk::TK_VERSION) + when /^4\.*/ + @latinfont = "" + @kanjifont = "" + if JAPANIZED_TK + @compoundfont = [[@latinfont], [@kanjifont]] + @fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont} + else + @compoundfont = @latinfont + @fontslot = {'font'=>@latinfont} + end + else + @latinfont = @id + 'l' + @kanjifont = @id + 'k' + @compoundfont = @id + 'c' + + if JAPANIZED_TK + tk_call('font', 'create', @latinfont, '-charset', 'iso8859') + tk_call('font', 'create', @kanjifont, '-charset', 'jisx0208.1983') + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont]) + else + tk_call('font', 'create', @latinfont) + tk_call('font', 'create', @kanjifont) + tk_call('font', 'create', @compoundfont) + end + + @fontslot = {'font'=>@compoundfont} + end + + self + end + def initialize(ltn=nil, knj=nil, keys=nil) + ltn = '{}' if ltn == '' + knj = '{}' if knj == '' + # @id = Tk_FontID.join('') @id = Tk_FontID.join(TkCore::INTERP._ip_id_) Tk_FontID[1].succ! @@ -657,10 +711,17 @@ class TkFont end def create_compoundfont_tk8x(ltn, knj, keys) - create_latinfont(ltn) - create_kanjifont(knj) + if knj + create_latinfont(ltn) + create_kanjifont(knj) + else + cfnt = ltn + create_kanjifont(cfnt) + create_latinfont(cfnt) + end @compoundfont = @id + 'c' + if JAPANIZED_TK unless keys keys = {} @@ -735,6 +796,7 @@ class TkFont end if knj + compoundkeys = nil kanjikeys = {} begin actual_core(@kanjifont).each{|key,val| kanjikeys[key] = val} @@ -746,6 +808,17 @@ class TkFont end end + if cfnt + if cfnt.kind_of?(Hash) + compoundkeys = cfnt.dup + else + compoundkeys = {} + actual_core(cfnt).each{|key,val| compoundkeys[key] = val} + end + compoundkeys.update(_symbolkey2str(keys)) + keys = compoundkeys + end + @fontslot = {'font'=>@compoundfont} tk_call('font', 'configure', @compoundfont, *hash_kv(keys)) end @@ -754,11 +827,21 @@ class TkFont ################################### public ################################### + def inspect + sprintf("#<%s:%0x:%s>", self.class.inspect, self.__id__, @compoundfont) + end + def method_missing(id, *args) name = id.id2name case args.length when 1 - configure name, args[0] + if name[-1] == ?= + configure name[0..-2], args[0] + args[0] + else + configure name, args[0] + self + end when 0 begin configinfo name @@ -1099,6 +1182,7 @@ class TkFont alias ascii_metrics latin_metrics ################################### +=begin def dup src = self obj = super() @@ -1111,6 +1195,13 @@ class TkFont obj.instance_eval{ initialize(src) } obj end +=end + def dup + TkFont.new(self) + end + def clone + TkFont.new(self) + end end module TkFont::CoreMethods @@ -1140,6 +1231,8 @@ module TkFont::CoreMethods end def actual_core_tk8x(font, win=nil, option=nil) + font = '{}' if font == '' + if option == 'compound' || option == :compound "" elsif option @@ -1465,6 +1558,8 @@ module TkFont::CoreMethods end def latin_replace_core_tk8x(ltn) + ltn = '{}' if ltn == '' + if JAPANIZED_TK begin tk_call('font', 'delete', '@font_tmp') @@ -1528,6 +1623,8 @@ module TkFont::CoreMethods end def kanji_replace_core_tk8x(knj) + knj = '{}' if knj == '' + if JAPANIZED_TK begin tk_call('font', 'delete', '@font_tmp') @@ -1573,6 +1670,8 @@ module TkFont::CoreMethods end def measure_core_tk8x(font, win, text) + font = '{}' if font == '' + if win number(tk_call('font', 'measure', font, '-displayof', win, text)) @@ -1591,6 +1690,8 @@ module TkFont::CoreMethods end def metrics_core_tk8x(font, win, option=nil) + font = '{}' if font == '' + if option if win number(tk_call('font', 'metrics', font, diff --git a/ext/tk/lib/tk/itemconfig.rb b/ext/tk/lib/tk/itemconfig.rb index f0f13e63b..72225e752 100644 --- a/ext/tk/lib/tk/itemconfig.rb +++ b/ext/tk/lib/tk/itemconfig.rb @@ -6,6 +6,8 @@ require 'tkutil' require 'tk/itemfont.rb' module TkItemConfigOptkeys + include TkUtil + def __item_numval_optkeys(id) [] end @@ -119,8 +121,13 @@ module TkItemConfigMethod ################################################ def itemcget(tagOrId, option) + orig_opt = option option = option.to_s + if option.length == 0 + fail ArgumentError, "Invalid option `#{orig_opt.inspect}'" + end + if ( method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[option] ) return self.__send__(method, tagOrId) end @@ -204,7 +211,12 @@ module TkItemConfigMethod end else + orig_slot = slot slot = slot.to_s + if slot.length == 0 + fail ArgumentError, "Invalid option `#{orig_slot.inspect}'" + end + if ( conf = __item_keyonly_optkeys(tagid(tagOrId)).find{|k, v| k.to_s == slot } ) defkey, undefkey = conf if value @@ -229,7 +241,7 @@ module TkItemConfigMethod def itemconfiginfo(tagOrId, slot = nil) if TkComm::GET_CONFIGINFO_AS_ARRAY - if (slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) + if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) fontkey = $2 conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}")))) conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = @@ -487,7 +499,7 @@ module TkItemConfigMethod end else # ! TkComm::GET_CONFIGINFO_AS_ARRAY - if (slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) + if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) fontkey = $2 conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}")))) conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb index e3a08dfdc..982182c2a 100644 --- a/ext/tk/lib/tk/variable.rb +++ b/ext/tk/lib/tk/variable.rb @@ -109,11 +109,12 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') end self end - def default_value=(val) + def set_default_value(val) @def_default = :val @default_val = val self end + alias default_value= set_default_value def default_proc(cmd = Proc.new) @def_default = :proc @default_val = cmd @@ -129,59 +130,111 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') def default_value_type @type end + def default_element_value_type(idxs) + if idxs.kind_of?(Array) + index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',') + else + index = _get_eval_string(idxs, true) + end + @element_type[index] + end - def default_value_type=(type) + def _set_default_value_type_core(type, idxs) if type.kind_of?(Class) if type == NilClass - @type = nil + type = nil elsif type == Numeric - @type = :numeric + type = :numeric elsif type == TrueClass || type == FalseClass - @type = :bool + type = :bool elsif type == String - @type = :string + type = :string elsif type == Symbol - @type = :symbol + type = :symbol elsif type == Array - @type = :list + type = :list + elsif type <= TkVariable + type = :variable + elsif type <= TkWindow + type = :window + elsif TkComm._callback_entry_class?(type) + type = :procedure else - @type = nil + type = nil end else case(type) when nil - @type = nil + type = nil when :numeric, 'numeric' - @type = :numeric + type = :numeric when true, false, :bool, 'bool' - @type = :bool + type = :bool when :string, 'string' - @type = :string + type = :string when :symbol, 'symbol' - @type = :symbol + type = :symbol when :list, 'list' - @type = :list + type = :list when :numlist, 'numlist' - @type = :numlist + type = :numlist + when :variable, 'variable' + type = :variable + when :window, 'window' + type = :window + when :procedure, 'procedure' + type = :procedure else - self.default_value_type = type.class + return _set_default_value_type_core(type.class, idxs) end end - @type + if idxs + if idxs.kind_of?(Array) + index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',') + else + index = _get_eval_string(idxs, true) + end + @element_type[index] = type + else + @type = type + end + type + end + private :_set_default_value_type_core + + def set_default_value_type(type) + _set_default_value_type_core(type, nil) + self end + alias default_value_type= set_default_value_type - def _to_default_type(val) - return val unless @type + def set_default_element_value_type(idxs, type) + _set_default_value_type_core(type, idxs) + self + end + + def _to_default_type(val, idxs = nil) + if idxs + if idxs.kind_of?(Array) + index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',') + else + index = _get_eval_string(idxs, true) + end + type = @element_type[index] + else + type = @type + end + return val unless type if val.kind_of?(Hash) - val.keys.each{|k| val[k] = _to_default_type(val[k]) } + val.keys.each{|k| val[k] = _to_default_type(val[k], idxs) } val else begin - case(@type) + case(type) when :numeric number(val) when :bool - TkComm + TkComm.bool(val) when :string val when :symbol @@ -190,6 +243,12 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') tk_split_simplelist(val) when :numlist tk_split_simplelist(val).collect!{|v| number(v)} + when :variable + TkVarAccess.new(val) + when :window + TkComm.window(val) + when :procedure + TkComm.procedure(val) else val end @@ -200,6 +259,11 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') end private :_to_default_type + def _to_default_element_type(idxs, val) + _to_default_type(val, idxs) + end + private :_to_default_element_type + def initialize(val="", type=nil) # @id = Tk_VARIABLE_ID.join('') @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_) @@ -213,6 +277,10 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') @trace_elem = nil @trace_opts = nil + @type = nil + var = self + @element_type = Hash.new{|k,v| var.default_value_type } + self.default_value_type = type begin @@ -326,14 +394,15 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') ! is_hash? end - def exist?(idx = nil) + def exist?(*elems) INTERP._invoke_without_enc('global', @id) - if idx + if elems.empty? + TkComm.bool(tk_call('info', 'exist', @id)) + else # array + index = elems.collect{|idx| _get_eval_string(idx, true)}.join(',') TkComm.bool(tk_call('info', 'exist', "#{@id}")) && - TkComm.bool(tk_call('info', 'exist', "#{@id}(#{idx})")) - else - TkComm.bool(tk_call('info', 'exist', @id)) + TkComm.bool(tk_call('info', 'exist', "#{@id}(#{index})")) end end @@ -389,6 +458,7 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS end def value=(val) + val = val._value if !@type && @type != :variable && val.kind_of?(TkVariable) if val.kind_of?(Hash) self.clear val.each{|k, v| @@ -418,11 +488,10 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS end end - def [](*idxs) + def _element_value(*idxs) index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',') begin - # _fromUTF8(INTERP._get_global_var2(@id, index)) - _to_default_type(_fromUTF8(INTERP._get_global_var2(@id, index))) + _fromUTF8(INTERP._get_global_var2(@id, index)) rescue => e case @def_default when :proc @@ -440,6 +509,8 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS def []=(*args) val = args.pop + type = default_element_value_type(args) + val = val._value if !type && type != :variable && val.kind_of?(TkVariable) index = args.collect{|idx| _get_eval_string(idx, true)}.join(',') _fromUTF8(INTERP._set_global_var2(@id, index, _get_eval_string(val, true))) #_fromUTF8(INTERP._set_global_var2(@id, _toUTF8(_get_eval_string(index)), @@ -448,11 +519,12 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS # _get_eval_string(val, true))) end - def unset(elem=nil) - if elem - INTERP._unset_global_var2(@id, _get_eval_string(elem, true)) - else + def unset(*elems) + if elems.empty? INTERP._unset_global_var(@id) + else + index = elems.collect{|idx| _get_eval_string(idx, true)}.join(',') + INTERP._unset_global_var2(@id, index) end end alias remove unset @@ -481,6 +553,7 @@ else end def value=(val) + val = val._value if !@type && @type != :variable && val.kind_of?(TkVariable) begin #s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"' s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"' @@ -530,11 +603,10 @@ else end end - def [](*idxs) + def _element_value(*idxs) index = idxs.collect{|idx| _get_eval_string(idx)}.join(',') begin - # INTERP._eval(Kernel.format('global %s; set %s(%s)', @id, @id, index)) - _to_default_type(INTERP._eval(Kernel.format('global %s; set %s(%s)', @id, @id, index))) + INTERP._eval(Kernel.format('global %s; set %s(%s)', @id, @id, index)) rescue => e case @def_default when :proc @@ -554,6 +626,8 @@ else def []=(*args) val = args.pop + type = default_element_value_type(args) + val = val._value if !type && type != :variable && val.kind_of?(TkVariable) index = args.collect{|idx| _get_eval_string(idx)}.join(',') INTERP._eval(Kernel.format('global %s; set %s(%s) %s', @id, @id, index, _get_eval_string(val))) @@ -565,37 +639,73 @@ else # _get_eval_string(val)) end - def unset(elem=nil) - if elem - INTERP._eval(Kernel.format('global %s; unset %s(%s)', - @id, @id, _get_eval_string(elem))) - #INTERP._eval(Kernel.format('unset %s(%s)', @id, tk_tcl2ruby(elem))) - #INTERP._eval('unset ' + @id + '(' + _get_eval_string(elem) + ')') - else + def unset(*elems) + if elems.empty? INTERP._eval(Kernel.format('global %s; unset %s', @id, @id)) #INTERP._eval(Kernel.format('unset %s', @id)) #INTERP._eval('unset ' + @id) + else + index = elems.collect{|idx| _get_eval_string(idx, true)}.join(',') + INTERP._eval(Kernel.format('global %s; unset %s(%s)', @id, @id, index)) + #INTERP._eval(Kernel.format('global %s; unset %s(%s)', + # @id, @id, _get_eval_string(elem))) + #INTERP._eval(Kernel.format('unset %s(%s)', @id, tk_tcl2ruby(elem))) + #INTERP._eval('unset ' + @id + '(' + _get_eval_string(elem) + ')') end end alias remove unset end - protected :_value + protected :_value, :_element_value def value _to_default_type(_value) end - def value_type=(val) - self.default_value_type = val - self.value=(val) + def [](*idxs) + _to_default_element_type(idxs, _element_value(*idxs)) + end + + def set_value(val) + self.value = val + self + end + + def set_element_value(idxs, val) + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self + end + + def set_value_type(val) + self.default_value_type = val.class + self.value = val + self + end + + alias value_type= set_value_type + + def set_element_value_type(idxs, val) + self.set_default_element_value_type(idxs, val.class) + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self end def numeric number(_value) end - def numeric=(val) + def numeric_element(*idxs) + number(_element_value(*idxs)) + end + def set_numeric(val) case val when Numeric self.value=(val) @@ -604,14 +714,39 @@ end else raise ArgumentError, "Numeric is expected" end - val + self + end + alias numeric= set_numeric + def set_numeric_element(idxs, val) + case val + when Numeric + val + when TkVariable + val = val.numeric + else + raise ArgumentError, "Numeric is expected" + end + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self end - def numeric_type=(val) + def set_numeric_type(val) @type = :numeric self.numeric=(val) + self + end + alias numeric_type= set_numeric_type + def set_numeric_element_type(idxs, val) + self.set_default_element_value_type(idxs, :numeric) + self.set_numeric_element(idxs, val) end def bool + TkComm.bool(_value) +=begin # see Tcl_GetBoolean man-page case _value.downcase when '0', 'false', 'no', 'off' @@ -619,8 +754,12 @@ end else true end +=end + end + def bool_element(*idxs) + TkComm.bool(_element_value(*idxs)) end - def bool=(val) + def set_bool(val) if ! val self.value = '0' else @@ -631,37 +770,216 @@ end self.value = '1' end end + self + end + alias bool= set_bool + def set_bool_element(idxs, val) + if ! val + val = '0' + else + case val.to_s.downcase + when 'false', '0', 'no', 'off' + val = '0' + else + val = '1' + end + end + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self end - def bool_type=(val) + def set_bool_type(val) @type = :bool self.bool=(val) + self + end + alias bool_type= set_bool_type + def set_bool_element_type(idxs, val) + self.set_default_element_value_type(idxs, :bool) + self.set_bool_element(idxs, val) + end + + def variable + TkVarAccess.new(self._value) + end + def variable_element(*idxs) + TkVarAccess.new(_element_value(*idxs)) + end + def set_variable(var) + var = var.id if var.kind_of?(TkVariable) + self.value = var + self + end + alias variable= set_variable + def set_variable_element(idxs, var) + var = var.id if var.kind_of?(TkVariable) + if idxs.kind_of?(Array) + self[*idxs]=var + else + self[idxs]=var + end + self + end + def set_variable_type(var) + @type = :variable + var = var.id if var.kind_of?(TkVariable) + self.value = var + self + end + alias variable_type= set_variable_type + def set_variable_element_type(idxs, var) + self.set_default_element_value_type(idxs, :variable) + self.set_variable_element(idxs, var) + end + + def window + TkComm.window(self._value) + end + def window_element(*idxs) + TkComm.window(_element_value(*idxs)) + end + def set_window(win) + win = win._value if win.kind_of?(TkVariable) + self.value = win + self + end + alias window= set_window + def set_window_element(idxs, win) + win = win._value if win.kind_of?(TkVariable) + if idxs.kind_of?(Array) + self[*idxs]=win + else + self[idxs]=win + end + self + end + def set_window_type(win) + @type = :window + self.window=(win) + self + end + alias window_type= set_window_type + def set_window_element_type(idxs, win) + self.set_default_element_value_type(idxs, :window) + self.set_window_element(idxs, win) + end + + def procedure + TkComm.procedure(self._value) + end + def procedure_element(*idxs) + TkComm.procedure(_element_value(*idxs)) + end + def set_procedure(cmd) + self.value = cmd + self + end + alias procedure= set_procedure + def set_procedure_element(idxs, cmd) + cmd = cmd._value if cmd.kind_of?(TkVariable) + if idxs.kind_of?(Array) + self[*idxs]=cmd + else + self[idxs]=cmd + end + self + end + def set_procedure_type(cmd) + @type = :procedure + self.procedure=(cmd) + self + end + alias procedure_type= set_procedure_type + def set_procedure_element_type(idxs, cmd) + self.set_default_element_value_type(idxs, :procedure) + self.set_proceure_element(idxs, cmd) end def to_i number(_value).to_i end + def element_to_i(*idxs) + number(_element_value(*idxs)).to_i + end def to_f number(_value).to_f end + def element_to_f(*idxs) + number(_element_value(*idxs)).to_f + end def to_s #string(value).to_s _value end - alias string= value= - def string_type=(val) + def element_to_s(*idxs) + _element_value(*idxs) + end + def string_element(*idxs) + _element_value(*idxs) + end + def set_string(val) + val = val._value if val.kind_of?(TkVariable) + self.value=val + self + end + alias string= set_string + def set_string_element(idxs, val) + val = val._value if val.kind_of?(TkVariable) + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self + end + def set_string_type(val) @type = :string - self.value=(val) + self.string=(val) + self + end + alias string_type= set_string_type + def set_string_element_type(idxs, val) + self.set_default_element_value_type(idxs, :string) + self.set_string_element(idxs, val) end def to_sym _value.intern end - alias symbol= value= - def symbol_type=(val) + alias symbol to_sym + def element_to_sym(*idxs) + _element_value(*idxs).intern + end + alias symbol_element element_to_sym + def set_symbol(val) + val = val._value if val.kind_of?(TkVariable) + self.value=val + self + end + alias symbol= set_symbol + def set_symbol_element(idxs, val) + val = val._value if val.kind_of?(TkVariable) + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self + end + def set_symbol_type(val) @type = :symbol self.value=(val) + self + end + alias symbol_type= set_symbol_type + def set_symbol_element_type(idxs, val) + self.set_default_element_value_type(idxs, :symbol) + self.set_symbol_element(idxs, val) end def list @@ -669,12 +987,19 @@ end tk_split_simplelist(_value) end alias to_a list + def list_element(*idxs) + tk_split_simplelist(_element_value(*idxs)) + end + alias element_to_a list_element def numlist list.collect!{|val| number(val)} end + def numlist_element(*idxs) + list_element(*idxs).collect!{|val| number(val)} + end - def list=(val) + def set_list(val) case val when Array self.value=(val) @@ -683,41 +1008,103 @@ end else raise ArgumentError, "Array is expected" end - val + self end - alias numlist= list= + alias list= set_list + + alias set_numlist set_list + alias numlist= set_numlist - def list_type=(val) + def set_list_element(idxs, val) + case val + when Array + val + when TkVariable + val = val.list + else + raise ArgumentError, "Array is expected" + end + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self + end + alias set_numlist_element set_list_element + + def set_list_type(val) @type = :list self.list=(val) + self + end + alias list_type= set_list_type + def set_list_element_type(idxs, val) + self.set_default_element_value_type(idxs, :list) + self.set_list_element(idxs, val) end - def numlist_type=(val) + def set_numlist_type(val) @type = :numlist self.numlist=(val) + self + end + alias numlist_type= set_numlist_type + def set_numlist_element_type(idxs, val) + self.set_default_element_value_type(idxs, :numlist) + self.set_numlist_element(idxs, val) end def lappend(*elems) tk_call('lappend', @id, *elems) self end + def element_lappend(idxs, *elems) + if idxs.kind_of?(Array) + idxs = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',') + end + tk_call('lappend', "#{@id}(#{idxs})", *elems) + self + end def lindex(idx) tk_call('lindex', self._value, idx) end alias lget lindex + def element_lindex(elem_idxs, idx) + if elem_idxs.kind_of?(Array) + val = _element_value(*elem_idxs) + else + val = _element_value(elem_idxs) + end + tk_call('lindex', val, idx) + end + alias element_lget element_lindex def lget_i(idx) number(lget(idx)).to_i end + def element_lget_i(elem_idxs, idx) + number(element_lget(elem_idxs, idx)).to_i + end def lget_f(idx) number(lget(idx)).to_f end + def element_lget_f(elem_idxs, idx) + number(element_lget(elem_idxs, idx)).to_f + end def lset(idx, val) tk_call('lset', @id, idx, val) self end + def element_lset(elem_idxs, idx, val) + if elem_idxs.kind_of?(Array) + idxs = elem_idxs.collect{|i| _get_eval_string(i, true)}.join(',') + end + tk_call('lset', "#{@id}(#{idxs})", idx, val) + self + end def inspect #Kernel.format "#<TkVariable: %s>", @id @@ -823,7 +1210,8 @@ end # false if self is not an assoc array self._value == other else - false + # false + self._value == _get_eval_string(other) end end @@ -842,13 +1230,14 @@ end rescue other = other._value end - end - if other.kind_of?(Numeric) + elsif other.kind_of?(Numeric) begin return self.numeric <=> other rescue return self._value <=> other.to_s end + elsif other.kind_of?(Array) + return self.list <=> other else return self._value <=> other end @@ -1107,7 +1496,6 @@ end end end - class TkVarAccess<TkVariable def self.new(name, *args) return TkVar_ID_TBL[name] if TkVar_ID_TBL[name] @@ -1135,6 +1523,10 @@ class TkVarAccess<TkVariable @trace_elem = nil @trace_opts = nil + @type = nil + var = self + @element_type = Hash.new{|k,v| var.default_value_type } + # teach Tk-ip that @id is global var INTERP._invoke_without_enc('global', @id) diff --git a/ext/tk/lib/tkextlib/SUPPORT_STATUS b/ext/tk/lib/tkextlib/SUPPORT_STATUS index 9cfc02d47..085de3bdf 100644 --- a/ext/tk/lib/tkextlib/SUPPORT_STATUS +++ b/ext/tk/lib/tkextlib/SUPPORT_STATUS @@ -73,6 +73,14 @@ ICONS 1.0 http://www.satisoft.com/tcltk/icons/ ==> ICONS TkImg 1.3 http://sf.net/projects/tkimg ==> tkimg +BLT 2.4z http://sourceforge.net/projects/blt + * see also tcltk-ext library on RAA + (http://raa.ruby-lang.org/) + ==> blt + +TkTreeCtrl 1.1 http://tktreectrl.sourceforge.net/ ==> treectrl + + ===< support (may be alpha or beta quality) >================================= @@ -84,19 +92,12 @@ TclX CVS/Hd(2005-02-07) ==> tclx (partial support; infox command and XPG/3 message catalogs only) -TkTreeCtrl 1.1 http://tktreectrl.sourceforge.net/ ==> treectrl - Tile 0.6 http://tktable.sourceforge.net/tile/ ==> tile ===< possibly available (not tested; alpha quality) >========================= -BLT 2.4z http://sourceforge.net/projects/blt - * see also tcltk-ext library on RAA - (http://raa.ruby-lang.org/) - ==> blt - winico CVS/Hd(2004-11-02) http://tktable.sourceforge.net ==> winico (win32 only) diff --git a/ext/tk/lib/tkextlib/blt.rb b/ext/tk/lib/tkextlib/blt.rb index 965886762..60ed39a0c 100644 --- a/ext/tk/lib/tkextlib/blt.rb +++ b/ext/tk/lib/tkextlib/blt.rb @@ -105,6 +105,47 @@ module Tk #################################################### + def self.active_legend(graph) + tk_call_without_enc('Blt_ActiveLegend', graph) + end + def self.crosshairs(graph) + tk_call_without_enc('Blt_Crosshairs', graph) + end + def self.zoom_stack(graph) + tk_call_without_enc('Blt_ZoomStack', graph) + end + def self.print_key(graph) + tk_call_without_enc('Blt_PrintKey', graph) + end + def self.closest_point(graph) + tk_call_without_enc('Blt_ClosestPoint', graph) + end + + module GraphCommand + def active_legend + tk_call_without_enc('Blt_ActiveLegend', @path) + self + end + def crosshairs + tk_call_without_enc('Blt_Crosshairs', @path) + self + end + def zoom_stack + tk_call_without_enc('Blt_ZoomStack', @path) + self + end + def print_key + tk_call_without_enc('Blt_PrintKey', @path) + self + end + def closest_point + tk_call_without_enc('Blt_ClosestPoint', @path) + self + end + end + + #################################################### + autoload :PlotComponent,'tkextlib/blt/component.rb' autoload :Barchart, 'tkextlib/blt/barchart.rb' diff --git a/ext/tk/lib/tkextlib/blt/barchart.rb b/ext/tk/lib/tkextlib/blt/barchart.rb index 624906b8b..d8ecad834 100644 --- a/ext/tk/lib/tkextlib/blt/barchart.rb +++ b/ext/tk/lib/tkextlib/blt/barchart.rb @@ -14,6 +14,7 @@ module Tk::BLT WidgetClassNames[WidgetClassName] = self include PlotComponent + include GraphCommand def __boolval_optkeys ['bufferelements', 'invertxy'] diff --git a/ext/tk/lib/tkextlib/blt/bitmap.rb b/ext/tk/lib/tkextlib/blt/bitmap.rb index 11ad5883d..31cf8d422 100644 --- a/ext/tk/lib/tkextlib/blt/bitmap.rb +++ b/ext/tk/lib/tkextlib/blt/bitmap.rb @@ -42,26 +42,41 @@ module Tk::BLT alias _new new def new(data, keys={}) - _new(:data, data, keys) + _new(:data, nil, data, keys) end alias define new + def new_with_name(name, data, keys={}) + _new(:data, name, data, keys) + end + alias define_with_name new_with_name + def compose(text, keys={}) - _new(:text, text, keys) + _new(:text, nil, text, keys) + end + + def compose_with_name(name, text, keys={}) + _new(:text, name, text, keys) end end - def initialize(type, data, keys = {}) - @id = BITMAP_ID.join(TkCore::INTERP._ip_id_) - BITMAP_ID[1].succ! - BITMAP_ID_TBL[@id] = self + def initialize(type, name, data, keys = {}) + if name + @id = name + else + @id = BITMAP_ID.join(TkCore::INTERP._ip_id_) + BITMAP_ID[1].succ! + BITMAP_ID_TBL[@id] = self + end @path = @id - if type == :text - tk_call('::blt::bitmap', 'compose', @id, *hash_kv(keys)) - else # :data - tk_call('::blt::bitmap', 'define', @id, *hash_kv(keys)) + unless bool(tk_call('::blt::bitmap', 'exists', @id)) + if type == :text + tk_call('::blt::bitmap', 'compose', @id, data, *hash_kv(keys)) + else # :data + tk_call('::blt::bitmap', 'define', @id, data, *hash_kv(keys)) + end end end diff --git a/ext/tk/lib/tkextlib/blt/busy.rb b/ext/tk/lib/tkextlib/blt/busy.rb index c0740dc2d..4726e466f 100644 --- a/ext/tk/lib/tkextlib/blt/busy.rb +++ b/ext/tk/lib/tkextlib/blt/busy.rb @@ -13,6 +13,27 @@ module Tk::BLT extend TkItemConfigMethod TkCommandNames = ['::blt::busy'.freeze].freeze + + ########################### + + class Shield < TkWindow + def self.shield_path(win) + win = window(win) unless win.kind_of?(TkWindow) + if win.kind_of?(TkToplevel) + win.path + '._Busy' + else + win.path + '_Busy' + end + end + + def initialize(win) + @path = self.class.shield_path(win) + end + end + + def self.shield_path(win) + Tk::BLT::Busy::Shield.shield_path(win) + end end end @@ -30,27 +51,6 @@ class << Tk::BLT::Busy ################################## - class Shield < TkWindow - def self.shield_path(win) - win = window(win) unless win.kind_of?(TkWindow) - if win.kind_of?(TkToplevel) - win.path + '._Busy' - else - win.path + '_Busy' - end - end - - def initialize(win) - @path = self.class.shield_path(win) - end - end - - def shield_path(win) - Tk::BLT::Busy::Shield.shield_path(win) - end - - ################################## - def hold(win, keys={}) tk_call('::blt::busy', 'hold', win, *hash_kv(keys)) end diff --git a/ext/tk/lib/tkextlib/blt/component.rb b/ext/tk/lib/tkextlib/blt/component.rb index 8e36946d0..c5152ddab 100644 --- a/ext/tk/lib/tkextlib/blt/component.rb +++ b/ext/tk/lib/tkextlib/blt/component.rb @@ -34,7 +34,7 @@ module Tk::BLT end private :__item_strval_optkeys - def _item_listval_optkeys(id) + def __item_listval_optkeys(id) ['bindtags'] end private :__item_listval_optkeys @@ -266,8 +266,9 @@ module Tk::BLT @cpath = @chart.path Axis::OBJ_TBL[@cpath][@axis] = self keys = _symbolkey2str(keys) - unless keys.delete['without_creating'] - @chart.axis_create(@axis, keys) + unless keys.delete('without_creating') + # @chart.axis_create(@axis, keys) + tk_call(@chart, 'axis', 'create', @axis, keys) end end @@ -420,8 +421,9 @@ module Tk::BLT @cpath = @chart.path Element::OBJ_TBL[@cpath][@element] = self keys = _symbolkey2str(keys) - unless keys.delete['without_creating'] - @chart.element_create(@element, keys) + unless keys.delete('without_creating') + # @chart.element_create(@element, keys) + tk_call(@chart, 'element', 'create', @element, keys) end end @@ -623,8 +625,9 @@ module Tk::BLT @cpath = @chart.path Pen::OBJ_TBL[@cpath][@pen] = self keys = _symbolkey2str(keys) - unless keys.delete['without_creating'] - @chart.pen_create(@pen, keys) + unless keys.delete('without_creating') + # @chart.pen_create(@pen, keys) + tk_call(@chart, 'pen', 'create', @pen, keys) end end @@ -784,6 +787,24 @@ module Tk::BLT idnum.to_i # 'item id' is an integer number end + def self.create_type(chart, type, keys={}) + args, fontkeys = _parse_create_args(keys) + idnum = tk_call_without_enc(chart.path, 'create', type, *args) + chart.marker_configure(idnum, fontkeys) unless fontkeys.empty? + id = idnum.to_i # 'item id' is an integer number + obj = self.allocate + obj.instance_eval{ + @parent = @chart = chart + @path = chart.path + @id = id + unless Tk::BLT::PlotComponent::MarkerID_TBL[@path] + Tk::BLT::PlotComponent::MarkerID_TBL[@path] = {} + end + Tk::BLT::PlotComponent::MarkerID_TBL[@path][@id] = self + } + obj + end + def initialize(parent, *args) @parent = @chart = parent @path = parent.path @@ -980,12 +1001,10 @@ module Tk::BLT ################### - def marker_create(type, *args) - type.create(self, *args) + def axis_create(id=nil, keys={}) + # tk_send('axis', 'create', tagid(id), keys) + Tk::BLT::PlotComponent::Axis.new(self, id, keys) end - - ################### - def axis_delete(*ids) tk_send('axis', 'delete', *(ids.collect{|id| tagid(id)})) self @@ -1033,6 +1052,10 @@ module Tk::BLT ################### + def element_create(id=nil, keys={}) + # tk_send('element', 'create', tagid(id), keys) + Tk::BLT::PlotComponent::Element.new(self, id, keys) + end def element_activate(id, *indices) tk_send('element', 'activate', tagid(id), *indices) self @@ -1109,6 +1132,10 @@ module Tk::BLT ################### + def pen_create(id=nil, keys={}) + # tk_send('pen', 'create', tagid(id), keys) + Tk::BLT::PlotComponent::Pen.new(self, id, keys) + end def pen_delete(*ids) tk_send('pen', 'delete', *(ids.collect{|id| tagid(id)})) self @@ -1137,6 +1164,28 @@ module Tk::BLT ################### + def marker_create(type, keys={}) + case type + when :text, 'text' + Tk::BLT::PlotComponent::TextMarker.new(self, keys) + when :line, 'line' + Tk::BLT::PlotComponent::LineMarker.new(self, keys) + when :bitmap, 'bitmap' + Tk::BLT::PlotComponent::BitmapMarker.new(self, keys) + when :image, 'image' + Tk::BLT::PlotComponent::ImageMarker.new(self, keys) + when :polygon, 'polygon' + Tk::BLT::PlotComponent::PolygonMarker.new(self, keys) + when :window, 'window' + Tk::BLT::PlotComponent::WindowMarker.new(self, keys) + else + if type.kind_of?(Tk::BLT::PlotComponent::Marker) + type.new(self, keys) + else + Tk::BLT::PlotComponent::Marker.create_type(self, type, keys) + end + end + end def marker_after(id, target=nil) if target tk_send_without_enc('marker', 'after', tagid(id), tagid(target)) @@ -1183,103 +1232,219 @@ module Tk::BLT ################### def xaxis_cget(option) - axis_cget('xaxis', option) + itemcget('xaxis', option) end def xaxis_configure(slot, value=None) - axis_configure('xaxis', slot, value) + itemconfigure('xaxis', slot, value) end def xaxis_configinfo(slot=nil) - axis_configinfo('xaxis', slot) + itemconfiginfo('xaxis', slot) end def current_xaxis_configinfo(slot=nil) - current_axis_configinfo('xaxis', slot) + current_itemconfiginfo('xaxis', slot) + end + def xaxis_bind(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, 'xaxis', 'bind'], context, cmd, *args) + self + end + def xaxis_bind_append(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([path, 'xaxis', 'bind'], context, cmd, *args) + self + end + def xaxis_bind_remove(context) + _bind_remove([path, 'xaxis', 'bind'], context) + self + end + def xaxis_bindinfo(context=nil) + _bindinfo([path, 'xaxis', 'bind'], context) end def xaxis_invtransform(val) - axis_invtransform('xaxis', val) + list(tk_send('xaxis', 'invtransform', val)) end def xaxis_limits - axis_limits('xaxis') + list(tk_send('xaxis', 'limits')) end def xaxis_transform(val) - axis_transform('xaxis', val) + list(tk_send('xaxis', 'transform', val)) end def xaxis_use(target=nil) - axis_use('xaxis', target) + if target + Axis.id2obj(self, tk_send('xaxis', 'use', tagid(target))) + else + Axis.id2obj(self, tk_send('xaxis', 'use')) + end end def x2axis_cget(option) - axis_cget('x2axis', option) + itemcget('x2axis', option) end def x2axis_configure(slot, value=None) - axis_configure('x2axis', slot, value) + itemconfigure('x2axis', slot, value) end def x2axis_configinfo(slot=nil) - axis_configinfo('x2axis', slot) + itemconfiginfo('x2axis', slot) end def current_x2axis_configinfo(slot=nil) - current_axis_configinfo('x2axis', slot) + current_itemconfiginfo('x2axis', slot) + end + def x2axis_bind(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, 'x2axis', 'bind'], context, cmd, *args) + self + end + def x2axis_bind_append(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([path, 'x2axis', 'bind'], context, cmd, *args) + self + end + def x2axis_bind_remove(context) + _bind_remove([path, 'x2axis', 'bind'], context) + self + end + def x2axis_bindinfo(context=nil) + _bindinfo([path, 'x2axis', 'bind'], context) end def x2axis_invtransform(val) - axis_invtransform('x2axis', val) + list(tk_send('x2axis', 'invtransform', val)) end def x2axis_limits - axis_limits('x2axis') + list(tk_send('x2axis', 'limits')) end def x2axis_transform(val) - axis_transform('x2axis', val) + list(tk_send('x2axis', 'transform', val)) end def x2axis_use(target=nil) - axis_use('x2axis', target) + if target + Axis.id2obj(self, tk_send('x2axis', 'use', tagid(target))) + else + Axis.id2obj(self, tk_send('x2axis', 'use')) + end end def yaxis_cget(option) - axis_cget('yaxis', option) + itemcget('yaxis', option) end def yaxis_configure(slot, value=None) - axis_configure('yaxis', slot, value) + itemconfigure('yaxis', slot, value) end def yaxis_configinfo(slot=nil) - axis_configinfo('yaxis', slot) + itemconfiginfo('yaxis', slot) end def current_yaxis_configinfo(slot=nil) - current_axis_configinfo('yaxis', slot) + current_itemconfiginfo('yaxis', slot) + end + def yaxis_bind(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, 'yaxis', 'bind'], context, cmd, *args) + self + end + def yaxis_bind_append(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([path, 'yaxis', 'bind'], context, cmd, *args) + self + end + def yaxis_bind_remove(context) + _bind_remove([path, 'yaxis', 'bind'], context) + self + end + def yaxis_bindinfo(context=nil) + _bindinfo([path, 'yaxis', 'bind'], context) end def yaxis_invtransform(val) - axis_invtransform('yaxis', val) + list(tk_send('yaxis', 'invtransform', val)) end def yaxis_limits - axis_limits('yaxis') + list(tk_send('yaxis', 'limits')) end def yaxis_transform(val) - axis_transform('yaxis', val) + list(tk_send('yaxis', 'transform', val)) end def yaxis_use(target=nil) - axis_use('yaxis', target) + if target + Axis.id2obj(self, tk_send('yaxis', 'use', tagid(target))) + else + Axis.id2obj(self, tk_send('yaxis', 'use')) + end end def y2axis_cget(option) - axis_cget('y2axis', option) + itemcget('y2axis', option) end def y2axis_configure(slot, value=None) - axis_configure('y2axis', slot, value) + itemconfigure('y2axis', slot, value) end def y2axis_configinfo(slot=nil) axis_configinfo('y2axis', slot) end def current_y2axis_configinfo(slot=nil) - current_axis_configinfo('y2axis', slot) + current_itemconfiginfo('y2axis', slot) + end + def y2axis_bind(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, 'y2axis', 'bind'], context, cmd, *args) + self + end + def y2axis_bind_append(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([path, 'y2axis', 'bind'], context, cmd, *args) + self + end + def y2axis_bind_remove(context) + _bind_remove([path, 'y2axis', 'bind'], context) + self + end + def y2axis_bindinfo(context=nil) + _bindinfo([path, 'y2axis', 'bind'], context) end def y2axis_invtransform(val) - axis_invtransform('y2axis', val) + list(tk_send('y2axis', 'invtransform', val)) end def y2axis_limits - axis_limits('y2axis') + list(tk_send('y2axis', 'limits')) end def y2axis_transform(val) - axis_transform('y2axis', val) + list(tk_send('y2axis', 'transform', val)) end def y2axis_use(target=nil) - axis_use('y2axis', target) + if target + Axis.id2obj(self, tk_send('y2axis', 'use', tagid(target))) + else + Axis.id2obj(self, tk_send('y2axis', 'use')) + end end end end diff --git a/ext/tk/lib/tkextlib/blt/graph.rb b/ext/tk/lib/tkextlib/blt/graph.rb index 0c49a70ec..b16c72458 100644 --- a/ext/tk/lib/tkextlib/blt/graph.rb +++ b/ext/tk/lib/tkextlib/blt/graph.rb @@ -14,6 +14,7 @@ module Tk::BLT WidgetClassNames[WidgetClassName] = self include PlotComponent + include GraphCommand def __boolval_optkeys ['bufferelements', 'invertxy'] diff --git a/ext/tk/lib/tkextlib/blt/htext.rb b/ext/tk/lib/tkextlib/blt/htext.rb index 29da9aa87..3bc35b7e1 100644 --- a/ext/tk/lib/tkextlib/blt/htext.rb +++ b/ext/tk/lib/tkextlib/blt/htext.rb @@ -9,6 +9,11 @@ require 'tkextlib/blt.rb' module Tk::BLT class Htext<TkWindow + Htext_Var = TkVarAccess.new_hash('htext') + Htext_Widget = TkVarAccess.new('htext(widget)', :window) + Htext_File = TkVarAccess.new('htext(file)') + Htext_Line = TkVarAccess.new('htext(line)') + include TkItemConfigMethod include Scrollable diff --git a/ext/tk/lib/tkextlib/blt/stripchart.rb b/ext/tk/lib/tkextlib/blt/stripchart.rb index faac8d830..b8cbf8bc3 100644 --- a/ext/tk/lib/tkextlib/blt/stripchart.rb +++ b/ext/tk/lib/tkextlib/blt/stripchart.rb @@ -14,6 +14,7 @@ module Tk::BLT WidgetClassNames[WidgetClassName] = self include PlotComponent + include GraphCommand def __boolval_optkeys ['bufferelements', 'buffergraph', 'invertxy'] diff --git a/ext/tk/lib/tkextlib/blt/table.rb b/ext/tk/lib/tkextlib/blt/table.rb index c80e9ac55..dc9cd0627 100644 --- a/ext/tk/lib/tkextlib/blt/table.rb +++ b/ext/tk/lib/tkextlib/blt/table.rb @@ -256,11 +256,20 @@ class << Tk::BLT::Table container end - def add(container, win=nil, *args) - if win - tk_call('::blt::table', container, _epath(win), *args) - else + def add(container, *args) + if args.empty? tk_call('::blt::table', container) + else + args = args.collect{|arg| + if arg.kind_of?(TkWindow) + _epath(arg) + elsif arg.kind_of?(Array) # index + arg.join(',') + else + arg + end + } + tk_call('::blt::table', container, *args) end end diff --git a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb index 0e8fd86c0..655ad8718 100644 --- a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb +++ b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb @@ -17,6 +17,8 @@ TkPackage.require('treectrl') module Tk class TreeCtrl < TkWindow + BindTag_FileList = TkBindTag.new_by_name('TreeCtrlFileList') + def self.package_version begin TkPackage.require('treectrl') @@ -25,6 +27,9 @@ module Tk end end + HasColumnCreateCommand = + (TkPackage.vcompare(self.package_version, '1.1') >= 0) + # dummy :: # pkgIndex.tcl of TreeCtrl-1.0 doesn't support auto_load for # 'loupe' command (probably it is bug, I think). @@ -146,7 +151,7 @@ module Tk::TreeCtrl::ConfigMethod None when 'dragimage' - obj + None when 'element' obj @@ -155,7 +160,7 @@ module Tk::TreeCtrl::ConfigMethod obj when 'marquee' - obj + None when 'notify' obj @@ -171,6 +176,10 @@ module Tk::TreeCtrl::ConfigMethod def tagid(mixed_id) if mixed_id == 'debug' ['debug', None] + elsif mixed_id == 'dragimage' + ['dragimage', None] + elsif mixed_id == 'marquee' + ['marquee', None] elsif mixed_id.kind_of?(Array) [mixed_id[0], treectrl_tagid(*mixed_id)] else @@ -237,6 +246,17 @@ module Tk::TreeCtrl::ConfigMethod end private :__item_configinfo_struct + + def __item_font_optkeys(id) + if id.kind_of?(Array) && (id[0] == 'element' || + (id[0].kind_of?(Array) && id[0][1] == 'element')) + [] + else + ['font'] + end + end + private :__item_font_optkeys + def __item_numstrval_optkeys(id) if id == 'debug' ['displaydelay'] @@ -249,14 +269,28 @@ module Tk::TreeCtrl::ConfigMethod def __item_boolval_optkeys(id) if id == 'debug' ['data', 'display', 'enable'] + elsif id == 'dragimage' + ['visible'] + elsif id == 'marquee' + ['visible'] elsif id.kind_of?(Array) case id[0] + when 'item' + ['button', 'visible'] when 'column' ['button', 'expand', 'squeeze', 'sunken', 'visible', 'widthhack'] when 'element' ['filled', 'showfocus'] + when 'notify' + ['active'] + when 'style' + ['detach'] else - super(id) + if id[0].kind_of?(Array) && id[0][1] == 'element' + ['filled', 'showfocus'] + else + super(id) + end end else super(id) @@ -280,8 +314,14 @@ module Tk::TreeCtrl::ConfigMethod ['itembackground'] when 'element' ['relief'] + when 'style' + ['union'] else - [] + if id[0].kind_of?(Array) && id[0][1] == 'element' + ['relief'] + else + [] + end end else [] @@ -328,17 +368,17 @@ module Tk::TreeCtrl::ConfigMethod current_itemconfiginfo('debug', slot) end - def dragimage_cget(tagOrId, option) - itemcget(['dragimage', tagOrId], option) + def dragimage_cget(option) + itemcget('dragimage', option) end - def dragimage_configure(tagOrId, slot, value=None) - itemconfigure(['dragimage', tagOrId], slot, value) + def dragimage_configure(slot, value=None) + itemconfigure('dragimage', slot, value) end - def dragimage_configinfo(tagOrId, slot=nil) - itemconfiginfo(['dragimage', tagOrId], slot) + def dragimage_configinfo(slot=nil) + itemconfiginfo('dragimage', slot) end - def current_dragimage_configinfo(tagOrId, slot=nil) - current_itemconfiginfo(['dragimage', tagOrId], slot) + def current_dragimage_configinfo(slot=nil) + current_itemconfiginfo('dragimage', slot) end def element_cget(tagOrId, option) @@ -380,17 +420,17 @@ module Tk::TreeCtrl::ConfigMethod current_itemconfiginfo([['item', 'element'], [item, column, elem]], slot) end - def marquee_cget(tagOrId, option) - itemcget(['marquee', tagOrId], option) + def marquee_cget(option) + itemcget('marquee', option) end - def marquee_configure(tagOrId, slot, value=None) - itemconfigure(['marquee', tagOrId], slot, value) + def marquee_configure(slot, value=None) + itemconfigure('marquee', slot, value) end - def marquee_configinfo(tagOrId, slot=nil) - itemconfiginfo(['marquee', tagOrId], slot) + def marquee_configinfo(slot=nil) + itemconfiginfo('marquee', slot) end - def current_marquee_configinfo(tagOrId, slot=nil) - current_itemconfiginfo(['marquee', tagOrId], slot) + def current_marquee_configinfo(slot=nil) + current_itemconfiginfo('marquee', slot) end def notify_cget(win, pattern, option) @@ -757,17 +797,20 @@ class Tk::TreeCtrl end alias item_first_child item_firstchild - def item_hashbutton(item, st=None) + def item_hasbutton(item, st=None) if st == None - bool(tk_send('item', 'hashbutton')) + bool(tk_send('item', 'hasbutton')) else - tk_send('item', 'hashbutton', st) + tk_send('item', 'hasbutton', st) self end end - def item_hashbutton?(item) - item_hashbutton(item) + alias item_has_button item_hasbutton + + def item_hasbutton?(item) + item_hasbutton(item) end + alias item_has_button? item_hasbutton? def item_index(item) list(tk_send('item', 'index', item)) @@ -811,8 +854,8 @@ class Tk::TreeCtrl end alias item_next_sibling item_nextsibling - def item_numchildren() - number(tk_send('item', 'numchildren')) + def item_numchildren(item) + number(tk_send('item', 'numchildren', item)) end alias item_num_children item_numchildren alias item_children_size item_numchildren @@ -850,10 +893,10 @@ class Tk::TreeCtrl opts = opts.collect{|param| if param.kind_of?(Hash) param = _symbolkey2str(param) - if param.key('column') + if param.key?('column') key = '-column' desc = param.delete('column') - elsif param.key('element') + elsif param.key?('element') key = '-element' desc = param.delete('element') else @@ -863,7 +906,7 @@ class Tk::TreeCtrl if param.empty? param = None else - param = __conv_item_keyonly_opts(item, param).to_a + param = hash_kv(__conv_item_keyonly_opts(item, param)) end if key @@ -874,7 +917,7 @@ class Tk::TreeCtrl elsif param.kind_of?(Array) if param[2].kind_of?(Hash) - param[2] = __conv_item_keyonly_opts(item, param[2]).to_a + param[2] = hash_kv(__conv_item_keyonly_opts(item, param[2])) end param @@ -898,17 +941,15 @@ class Tk::TreeCtrl end private :_item_sort_core - def item_sort_not_really(item, *opts) - _item_sort_core(false, item, *opts) - end - def item_sort(item, *opts) _item_sort_core(true, item, *opts) end + def item_sort_not_really(item, *opts) + _item_sort_core(false, item, *opts) + end def item_state_forcolumn(item, column, *args) tk_send('item', 'state', 'forcolumn', item, column, *args) - self end alias item_state_for_column item_state_forcolumn @@ -922,7 +963,6 @@ class Tk::TreeCtrl def item_state_set(item, *args) tk_send('item', 'state', 'set', item, *args) - self end def item_style_elements(item, column) @@ -1230,7 +1270,8 @@ class Tk::TreeCtrl def _conv_style_layout_val(sty, val) case sty.to_s when 'padx', 'pady', 'ipadx', 'ipady' - number(val) + lst = list(val) + (lst.size == 1)? lst[0]: lst when 'detach' bool(val) when 'union' @@ -1256,6 +1297,7 @@ class Tk::TreeCtrl else ret = Hash.new Hash[*simplelist(tk_send('style', 'layout', style, elem))].each{|k, v| + k = k[1..-1] ret[k] = _conv_style_layout_val(k, v) } ret @@ -1599,18 +1641,20 @@ class Tk::TreeCtrl::Item < TkObject end alias first_child firstchild - def hashbutton(st=None) + def hasbutton(st=None) if st == None - @tree.item_hashbutton(@id) + @tree.item_hasbutton(@id) else - @tree.item_hashbutton(@id, st) + @tree.item_hasbutton(@id, st) self end end + alias has_button hasbutton - def hashbutton? - @tree.item_hashbutton(@id) + def hasbutton? + @tree.item_hasbutton(@id) end + alias has_button? hasbutton? def index @tree.item_index(@id) @@ -1685,6 +1729,10 @@ class Tk::TreeCtrl::Item < TkObject def sort(*opts) @tree.item_sort(@id, *opts) end + def sort_not_really(*opts) + @tree.item_sort_not_really(@id, *opts) + self + end def state_forcolumn(column, *args) @tree.item_state_forcolumn(@id, column, *args) @@ -1829,3 +1877,149 @@ class Tk::TreeCtrl::Style < TkObject end end end + +module Tk::TreeCtrl::BindCallback + include Tk + extend Tk +end + +class << Tk::TreeCtrl::BindCallback + def cursorCheck(w, x, y) + tk_call('::TreeCtrl::CursorCheck', w, x, y) + end + def cursorCheckAux(w) + tk_call('::TreeCtrl::CursorCheckAux', w) + end + def cursorCancel(w) + tk_call('::TreeCtrl::CursorCancel', w) + end + def buttonPress1(w, x, y) + tk_call('::TreeCtrl::ButtonPress1', w, x, y) + end + def doubleButton1(w, x, y) + tk_call('::TreeCtrl::DoubleButton1', w, x, y) + end + def motion1(w, x, y) + tk_call('::TreeCtrl::Motion1', w, x, y) + end + def leave1(w, x, y) + tk_call('::TreeCtrl::Leave1', w, x, y) + end + def release1(w, x, y) + tk_call('::TreeCtrl::Release1', w, x, y) + end + def beginSelect(w, el) + tk_call('::TreeCtrl::BeginSelect', w, el) + end + def motion(w, le) + tk_call('::TreeCtrl::Motion', w, el) + end + def beginExtend(w, el) + tk_call('::TreeCtrl::BeginExtend', w, el) + end + def beginToggle(w, el) + tk_call('::TreeCtrl::BeginToggle', w, el) + end + def cancelRepeat + tk_call('::TreeCtrl::CancelRepeat') + end + def autoScanCheck(w, x, y) + tk_call('::TreeCtrl::AutoScanCheck', w, x, y) + end + def autoScanCheckAux(w) + tk_call('::TreeCtrl::AutoScanCheckAux', w) + end + def autoScanCancel(w) + tk_call('::TreeCtrl::AutoScanCancel', w) + end + def up_down(w, n) + tk_call('::TreeCtrl::UpDown', w, n) + end + def left_right(w, n) + tk_call('::TreeCtrl::LeftRight', w, n) + end + def setActiveItem(w, idx) + tk_call('::TreeCtrl::SetActiveItem', w, idx) + end + def extendUpDown(w, amount) + tk_call('::TreeCtrl::ExtendUpDown', w, amount) + end + def dataExtend(w, el) + tk_call('::TreeCtrl::DataExtend', w, el) + end + def cancel(w) + tk_call('::TreeCtrl::Cancel', w) + end + def selectAll(w) + tk_call('::TreeCtrl::selectAll', w) + end + def marqueeBegin(w, x, y) + tk_call('::TreeCtrl::MarqueeBegin', w, x, y) + end + def marqueeUpdate(w, x, y) + tk_call('::TreeCtrl::MarqueeUpdate', w, x, y) + end + def marqueeEnd(w, x, y) + tk_call('::TreeCtrl::MarqueeEnd', w, x, y) + end + def scanMark(w, x, y) + tk_call('::TreeCtrl::ScanMark', w, x, y) + end + def scanDrag(w, x, y) + tk_call('::TreeCtrl::ScanDrag', w, x, y) + end + + # filelist-bindings + def fileList_button1(w, x, y) + tk_call('::TreeCtrl::FileListButton1', w, x, y) + end + def fileList_motion1(w, x, y) + tk_call('::TreeCtrl::FileListMotion1', w, x, y) + end + def fileList_motion(w, x, y) + tk_call('::TreeCtrl::FileListMotion', w, x, y) + end + def fileList_leave1(w, x, y) + tk_call('::TreeCtrl::FileListLeave1', w, x, y) + end + def fileList_release1(w, x, y) + tk_call('::TreeCtrl::FileListRelease1', w, x, y) + end + def fileList_edit(w, i, s, e) + tk_call('::TreeCtrl::FileListEdit', w, i, s, e) + end + def fileList_editCancel(w) + tk_call('::TreeCtrl::FileListEditCancel', w) + end + def fileList_autoScanCheck(w, x, y) + tk_call('::TreeCtrl::FileListAutoScanCheck', w, x, y) + end + def fileList_autoScanCheckAux(w) + tk_call('::TreeCtrl::FileListAutoScanCheckAux', w) + end + + def entryOpen(w, item, col, elem) + tk_call('::::TreeCtrl::EntryOpen', w, item, col, elem) + end + def entryExpanderOpen(w, item, col, elem) + tk_call('::TreeCtrl::EntryExpanderOpen', w, item, col, elem) + end + def entryClose(w, accept) + tk_call('::TreeCtrl::EntryClose', w, accept) + end + def entryExpanderKeypress(w) + tk_call('::TreeCtrl::EntryExpanderKeypress', w) + end + def textOpen(w, item, col, elem, width=0, height=0) + tk_call('::TreeCtrl::TextOpen', w, item, col, elem, width, height) + end + def textExpanderOpen(w, item, col, elem, width) + tk_call('::TreeCtrl::TextOpen', w, item, col, elem, width) + end + def textClose(w, accept) + tk_call('::TreeCtrl::TextClose', w, accept) + end + def textExpanderKeypress(w) + tk_call('::TreeCtrl::TextExpanderKeypress', w) + end +end diff --git a/ext/tk/sample/tkextlib/blt/barchart5.rb b/ext/tk/sample/tkextlib/blt/barchart5.rb new file mode 100644 index 000000000..db181d10c --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/barchart5.rb @@ -0,0 +1,101 @@ +#!/usr/bin/env ruby +require 'tk' +require 'tkextlib/blt' + +load File.join(File.dirname(File.expand_path(__FILE__)), + 'scripts', 'stipples.rb') + +TkOption.add('*graph.x.Title', 'X Axis Label') +TkOption.add('*graph.y.Title', 'Y Axis Label') +TkOption.add('*graph.title', 'A Simple Barchart') +TkOption.add('*graph.x.Font', 'Times 10') +TkOption.add('*graph.Element.Relief', :raised) + +visual = Tk.root.winfo_screenvisual +if visual != 'staticgray' && visual != 'grayscale' + TkOption.add('*graph.LineMarker.color', 'yellow') + TkOption.add('*graph.Element.Background', 'white') + TkOption.add('*graph.Legend.activeForeground', 'pink') + TkOption.add('*print.background', 'yellow') + TkOption.add('*quit.background', 'red') + TkOption.add('*graph.background', 'palegreen') + TkOption.add('*graph.plotBackground', 'lightblue') +end + +htext = Tk::BLT::Htext.new(:widgetname=>'.htext', :text=><<EOD) + This is an example of the barchart widget. The barchart has + many components; x and y axis, legend, crosshairs, elements, etc. + To create a postscript file "bar.ps", press the %% + + ruby { + b = TkButton.new(Tk::BLT::Htext::Htext_Widget.window, + :widgetname=>'print', :text=>'Print', + :command=>proc{ + $graph.postsript(:output=>'bar.ps') + }) + Tk::BLT::Htext::Htext_Widget.window.append(b) + } + +%% button. +%% + + ruby { + $graph = Tk::BLT::Barchart.new(:widgetname=>'.htext.graph', + :relief=>:raised, :borderwidth=>2) + $graph.xaxis_configure(:rotate=>90, :stepsize=>0) + Tk::BLT::Htext::Htext_Widget.window.append($graph, + :fill=>:both, :padx=>4) + } + +%% + Hit the %% + + ruby { + b = TkButton.new(Tk::BLT::Htext::Htext_Widget.window, + :widgetname=>'quit', :text=>'Quit', + :command=>proc{ exit }) + Tk::BLT::Htext::Htext_Widget.window.append(b) + } + +%% button when you've seen enough.%% + + ruby { + l = TkLabel.new(Tk::BLT::Htext::Htext_Widget.window, :bitmap=>'BLT') + Tk::BLT::Htext::Htext_Widget.window.append(l, :padx=>20) + } + +%% +EOD + +names = %w(One Two Three Four Five Six Seven Eight) +if visual == 'staticgray' || visual == 'grayscale' + fgcolors = %w(white white white white white white white white) + bgcolors = %w(black black black black black black black black) +else + fgcolors = %w(yellow orange red magenta purple blue cyan green) + bgcolors = %w(yellow4 orange4 red4 magenta4 purple4 blue4 cyan4 green4) +end + +numColors = names.length + +Tk::TCL_PRECISION.value = 15 + +x = Tk::BLT::Vector.new +y = Tk::BLT::Vector.new +x.seq(-5.0, 5.0, 0.2) +y.expr("sin(#{x})") +barWidth = 0.19 + +$graph.element_create('sin', :relief=>:raised, :borderwidth=>1, + :x=>x, :y=>y, :barwidth=>barWidth) + +Tk::BLT::Table.add(Tk.root, htext, :fill=>:both) + +Tk.root.minsize(0, 0) + +Tk::BLT.zoom_stack($graph) +Tk::BLT.crosshairs($graph) +Tk::BLT.active_legend($graph) +Tk::BLT.closest_point($graph) + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/blt/graph7.rb b/ext/tk/sample/tkextlib/blt/graph7.rb new file mode 100644 index 000000000..27fbe53d9 --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/graph7.rb @@ -0,0 +1,40 @@ +#!/usr/bin/env ruby +require 'tk' +require 'tkextlib/blt' + +length = 250000 +graph = Tk::BLT::Graph.new(:title=>"Scatter Plot\n#{length} points") +graph.xaxis_configure(:loose=>false, :title=>'X Axis Label') +graph.yaxis_configure(:title=>'Y Axis Label') +graph.legend_configure(:activerelief=>:sunken, :background=>'') + +Tk::BLT::Table.add(Tk.root, graph, [0,0], :fill=>:both) + +v_x = Tk::BLT::Vector.new(length) +v_y = Tk::BLT::Vector.new(length) +v_x.expr("random(#{v_x})") +v_y.expr("random(#{v_y})") +v_x.sort(v_y) + +plot = Tk::BLT::PlotComponent::Element.new(graph, :symbol=>:square, + :color=>'green4', :fill=>'green2', + :linewidth=>0, :outlinewidth=>1, + :pixels=>4, :label=>'plot', + :xdata=>v_x, :ydata=>v_y) + +Tk.root.minsize(0, 0) + +#graph.zoom_stack +#graph.crosshairs +#graph.active_legend +#graph.closest_point +Tk::BLT.zoom_stack(graph) +Tk::BLT.crosshairs(graph) +Tk::BLT.active_legend(graph) +Tk::BLT.closest_point(graph) + +Tk::BLT::Busy.hold(graph) +Tk.update +Tk::BLT::Busy.release(graph) + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/blt/graph7a.rb b/ext/tk/sample/tkextlib/blt/graph7a.rb new file mode 100644 index 000000000..a014f72fc --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/graph7a.rb @@ -0,0 +1,63 @@ +#!/usr/bin/env ruby +require 'tk' +require 'tkextlib/blt' + +file = File.join(File.dirname(File.expand_path(__FILE__)), + 'images', 'buckskin.gif') +bgTexture = TkPhotoImage.new(:file=>file) + +TkOption.add('*Graph.Tile', bgTexture) +TkOption.add('*Label.Tile', bgTexture) +TkOption.add('*Frame.Tile', bgTexture) +TkOption.add('*Htext.Tile', bgTexture) +TkOption.add('*TileOffset', 0) +TkOption.add('*HighlightThickness', 0) +TkOption.add('*Element.ScaleSybols', false) +TkOption.add('*Element.Smooth', :linear) +TkOption.add('*activeLine.Color', 'yellow4') +TkOption.add('*activeLine.Fill', 'yellow') +TkOption.add('*activeLine.LineWidth', 0) +TkOption.add('*Element.Pixels', 3) +TkOption.add('*Graph.halo', '7i') + +if Tk.root.winfo_screenvisual != 'staticgray' + TkOption.add('*print.background', 'yellow') + TkOption.add('*quit.background', 'red') +end + +length = 250000 +graph = Tk::BLT::Graph.new(:title=>"Scatter Plot\n#{length} points") +graph.xaxis_configure(:loose=>false, :title=>'X Axis Label') +graph.yaxis_configure(:title=>'Y Axis Label') +graph.legend_configure(:activerelief=>:sunken, :background=>'') + +Tk::BLT::Table.add(Tk.root, graph, [0,0], :fill=>:both) + +v_x = Tk::BLT::Vector.new(length) +v_y = Tk::BLT::Vector.new(length) +v_x.expr("random(#{v_x})") +v_y.expr("random(#{v_y})") +v_x.sort(v_y) + +plot = Tk::BLT::PlotComponent::Element.new(graph, :symbol=>:square, + :color=>'green4', :fill=>'green2', + :linewidth=>0, :outlinewidth=>1, + :pixels=>4, :label=>'plot', + :xdata=>v_x, :ydata=>v_y) + +Tk.root.minsize(0, 0) + +#graph.zoom_stack +#graph.crosshairs +#graph.active_legend +#graph.closest_point +Tk::BLT.zoom_stack(graph) +Tk::BLT.crosshairs(graph) +Tk::BLT.active_legend(graph) +Tk::BLT.closest_point(graph) + +Tk::BLT::Busy.hold(graph) +Tk.update +Tk::BLT::Busy.release(graph) + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/blt/graph7b.rb b/ext/tk/sample/tkextlib/blt/graph7b.rb new file mode 100644 index 000000000..c589f18d8 --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/graph7b.rb @@ -0,0 +1,41 @@ +#!/usr/bin/env ruby +require 'tk' +require 'tkextlib/blt' + +length = 250000 +graph = Tk::BLT::Graph.new(:title=>"Scatter Plot\n#{length} points") +graph.xaxis_configure(:loose=>false, :title=>'X Axis Label') +graph.yaxis_configure(:title=>'Y Axis Label') +graph.legend_configure(:activerelief=>:sunken, :background=>'') + +Tk::BLT::Table.add(Tk.root, graph, [0,0], :fill=>:both) + +x = Array.new(length) +y = Array.new(length) +(0...length).each{|i| + x[i] = rand + y[i] = rand +} + +plot = Tk::BLT::PlotComponent::Element.new(graph, :symbol=>:square, + :color=>'green4', :fill=>'green2', + :linewidth=>0, :outlinewidth=>1, + :pixels=>4, :label=>'plot', + :xdata=>x, :ydata=>y) + +Tk.root.minsize(0, 0) + +#graph.zoom_stack +#graph.crosshairs +#graph.active_legend +#graph.closest_point +Tk::BLT.zoom_stack(graph) +Tk::BLT.crosshairs(graph) +Tk::BLT.active_legend(graph) +Tk::BLT.closest_point(graph) + +Tk::BLT::Busy.hold(graph) +Tk.update +Tk::BLT::Busy.release(graph) + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/blt/graph7c.rb b/ext/tk/sample/tkextlib/blt/graph7c.rb new file mode 100644 index 000000000..495b66f4a --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/graph7c.rb @@ -0,0 +1,45 @@ +#!/usr/bin/env ruby +require 'tk' +require 'tkextlib/blt' + +length = 250000 +graph = Tk::BLT::Graph.new(:title=>"Scatter Plot\n#{length} points") +graph.xaxis_configure(:loose=>false, :title=>'X Axis Label') +graph.yaxis_configure(:title=>'Y Axis Label') +graph.legend_configure(:activerelief=>:sunken, :background=>'') + +Tk::BLT::Table.add(Tk.root, graph, [0,0], :fill=>:both) + +v_x = Tk::BLT::Vector.new(length) +v_y = Tk::BLT::Vector.new(length) +x = Array.new(length) +y = Array.new(length) +(0...length).each{|i| + x[i] = rand + y[i] = rand +} +v_x.set(x) +v_y.set(y) + +plot = Tk::BLT::PlotComponent::Element.new(graph, :symbol=>:square, + :color=>'green4', :fill=>'green2', + :linewidth=>0, :outlinewidth=>1, + :pixels=>4, :label=>'plot', + :xdata=>v_x, :ydata=>v_y) + +Tk.root.minsize(0, 0) + +#graph.zoom_stack +#graph.crosshairs +#graph.active_legend +#graph.closest_point +Tk::BLT.zoom_stack(graph) +Tk::BLT.crosshairs(graph) +Tk::BLT.active_legend(graph) +Tk::BLT.closest_point(graph) + +Tk::BLT::Busy.hold(graph) +Tk.update +Tk::BLT::Busy.release(graph) + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/blt/images/buckskin.gif b/ext/tk/sample/tkextlib/blt/images/buckskin.gif Binary files differnew file mode 100644 index 000000000..e2d7be9d6 --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/images/buckskin.gif diff --git a/ext/tk/sample/tkextlib/blt/images/qv100.t.gif b/ext/tk/sample/tkextlib/blt/images/qv100.t.gif Binary files differnew file mode 100644 index 000000000..1e738ee86 --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/images/qv100.t.gif diff --git a/ext/tk/sample/tkextlib/blt/images/sample.gif b/ext/tk/sample/tkextlib/blt/images/sample.gif Binary files differnew file mode 100644 index 000000000..1d8a4010c --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/images/sample.gif diff --git a/ext/tk/sample/tkextlib/blt/plot1.rb b/ext/tk/sample/tkextlib/blt/plot1.rb new file mode 100644 index 000000000..07dff4829 --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/plot1.rb @@ -0,0 +1,9 @@ +#!/usr/bin/env ruby +require 'tk' +require 'tkextlib/blt' + +graph = Tk::BLT::Graph.new.pack +plot = Tk::BLT::PlotComponent::Element.new(graph, :linewidth=>0, :label=>'foo') +plot.data([[1.0, 3.4], [1.1, 2.8], [1.2, 3.1], [1.4, 2.9]].flatten) + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/blt/plot1b.rb b/ext/tk/sample/tkextlib/blt/plot1b.rb new file mode 100644 index 000000000..eb41e361f --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/plot1b.rb @@ -0,0 +1,10 @@ +#!/usr/bin/env ruby +require 'tk' +require 'tkextlib/blt' + +graph = Tk::BLT::Graph.new.pack +plot = graph.element_create +plot.configure(:linewidth=>0, :label=>'foo', + :data=>[[1.0, 3.4], [1.1, 2.8], [1.2, 3.1], [1.4, 2.9]].flatten) + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/blt/readme.txt b/ext/tk/sample/tkextlib/blt/readme.txt new file mode 100644 index 000000000..fe12dd88a --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/readme.txt @@ -0,0 +1,2 @@ +The scripts and image files in this directory are based on demo files +of Tcl/Tk's BLT extention. diff --git a/ext/tk/sample/tkextlib/blt/scripts/stipples.rb b/ext/tk/sample/tkextlib/blt/scripts/stipples.rb new file mode 100644 index 000000000..47f3c4d06 --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/scripts/stipples.rb @@ -0,0 +1,156 @@ +$stipples = {} unless $stipples + +$stipples['bdiagonal1'] = Tk::BLT::Bitmap.new(<<EOD) +#define bdiagonal1_width 8 +#define bdiagonal1_height 8 +static unsigned char bdiagonal1_bits[] = { + 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11}; +EOD + +$stipples['bdiagonal2'] = Tk::BLT::Bitmap.new(<<EOD) +#define bdiagonal2_width 8 +#define bdiagonal2_height 8 +static unsigned char bdiagonal2_bits[] = { + 0x08, 0x04, 0x02, 0x01, 0x80, 0x40, 0x20, 0x10}; +EOD + +$stipples['checker2'] = Tk::BLT::Bitmap.new(<<EOD) +#define checker2_width 8 +#define checker2_height 8 +static unsigned char checker2_bits[] = { + 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc}; +EOD + + +$stipples['checker3'] = Tk::BLT::Bitmap.new(<<EOD) +#define checker3_width 8 +#define checker3_height 8 +static unsigned char checker3_bits[] = { + 0x0f, 0x0f, 0x0f, 0x0f, 0xf0, 0xf0, 0xf0, 0xf0}; +EOD + +$stipples['cross1'] = Tk::BLT::Bitmap.new(<<EOD) +#define cross1_width 8 +#define cross1_height 8 +static unsigned char cross_bits[] = { + 0xff, 0xaa, 0xff, 0xaa, 0xff, 0xaa, 0xff, 0xaa}; +EOD + +$stipples['cross2'] = Tk::BLT::Bitmap.new(<<EOD) +#define cross2_width 8 +#define cross2_height 8 +static unsigned char cross2_bits[] = { + 0xff, 0x88, 0x88, 0x88, 0xff, 0x88, 0x88, 0x88}; +EOD + +$stipples['cross3'] = Tk::BLT::Bitmap.new(<<EOD) +#define cross3_width 8 +#define cross3_height 8 +static unsigned char cross3_bits[] = { + 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; +EOD + +$stipples['crossdiag'] = Tk::BLT::Bitmap.new(<<EOD) +#define crossdiag_width 8 +#define crossdiag_height 8 +static unsigned char crossdiag2_bits[] = { + 0x18, 0x24, 0x42, 0x81, 0x81, 0x42, 0x24, 0x18}; +EOD + +$stipples['dot1'] = Tk::BLT::Bitmap.new(<<EOD) +#define dot1_width 8 +#define dot1_height 8 +static unsigned char dot1_bits[] = { + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa}; +EOD + +$stipples['dot2'] = Tk::BLT::Bitmap.new(<<EOD) +#define dot2_width 8 +#define dot2_height 8 +static unsigned char dot2_bits[] = { + 0x55, 0x00, 0x55, 0x00, 0x55, 0x00, 0x55, 0x00}; +EOD + +$stipples['dot3'] = Tk::BLT::Bitmap.new(<<EOD) +#define dot3_width 8 +#define dot3_height 8 +static unsigned char dot3_bits[] = { + 0x11, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00}; +EOD + +$stipples['dot4'] = Tk::BLT::Bitmap.new(<<EOD) +#define dot4_width 8 +#define dot4_height 8 +static unsigned char dot4_bits[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +EOD + +$stipples['fdiagonal1'] = Tk::BLT::Bitmap.new(<<EOD) +#define fdiagonal1_width 8 +#define fdiagonal1_height 8 +static unsigned char fdiagonal1_bits[] = { + 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88}; +EOD + +$stipples['fdiagonal2'] = Tk::BLT::Bitmap.new(<<EOD) +#define fdiagonal2_width 8 +#define fdiagonal2_height 8 +static unsigned char fdiagonal2_bits[] = { + 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08}; +EOD + +$stipples['hline1'] = Tk::BLT::Bitmap.new(<<EOD) +#define hline1_width 8 +#define hline1_height 8 +static unsigned char hline1_bits[] = { + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00}; +EOD + +$stipples['hline2'] = Tk::BLT::Bitmap.new(<<EOD) +#define hline2_width 8 +#define hline2_height 8 +static unsigned char hline2_bits[] = { + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00}; +EOD + +$stipples['lbottom'] = Tk::BLT::Bitmap.new(<<EOD) +#define lbottom_width 8 +#define lbottom_height 8 +static unsigned char lbottom_bits[] = { + 0x00, 0x11, 0x11, 0x77, 0x00, 0x11, 0x11, 0x77}; +EOD + +$stipples['ltop'] = Tk::BLT::Bitmap.new(<<EOD) +#define ltop_width 8 +#define ltop_height 8 +static unsigned char ltop_bits[] = { + 0xee, 0x88, 0x88, 0x00, 0xee, 0x88, 0x88, 0x00}; +EOD + +$stipples['rbottom'] = Tk::BLT::Bitmap.new(<<EOD) +#define rbottom_width 8 +#define rbottom_height 8 +static unsigned char rbottom_bits[] = { + 0x00, 0x88, 0x88, 0xee, 0x00, 0x88, 0x88, 0xee}; +EOD + +$stipples['rtop'] = Tk::BLT::Bitmap.new(<<EOD) +#define rtop_width 8 +#define rtop_height 8 +static unsigned char rtop_bits[] = { + 0x77, 0x11, 0x11, 0x00, 0x77, 0x11, 0x11, 0x00}; +EOD + +$stipples['vline1'] = Tk::BLT::Bitmap.new(<<EOD) +#define vline1_width 8 +#define vline1_height 8 +static unsigned char vline1_bits[] = { + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}; +EOD + +$stipples['vline2'] = Tk::BLT::Bitmap.new(<<EOD) +#define vline2_width 8 +#define vline2_height 8 +static unsigned char vline2_bits[] = { + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33}; +EOD diff --git a/ext/tk/sample/tkextlib/blt/winop1.rb b/ext/tk/sample/tkextlib/blt/winop1.rb new file mode 100644 index 000000000..e94138cd9 --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/winop1.rb @@ -0,0 +1,40 @@ +#!/usr/bin/env ruby +require 'tk' +require 'tkextlib/blt' + +file = File.join(File.dirname(File.expand_path(__FILE__)), + 'images', 'sample.gif') +if File.exist?(file) + src = TkPhotoImage.new(:file=>file) +else + fail RuntimeError, 'no image file' +end + +width = src.width +height = src.height + +TkOption.add('*Label.font', '*helvetica*10*') +TkOption.add('*Label.background', 'white') + +l_img0 = TkLabel.new(:image=>src) +l_hdr0 = TkLabel.new(:text=>"#{width} x #{height}") +l_ftr0 = TkLabel.new(:text=>'100%') +Tk.root.background('white') + +(2..10).each{|i| + iw = width/i + ih = height/i + r = '%6g'%(100.0/i) + dst = TkPhotoImage.new(:width=>iw, :height=>ih) + Tk::BLT::Winop.image_resample(src, dst, :sinc) + l_hdr = TkLabel.new(:text=>"#{iw} x #{ih}") + l_ftr = TkLabel.new(:text=>"#{r}%") + l_img = TkLabel.new(:image=>dst) + Tk::BLT::Table.add(Tk.root, + [0,i], l_hdr, + [1,i], l_img, + [2,i], l_ftr) + Tk.update +} + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/blt/winop2.rb b/ext/tk/sample/tkextlib/blt/winop2.rb new file mode 100644 index 000000000..1f674ee89 --- /dev/null +++ b/ext/tk/sample/tkextlib/blt/winop2.rb @@ -0,0 +1,28 @@ +#!/usr/bin/env ruby +require 'tk' +require 'tkextlib/blt' + +file = File.join(File.dirname(File.expand_path(__FILE__)), + 'images', 'qv100.t.gif') +if File.exist?(file) + src = TkPhotoImage.new(:file=>file) +else + fail RuntimeError, 'no image file' +end + +width = src.width +height = src.height + +TkOption.add('*Label.font', '*helvetica*10*') +TkOption.add('*Label.background', 'white') + +[0, 90, 180, 270, 360, 45].each_with_index{|r, i| + dest = TkPhotoImage.new + Tk::BLT::Winop.image_rotate(src, dest, r) + l_txt = TkLabel.new(:text=>"#{r} degrees") + l_img = TkLabel.new(:image=>dest) + Tk::BLT::Table.add(Tk.root, [0,i], l_img, [1,i], l_txt) + Tk.update +} + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/treectrl/bitmaps.rb b/ext/tk/sample/tkextlib/treectrl/bitmaps.rb new file mode 100644 index 000000000..c621e61fd --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/bitmaps.rb @@ -0,0 +1,75 @@ +# +# Demo: Bitmaps +# +def demoBitmaps(t) + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false, + :selectmode=>:browse, :orient=>:horizontal, :wrap=>'5 items', + :showheader=>false, :backgroundimage=>@images['sky']) + else + t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false, + :selectmode=>:browse, :orient=>:horizontal, :wrap=>'5 items', + :showheader=>false) + end + + if $HasColumnCreate + t.column_create(:itembackground=>['gray90', []]) + else + t.column_configure(0, :itembackground=>['gray90', []]) + end + + t.element_create('elemTxt', :text, + :fill=>[@SystemHighlightText, ['selected', 'focus']]) + t.element_create('elemSelTxt', :rect, :showfocus=>true, + :fill=>[@SystemHighlight, ['selected', 'focus']]) + t.element_create('elemSelBmp', :rect, :outlinewidth=>4, + :outline=>[@SystemHighlight, ['selected', 'focus']]) + t.element_create('elemBmp', :bitmap, + :foreground=>[@SystemHighlight, ['selected', 'focus']], + :background=>'linen', + :bitmap=>['question' ['selected']]) + + s = t.style_create('STYLE', :orient=>:vertical) + t.style_elements(s, ['elemSelBmp', 'elemBmp', 'elemSelTxt', 'elemTxt']) + t.style_layout(s, 'elemSelBmp', :union=>'elemBmp', :ipadx=>6, :ipady=>6) + t.style_layout(s, 'elemBmp', :pady=>[0, 6], :expand=>:we) + t.style_layout(s, 'elemSelTxt', :union=>'elemTxt', :ipadx=>2) + t.style_layout(s, 'elemTxt', :expand=>:we) + + # Set default item style + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.defaultstyle = [s] + end + + bitmap_names = %w(error gray75 gray50 gray25 gray12 + hourglass info questhead question warning) + + bitmap_names.each{|name| + i = t.item_create + unless (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_style_set(i, 0, s) + end + t.item_text(i, 0, name) + t.item_element_configure(i, 0, 'elemBmp', :bitmap=>name) + t.item_lastchild(:root, i) + } + + bitmap_names.each{|name| + i = t.item_create + t.item_style_set(i, 0, s) + t.item_text(i, 0, name) + if true + t.item_element_configure(i, 0, 'elemBmp', :bitmap=>name, + :foreground=>['brown', ''], + :background=>['', '']) + else + t.item_element_configure(i, 0, 'elemBmp', :bitmap=>name, + :foreground=>[ + @SystemHighlight, ['selected', 'focus'], + 'brown', [] + ], + :background=>['', []]) + end + t.item_lastchild(:root, i) + } +end diff --git a/ext/tk/sample/tkextlib/treectrl/demo.rb b/ext/tk/sample/tkextlib/treectrl/demo.rb new file mode 100644 index 000000000..1f822a654 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/demo.rb @@ -0,0 +1,1256 @@ +#!/usr/bin/env ruby + +require 'tk' +require 'tkextlib/treectrl' + +$ScriptDir = File.dirname(File.expand_path(__FILE__)) + +$HasColumnCreate = Tk::TreeCtrl::HasColumnCreateCommand + +class TkTreeCtrl_demo + def initialize(dir) + @ScriptDir = dir || '.' + + @thisPlatform = Tk::PLATFORM['platform'] + if @thisPlatform == 'unix' && Tk.windowingsystem == 'aqua' + @thisPlatform = 'macosx' + end + + @RandomN = [500] + + @images = Hash.new + @sel_images = Hash.new + + @popup = Hash.new + @mTree = Hash.new + @mHeader = Hash.new + + @non_clear_list = [] + + @demoCmd = Hash.new + @demoFile = Hash.new + + # Get default colors + w = TkListbox.new + @SystemButtonFace = w[:highlightbackground] + @SystemHighlight = w[:selectbackground] + @SystemHighlightText = w[:selectforeground] + w.destroy + + #################### + + make_source_window() + make_menubar() + make_main_window() + make_list_popup() + make_header_popup() + + init_pics('sky') + + #################### + + @tree2.bind('ButtonPress-3', + proc{|w, x, y, rootx, rooty| + show_list_popup(w, x, y, rootx, rooty) + }, '%W %x %y %X %Y') + + # Allow "scan" bindings + if @thisPlatform == 'windows' + @tree2.bind_remove('Control-ButtonPress-3') + end + + #################### + + init_demo_scripts_module() + load_demo_scripts() + init_demo_list() + + #################### + + @tree1.notify_bind(@tree1, 'Selection', + proc{|c, t| + if c == 1 + item = t.selection_get[0] + demo_set(@demoCmd[item], @demoFile[item]) + end + }, '%c %T') + + # When one item is selected in the demo list, display the styles in + # that item. + # See DemoClear for why the tag "DontDelete" is used + @tree2.notify_bind('DontDelete', 'Selection', + proc{|c, t| + display_styles_in_item(t.selection_get[0]) if c == 1 + }, '%c %T') + end + + ########################## + + def init_pics(*args) + args.each{|pat| + pat = "#{pat}.gif" + unless TkImage.names.find{|img| (name = @images.key(img)) && File.fnmatch(pat, name)} + Dir.glob(File.join(@ScriptDir, 'pics', pat)).each{|file| + name = File.basename(file, '.gif') + img = TkPhotoImage.new(:file=>file) + @images[name] = img + @sel_images[name] = TkPhotoImage.new + @sel_images[name].copy(img) + Tk::TreeCtrl.image_tint(@sel_images[name], @SystemHighlight, 128) + } + end + } + end + + ########################## + + private + + def make_menubar + menuspec = [ + [['File']] + ] + if Tk::PLATFORM['platform'] != 'unix' + TkConsole.eval('.console conf -height 8') + menuspec[0] << ['Console', proc{ + if TkComm.bool(TkConsole.eval('winfo ismapped .')) + TkConsole.hide + else + TkConsole.show + end + }] + end + menuspec[0] << ['View Source', proc{toggle_source_window()}] + menuspec[0] << ['Quit', proc{exit}] + Tk.root.add_menubar(menuspec) + end + + def make_source_window + @src_top = TkToplevel.new + f = TkFrame.new(@src_top, :borderwidth=>0) + case @thisPlatform + when 'macintosh', 'macos' + font = TkFont.new(['Geneva', 9]) + when 'unix' + font = TkFont.new(['Courier', -12]) + else + font = TkFont.new(['Courier', 9]) + end + + @src_txt = TkText.new(f, :font=>font, :tabs=>font.measure('1234'), + :wrap=>:none) + xscr = @src_txt.xscrollbar(TkScrollbar.new(f)) + yscr = @src_txt.yscrollbar(TkScrollbar.new(f)) + + f.pack(:expand=>true, :fill=>:both) + f.grid_columnconfigure(0, :weight=>1) + f.grid_rowconfigure(0, :weight=>1) + @src_txt.grid(:row=>0, :column=>0, :sticky=>:news) + xscr.grid(:row=>1, :column=>0, :sticky=>:we) + yscr.grid(:row=>0, :column=>1, :sticky=>:ns) + + @src_top.protocol('WM_DELETE_WINDOW', proc{@src_top.withdraw}) + @src_top.geometry('-0+0') + @src_top.withdraw + end + + def show_source(file) + @src_top.title("Demo Source: #{file}") + @src_txt.value = IO.read(File.join(@ScriptDir, file)) + @src_txt.set_insert('1.0') + end + + def toggle_source_window + if @src_top.winfo_mapped? + @src_top.withdraw + else + @src_top.deiconify + end + end + + def tree_plus_scrollbars_in_a_frame(parent, h, v) + f = TkFrame.new(parent, :borderwidth=>1, :relief=>:sunken) + case @thisPlatform + when 'macintosh' + font = TkFont.new(['Geneva', 9]) + when 'macos' + font = TkFont.new(['Lucida Grande', 11]) + when 'unix' + font = TkFont.new(['Helvetica', -12]) + else + # There is a bug on my Win98 box with Tk_MeasureChars() and + # MS Sans Serif 8. + font = TkFont.new(['MS Sans', 8]) + end + + tree = Tk::TreeCtrl.new(f, :highlightthickness=>0, + :borderwidth=>0, :font=>font) + tree[:xscrollincrement] = 20 + tree.debug_configure(:enable=>false, :display=>false) + + if h + h_scr = TkScrollbar.new(f, :orient=>:horizontal, + :command=>proc{|*args| tree.xview(*args)}) + tree.notify_bind(h_scr, 'Scroll-x', + proc{|w, l, u| w.set(l, u)}, '%W %l %u') + h_scr.bind('ButtonPress-1', proc{tree.set_focus}) + end + + if v + v_scr = TkScrollbar.new(f, :orient=>:vertical, + :command=>proc{|*args| tree.yview(*args)}) + tree.notify_bind(v_scr, 'Scroll-y', + proc{|w, l, u| w.set(l, u)}, '%W %l %u') + v_scr.bind('ButtonPress-1', proc{tree.set_focus}) + end + + f.grid_columnconfigure(0, :weight=>1) + f.grid_rowconfigure(0, :weight=>1) + tree.grid(:row=>0, :column=>0, :sticky=>:news) + h_scr.grid(:row=>1, :column=>0, :sticky=>:we) if h + v_scr.grid(:row=>0, :column=>1, :sticky=>:ns) if v + + [f, tree] + end + + def make_main_window + Tk.root.title('Tk::TreeCtrl Demo') + + case @thisPlatform + when 'macintosh', 'macosx' + Tk.root.geometry('+40+40') + else + Tk.root.geometry('+0+30') + end + + pane1 = TkPanedWindow.new(:orient=>:vertical, :borderwidth=>0) + pane2 = TkPanedWindow.new(:orient=>:horizontal, :borderwidth=>0) + + # Tree + scrollbar: demos + f1, @tree1 = tree_plus_scrollbars_in_a_frame(nil, false, true) + @tree1.configure(:showbuttons=>false, :showlines=>:false, + :showroot=>false, :height=>100) + if $HasColumnCreate + @tree1.column_create(:text=>'List of Demos', + :expand=>true, :button=>false) + else + @tree1.column_configure(0, :text=>'List of Demos', + :expand=>true, :button=>false) + end + + # Tree + scrollbar: styles + elements in list + f4, @tree4 = tree_plus_scrollbars_in_a_frame(nil, false, true) + @tree4.configure(:showroot=>false, :height=>140) + if $HasColumnCreate + @tree4.column_create(:text=>'Elements and Styles', + :expand=>true, :button=>false) + else + @tree4.column_configure(0, :text=>'Elements and Styles', + :expand=>true, :button=>false) + end + + # Tree + scrollbar: styles + elements in selected item + f3, @tree3 = tree_plus_scrollbars_in_a_frame(nil, false, true) + @tree3.configure(:showroot=>false) + if $HasColumnCreate + @tree3.column_create(:text=>'Styles in Item', + :expand=>true, :button=>false) + else + @tree3.column_configure(0, :text=>'Styles in Item', + :expand=>true, :button=>false) + end + + pane1.add(f1, f4, f3, :height=>150) + pane1.pack(:expand=>true, :fill=>:both) + + # Frame on right + f2_base = TkFrame.new + + # Tree + scrollbars + f2, @tree2 = tree_plus_scrollbars_in_a_frame(f2_base, true, true) + @tree2.configure(:indent=>19) + @tree2.debug_configure(:enable=>false, :display=>true, + :erasecolor=>'pink', :displaydelay=>30) + + # Give it a big border to debug drawing + @tree2.configure(:borderwidth=>6, :relief=>:ridge, :highlightthickness=>3) + + f2_base.grid_columnconfigure(0, :weight=>1) + f2_base.grid_rowconfigure(0, :weight=>1) + f2.grid(:row=>0, :column=>0, :sticky=>:news, :pady=>0) + + pane2.add(pane1, :width=>200) + pane2.add(f2_base, :width=>450) + + pane2.pack(:expand=>true, :fill=>:both) + + ### + # A treectrl widget can generate the following built-in events: + # <ActiveItem> called when the active item changes + # <Collapse-before> called before an item is closed + # <Collapse-after> called after an item is closed + # <Expand-before> called before an item is opened + # <Expand-after> called after an item is opened + # <Selection> called when items are added to or removed from the selection + # <Scroll-x> called when horizontal scroll position changes + # <Scroll-y> called when vertical scroll position changes + # + # The application programmer can define custom events to be + # generated by the "T notify generate" command. The following events + # are generated by the example bindings. + + @tree2.notify_install_event('Header') + @tree2.notify_install_detail('Header', 'invoke') + + @tree2.notify_install_event('Drag') + @tree2.notify_install_detail('Drag', 'begin') + @tree2.notify_install_detail('Drag', 'end') + @tree2.notify_install_detail('Drag', 'receive') + + @tree2.notify_install_event('Edit') + @tree2.notify_install_detail('Edit', 'accept') + end + + def make_list_popup + @popup[:bgimg] = TkVariable.new + @popup[:bgmode] = TkVariable.new + @popup[:debug] = Hash.new{|h, k| h[k] = TkVariable.new} + @popup[:doublebuffer] = TkVariable.new + @popup[:linestyle] = TkVariable.new + @popup[:orient] = TkVariable.new + @popup[:selectmode] = TkVariable.new + @popup[:show] = Hash.new{|h, k| h[k] = TkVariable.new} + + menuspec = [ + [ 'Collapse', [], nil, '', {:menu_config=>{:tearoff=>false}} ], + + [ 'Expand', [], nil, '', {:menu_config=>{:tearoff=>false}} ] + ] + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + menuspec << \ + [ 'Background Image', + [ + [ 'none', [@popup[:bgimg], 'none'], nil, '', + {:command=>proc{@tree2.backgroundimage = ''}} ], + [ 'sky', [@popup[:bgimg], 'sky'], nil, '', + {:command=>proc{ + @tree2.backgroundimage = @images[@popup[:bgimg].value]}} ] + ], + nil, '', {:menu_config=>{:tearoff=>false}} + ] + end + + menuspec.concat([ + [ 'Background Mode', + %w(column index row visindex).collect{|val| + [ val, [@popup[:bgmode], val] , nil, '', + {:command=>proc{@tree2.backgroundmode = @popup[:bgmode].value}} ] + }, + nil, '', {:menu_config=>{:tearoff=>false}} + ], + + [ 'Debug', + [ + [ 'Data', @popup[:debug][:data], nil, '', + {:command=>proc{ + @tree2.debug_configure(:data=>@popup[:debug][:data].value) + } + } ], + [ 'Display', @popup[:debug][:display], nil, '', + {:command=>proc{ + @tree2.debug_configure(:display=>@popup[:debug][:display].value) + } + } ], + [ 'Enable', @popup[:debug][:enable], nil, '', + {:command=>proc{ + @tree2.debug_configure(:enable=>@popup[:debug][:enable].value) + } + } ] + ], + nil, '', {:menu_config=>{:tearoff=>false}} + ], + + [ 'Buffering', + [ + [ 'none', [@popup[:doublebuffer], 'none'], nil, '', + {:command=>proc{ + @tree2.doublebuffer = @popup[:doublebuffer].value + } + } ], + [ 'item', [@popup[:doublebuffer], 'item'], nil, '', + {:command=>proc{ + @tree2.doublebuffer = @popup[:doublebuffer].value + } + } ], + [ 'window', [@popup[:doublebuffer], 'window'], nil, '', + {:command=>proc{ + @tree2.doublebuffer = @popup[:doublebuffer].value + } + } ] + ], + nil, '', {:menu_config=>{:tearoff=>false}} + ], + + [ 'Line style', + [ + [ 'dot', [@popup[:linestyle], 'dot'], nil, '', + {:command=>proc{@tree2.linestyle = @popup[:linestyle].value}} ], + [ 'solid', [@popup[:linestyle], 'solid'], nil, '', + {:command=>proc{@tree2.linestyle = @popup[:linestyle].value}} ] + ], + nil, '', {:menu_config=>{:tearoff=>false}} + ], + + [ 'Orient', + [ + [ 'Horizontal', [@popup[:orient], 'horizontal'], nil, '', + {:command=>proc{@tree2.orient = @popup[:orient].value}} ], + [ 'Vertical', [@popup[:orient], 'vertical'], nil, '', + {:command=>proc{@tree2.orient = @popup[:orient].value}} ] + ], + nil, '', {:menu_config=>{:tearoff=>false}} + ], + + [ 'Selectmode', + %w(list browse extended multiple single).collect{|val| + [ val, [@popup[:selectmode], val] , nil, '', + {:command=>proc{@tree2.selectmode = @popup[:selectmode].value}} ] + }, + nil, '', {:menu_config=>{:tearoff=>false}} + ], + + [ 'Show', + [ + [ 'Buttons', @popup[:show][:buttons], nil, '', + {:command=>proc{ + @tree2.showbuttons = @popup[:show][:buttons].value + } + } ], + [ 'Header', @popup[:show][:header], nil, '', + {:command=>proc{ + @tree2.showheader = @popup[:show][:header].value + } + } ], + [ 'Lines', @popup[:show][:lines], nil, '', + {:command=>proc{ + @tree2.showlines = @popup[:show][:lines].value + } + } ], + [ 'Root', @popup[:show][:root], nil, '', + {:command=>proc{ + @tree2.showroot = @popup[:show][:root].value + } + } ], + [ 'Root Button', @popup[:show][:rootbutton], nil, '', + {:command=>proc{ + @tree2.showrootbutton = @popup[:show][:rootbutton].value + } + } ] + ], + nil, '', {:menu_config=>{:tearoff=>false}} + ], + + [ 'Visible', [], nil, '', {:menu_config=>{:tearoff=>false}} ] + ]) + + m = TkMenu.new_menuspec(menuspec, @tree2, false) + @non_clear_list << m + @mTree[@tree2] = m + end + + def show_list_popup(w, x, y, rootx, rooty) + id = w.identify(x, y) + unless id.empty? + if id[0] == 'header' + col = id[1] + @popup[:column].value = col + @popup[:arrow].value = w.column_cget(col, :arrow) + @popup[:arrowside].value = w.column_cget(col, :arrowside) + @popup[:arrowgravity].value = w.column_cget(col, :arrowgravity) + @popup[:expand].value = w.column_cget(col, :expand) + @popup[:sqeeeze].value = w.column_cget(col, :squeeze) + @popup[:justify].value = w.column_cget(col, :justify) + @mHeader[w].popup(rootx, rooty) + return + end + end + + m = @mTree[w].entrycget('Collapse', :menu) + m.delete(0, :end) + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + m.add_command(:label=>'All', :command=>proc{w.item_collapse(:all)}) + else + m.add_command(:label=>'All', :command=>proc{w.collapse(:all)}) + end + unless id.empty? + if id[0] == 'item' + item = id[1] + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + m.add_command(:label=>"Item #{item}", + :command=>proc{w.item_collapse(item)}) + m.add_command(:label=>"Item #{item} (recurse)", + :command=>proc{w.item_collapse_recurse(item)}) + else + m.add_command(:label=>"Item #{item}", + :command=>proc{w.collapse(item)}) + m.add_command(:label=>"Item #{item} (recurse)", + :command=>proc{w.collapse_recurse(item)}) + end + end + end + + m = @mTree[w].entrycget('Expand', :menu) + m.delete(0, :end) + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + m.add_command(:label=>'All', :command=>proc{w.item_expand(:all)}) + else + m.add_command(:label=>'All', :command=>proc{w.expand(:all)}) + end + unless id.empty? + if id[0] == 'item' + item = id[1] + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + m.add_command(:label=>"Item #{item}", + :command=>proc{w.item_expand(item)}) + m.add_command(:label=>"Item #{item} (recurse)", + :command=>proc{w.item_expand_recurse(item)}) + else + m.add_command(:label=>"Item #{item}", + :command=>proc{w.expand(item)}) + m.add_command(:label=>"Item #{item} (recurse)", + :command=>proc{w.expand_recurse(item)}) + end + end + end + + [:data, :display, :enable].each{|k| + @popup[:debug][k].value = w.debug_cget(k) + } + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + @popup[:bgimg].value = @images.key(w[:backgroundimage]) + end + @popup[:bgmode].value = w[:backgroundmode] + @popup[:doublebuffer].value = w[:doublebuffer] + @popup[:linestyle].value = w[:linestyle] + @popup[:orient].value = w[:orient] + @popup[:selectmode].value = w[:selectmode] + @popup[:show][:buttons].value = w[:showbuttons] + @popup[:show][:header].value = w[:showheader] + @popup[:show][:lines].value = w[:showlines] + @popup[:show][:root].value = w[:showroot] + @popup[:show][:rootbutton].value = w[:showrootbutton] + + m = @mTree[w].entrycget('Visible', :menu) + m.delete(0, :end) + @popup[:visible] = [] + (0...(w.numcolumns)).each{|i| + @popup[:visible][i] = TkVariable.new(w.column_cget(i, :visible)) + txt = w.column_cget(i, :text) + img_name = w.column_cget(i, :image) + img_name = @images.key(img_name) if img_name.kind_of?(TkImage) + m.add_checkbutton(:variable=>@popup[:visible][i], + :label=>"Column #{i} \"#{txt}\" [#{img_name}]", + :command=>proc{w.column_configure(i, :visible=>@popup[:visible][i].value)}) + } + + @mTree[w].popup(rootx, rooty) + end + + def make_header_popup + @popup[:column] = TkVariable.new unless @popup[:column] + @popup[:arrow] = TkVariable.new + @popup[:arrowside] = TkVariable.new + @popup[:arrowgravity] = TkVariable.new + @popup[:expand] = TkVariable.new + @popup[:squeeze] = TkVariable.new + @popup[:justify] = TkVariable.new + + menuspec = [ + [ 'Arrow', + [ + [ 'None', [@popup[:arrow], 'none'], nil, '', + {:command=>proc{ + @tree2.column_configure(@popup[:column].value, :arrow=>:none) + } + } ], + [ 'Up', [@popup[:arrow], 'up'], nil, '', + {:command=>proc{ + @tree2.column_configure(@popup[:column].value, :arrow=>:up) + } + } ], + [ 'Down', [@popup[:arrow], 'down'], nil, '', + {:command=>proc{ + @tree2.column_configure(@popup[:column].value, :arrow=>:down) + } + } ], + + '---', + + [ 'Side Left', [@popup[:arrowside], 'left'], nil, '', + {:command=>proc{ + @tree2.column_configure(@popup[:column].value, + :arrowside=>:left) + } + } ], + [ 'Side Right', [@popup[:arrowside], 'right'], nil, '', + {:command=>proc{ + @tree2.column_configure(@popup[:column].value, + :arrowside=>:right) + } + } ], + + '---', + + [ 'Gravity Left', [@popup[:arrowgravity], 'left'], nil, '', + {:command=>proc{ + @tree2.column_configure(@popup[:column].value, + :arrowgravity=>:left) + } + } ], + [ 'Gravity Right', [@popup[:arrowgravity], 'right'], nil, '', + {:command=>proc{ + @tree2.column_configure(@popup[:column].value, + :arrowgravity=>:right) + } + } ], + ], + nil, '', {:menu_config=>{:tearoff=>false}} ], + + [ 'Expand', @popup[:expand], nil, '', + {:command=>proc{ + @tree2.column_configure(@popup[:column].value, + :expand=>@popup[:expand].value) + } + } ], + + [ 'Squeeze', @popup[:squeeze], nil, '', + {:command=>proc{ + @tree2.column_configure(@popup[:column].value, + :squeeze=>@popup[:squeeze].value) + } + } ], + + [ 'Justify', + [ + [ 'Left', [@popup[:justify], 'left'], nil, '', + {:command=>proc{ + @tree2.column_configure(@popup[:column].value, :justify=>:left) + } + } ], + [ 'Center', [@popup[:justify], 'center'], nil, '', + {:command=>proc{ + @tree2.column_configure(@popup[:column].value, + :justify=>:center) + } + } ], + [ 'Right', [@popup[:justify], 'right'], nil, '', + {:command=>proc{ + @tree2.column_configure(@popup[:column].value, + :justify=>:right) + } + } ] + ], + nil, '', {:menu_config=>{:tearoff=>false}} ] + ] + + m = TkMenu.new_menuspec(menuspec, @tree2, false) + @non_clear_list << m + @mHeader[@tree2] = m + end + + ########################### + + def init_demo_scripts_module + @demo_scripts = Module.new + + master = self + + scriptDir = @ScriptDir + + thisPlatform = @thisPlatform + + randomN = @RandomN + + images = @images + sel_images = @sel_images + + systemButtonFace = @SystemButtonFace + systemHighlight = @SystemHighlight + systemHighlightText = @SystemHighlightText + + proc_disp_styles_in_item = proc{|item| + master.instance_eval{ display_styles_in_item(item) } + } + + @demo_scripts.instance_eval{ + @master = master + + @display_styles_in_item = proc_disp_styles_in_item + + @Priv = TkVarAccess.new('::TreeCtrl::Priv') + + @ScriptDir = scriptDir + + @thisPlatform = thisPlatform + + @RandomN = randomN + + @images = images + @sel_images = sel_images + + @SystemButtonFace = systemButtonFace + @SystemHighlight = systemHighlight + @SystemHighlightText = systemHighlightText + } + + class << @demo_scripts + def _get_binding + binding + end + private :_get_binding + + def load_demo(file) + eval(IO.readlines(file).join, _get_binding()) + end + + def init_pics(*args) + @master.init_pics(*args) + end + end + end + + def load_demo_scripts + # demo sources + [ + 'bitmaps', + 'explorer', + 'help', + 'imovie', + 'layout', + 'mailwasher', + 'outlook-folders', + 'outlook-newgroup', + 'random', + 'www-options' + ].each{|f| + @demo_scripts.load_demo(File.join(@ScriptDir, "#{f}.rb")) + } + end + + ########################### + + def init_demo_list + @tree1.element_create('e1', :text, + :fill=>[@SystemHighlightText, ['selected', 'focus']]) + @tree1.element_create('e2', :rect, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected', 'focus'], + 'gray', ['selected', '!focus'], + ]) + @tree1.style_create('s1') + @tree1.style_elements('s1', ['e2', 'e1']) + + # Tk listbox has linespace + 1 height + @tree1.style_layout('s1', 'e2', :union=>['e1'], + :ipadx=>2, :ipady=>[0, 1], :iexpand=>:e) + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + @tree1.defaultstyle = 's1' + end + + ### + [ + ["Random #{@RandomN[0]} Items", :demoRandom, 'random.rb'], + ["Random #{@RandomN[0]} Items, Button Images", :demoRandom2, 'random.rb'], + ["Outlook Express (Folders)", :demoOutlookFolders, 'outlook-folders.rb'], + ["Outlook Express (Newsgroup)", :demoOutlookNewsgroup, 'outlook-newgroup.rb'], + ["Explorer (Details)", :demoExplorerDetails, 'explorer.rb'], + ["Explorer (List)", :demoExplorerList, 'explorer.rb'], + ["Explorer (Large icons)", :demoExplorerLargeIcons, 'explorer.rb'], + ["Explorer (Small icons)", :demoExplorerSmallIcons, 'explorer.rb'], + ["Internet Options", :demoInternetOptions, 'www-options.rb'], + ["Help Contents", :demoHelpContents, 'help.rb'], + ["Layout", :demoLayout, 'layout.rb'], + ["MailWasher", :demoMailWasher, 'mailwasher.rb'], + ["Bitmaps", :demoBitmaps, 'bitmaps.rb'], + ["iMovie", :demoIMovie, 'imovie.rb'] + ].each{|label, cmd, file| + item = @tree1.item_create + @tree1.item_lastchild(:root, item) + unless (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + @tree1.item_style_set(item, 0, 's1') + end + @tree1.item_text(item, 0, label) + @demoCmd[item] = cmd + @demoFile[item] = file + } + + @tree1.yview_moveto(0.0) + end + + def demo_set(cmd, file) + demo_clear() + clicks = Tk::Clock.clicks + @demo_scripts.__send__(cmd, @tree2) + clicks = Tk::Clock.clicks - clicks + puts "set list in #{'%.2g'%(clicks/1000000.0)} seconds (#{clicks} clicks)" + @tree2.xview_moveto(0) + @tree2.yview_moveto(0) + Tk.update + display_styles_in_list() + show_source(file) + end + + def display_styles_in_list + # Create elements and styles the first time this is called + if @tree4.style_names.empty? + @tree4.element_create('e1', :text, + :fill=>[@SystemHighlightText,['selected','focus']]) + @tree4.element_create('e2', :text, + :fill=>[ + @SystemHighlightText, ['selected','focus'], + '', ['selected','!focus'], + 'blue', [] + ]) + @tree4.element_create('e3', :rect, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected','focus'], + 'gray', ['selected', '!focus'] + ]) + + @tree4.style_create('s1') + @tree4.style_elements('s1', ['e3', 'e1']) + @tree4.style_layout('s1', 'e3', :union=>['e1'], :ipadx=>1, :ipady=>[0,1]) + + @tree4.style_create('s2') + @tree4.style_elements('s2', ['e3', 'e1', 'e2']) + @tree4.style_layout('s2', 'e1', :padx=>[0,4]) + @tree4.style_layout('s2', 'e3', :union=>['e1', 'e2'], + :ipadx=>1, :ipady=>[0,1]) + end + + # Clear the list + @tree4.item_delete(:all) + + # One item for each element in the demo list + @tree2.element_names.sort.each{|elem| + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + item = @tree4.item_create(:button=>true) + @tree4.item_collapse(item) + else + item = @tree4.item_create + @tree4.item_hasbutton(item, true) + @tree4.collapse(item) + end + @tree4.item_style_set(item, 0, 's1') + @tree4.item_text(item, 0, + "Element #{elem} (#{@tree2.element_type(elem)})") + + # One item for each configuration option for this element + @tree2.element_configinfo(elem).each{|name, x, y, default, current| + item2 = @tree4.item_create + + if default == current + @tree4.item_style_set(item2, 0, 's1') + @tree4.item_complex(item2, [ + ['e1', {:text=>"#{name} #{current.inspect}"}] + ]) + else + @tree4.item_style_set(item2, 0, 's2') + @tree4.item_complex(item2, [ + ['e1', {:text=>name}], + ['e2', {:text=>current.inspect}] + ]) + end + + @tree4.item_lastchild(item, item2) + } + + @tree4.item_lastchild(:root, item) + } + + # One item for each style in the demo list + @tree2.style_names.sort.each{|sty| + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + item = @tree4.item_create(:button=>true) + @tree4.item_collapse(item) + else + item = @tree4.item_create + @tree4.item_hasbutton(item, true) + @tree4.collapse(item) + end + @tree4.item_style_set(item, 0, 's1') + @tree4.item_text(item, 0, "Style #{sty}") + + # One item for each element in the style + @tree2.style_elements(sty).each{|elem| + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + item2 = @tree4.item_create(:button=>true) + @tree4.item_collapse(item2) + else + item2 = @tree4.item_create + @tree4.item_hasbutton(item2, true) + @tree4.collapse(item2) + end + @tree4.item_style_set(item2, 0, 's1') + @tree4.item_text(item2, 0, + "Element #{elem} (#{@tree2.element_type(elem)})") + + # One item for each layout option for this element in this style + @tree2.style_layout(sty, elem).each{|k, v| + item3 = @tree4.item_create + unless (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + @tree4.item_hasbutton(item3, false) + end + @tree4.item_style_set(item3, 0, 's1') + @tree4.item_text(item3, 0, "#{k} #{v.inspect}") + @tree4.item_lastchild(item2, item3) + } + + @tree4.item_lastchild(item, item2) + } + + @tree4.item_lastchild(:root, item) + } + + @tree4.xview_moveto(0) + @tree4.yview_moveto(0) + end + + def display_styles_in_item(item) + @tree3.column_configure(0, :text=>"Styles in item #{@tree2.index(item)}") + + # Create elements and styles the first time this is called + if @tree3.style_names.empty? + @tree3.element_create('e1', :text, + :fill=>[@SystemHighlightText,['selected','focus']]) + @tree3.element_create('e2', :text, + :fill=>[ + @SystemHighlightText, ['selected','focus'], + '', ['selected','!focus'], + 'blue', [] + ]) + @tree3.element_create('e3', :rect, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected','focus'], + 'gray', ['selected', '!focus'] + ]) + + @tree3.style_create('s1') + @tree3.style_elements('s1', ['e3', 'e1']) + @tree3.style_layout('s1', 'e3', :union=>['e1'], :ipadx=>1, :ipady=>[0,1]) + + @tree3.style_create('s2') + @tree3.style_elements('s2', ['e3', 'e1', 'e2']) + @tree3.style_layout('s2', 'e1', :padx=>[0,4]) + @tree3.style_layout('s2', 'e3', :union=>['e1', 'e2'], + :ipadx=>1, :ipady=>[0,1]) + end + # Clear the list + @tree3.item_delete(:all) + + # One item for each item-column + column = 0 + @tree2.item_style_set(item).each{|sty| + item2 = @tree3.item_create + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + @tree3.item_collapse(item2) + else + @tree3.collapse(item2) + end + @tree3.item_style_set(item2, 0, 's1') + @tree3.item_element_configure(item2, 0, 'e1', + :text=>"Column #{column}: Style #{sty}") + + button = false + + # One item for each element in this style + unless sty.to_s.empty? + @tree2.item_style_elements(item, column).each{|elem| + button = true + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + item3 = @tree3.item_create(:button=>true) + else + item3 = @tree3.item_create + @tree3.item_hasbutton(item3, true) + end + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + @tree3.item_collapse(item3) + else + @tree3.collapse(item3) + end + @tree3.item_style_set(item3, 0, 's1') + @tree3.item_element_configure(item3, 0, 'e1', + :text=>"Element #{elem} (#{@tree2.element_type(elem)})") + + # One item for each configuration option in this element + @tree2.item_element_configinfo(item, column, elem) \ + .each{|name, x, y, default, current| + item4 = @tree3.item_create + masterDefault = @tree2.element_cget(elem, name) + sameAsMaster = (masterDefault == current) + if !sameAsMaster && current == '' + sameAsMaster = true + current = masterDefault + end + + if sameAsMaster + @tree3.item_style_set(item4, 0, 's1') + @tree3.item_complex(item4, [ + ['e1', + {:text=>"#{name} #{current.inspect}"}] + ]) + else + @tree3.item_style_set(item4, 0, 's2') + @tree3.item_complex(item4, [ + ['e1', {:text=>name}], + ['e2', {:text=>current.inspect}] + ]) + end + @tree3.item_lastchild(item3, item4) + } + @tree3.item_lastchild(item2, item3) + } + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + @tree3.item_configure(item2, :button=>true) if button + else + @tree3.item_hasbutton(item2, true) if button + end + end + @tree3.item_lastchild(:root, item2) + column += 1 + } + + @tree3.xview_moveto(0) + @tree3.yview_moveto(0) + end + + def demo_clear + # Clear the demo list + @tree2.item_delete(:all) + + # Clear all bindings on the demo list added by the previous demo. + # This is why DontDelete is used for the <Selection> binding. + @tree2.notify_bindinfo(@tree2).each{|ev| + @tree2.notify_bind_remove(@tree2, ev) + } + + # Clear all run-time states + @tree2.state_names.each{|st| @tree2.state_undefine(st) } + + # Clear the styles-in-item list + @tree3.item_delete(:all) + + # Delete columns in demo list + while (@tree2.numcolumns > 0) + @tree2.column_delete(0) + end + + # Delete all styles in demo list + @tree2.style_delete(*(@tree2.style_names)) + + # Delete all elements in demo list + @tree2.element_delete(*(@tree2.element_names)) + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + @tree2.item_configure(:root, :button=>false) + @tree2.item_expand(:root) + else + @tree2.item_hasbutton(:root, false) + @tree2.expand(:root) + end + + # Restore some happy defaults to the demo list + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + @tree2.configure(:orient=>:vertical, :wrap=>'', + :xscrollincrement=>0, :yscrollincrement=>0, + :itemheight=>0, :showheader=>true, + :background=>'white', :scrollmargin=>0, + :xscrolldelay=>50, :yscrolldelay=>50, + :openbuttonimage=>'', :closedbuttonimage=>'', + :backgroundmode=>:row, :treecolumn=>0, :indent=>19, + :defaultstyle=>'', :backgroundimage=>'') + else + @tree2.configure(:orient=>:vertical, :wrap=>'', + :xscrollincrement=>0, :yscrollincrement=>0, + :itemheight=>0, :showheader=>true, + :background=>'white', :scrollmargin=>0, + :xscrolldelay=>50, :yscrolldelay=>50, + :openbuttonimage=>'', :closedbuttonimage=>'', + :backgroundmode=>:row, :treecolumn=>0, :indent=>19) + end + + # Restore default bindings to the demo list + @tree2.bindtags = [ @tree2, Tk::TreeCtrl, @tree2.winfo_toplevel, :all ] + + @tree2.winfo_children.each{|w| + w.destroy unless @non_clear_list.include?(w) + } + end +end + +TkTreeCtrl_demo.new($ScriptDir) + +############################################## + +def cursor_window(top = nil) + top.destroy if top.kind_of?(TkWindow) && top.winfo_exist? + top = TkToplevel.new(:title=>'Cursor Window') + + c = TkCanvas.new(top, :background=>'white', + :width=>50*10, :highlightthickness=>0, + :borderwidth=>0).pack(:expand=>true, :fill=>:both) + cursors = %w( + X_cursor + arrow + based_arrow_down + based_arrow_up + boat + bogosity + bottom_left_corner + bottom_right_corner + bottom_side + bottom_tee + box_spiral + center_ptr + circle + clock + coffee_mug + cross + cross_reverse + crosshair + diamond_cross + dot + dotbox + double_arrow + draft_large + draft_small + draped_box + exchange + fleur + gobbler + gumby + hand1 + hand2 + heart + icon + iron_cross + left_ptr + left_side + left_tee + leftbutton + ll_angle + lr_angle + man + middlebutton + mouse + pencil + pirate + plus + question_arrow + right_ptr + right_side + right_tee + rightbutton + rtl_logo + sailboat + sb_down_arrow + sb_h_double_arrow + sb_left_arrow + sb_right_arrow + sb_up_arrow + sb_v_double_arrow + shuttle + sizing + spider + spraycan + star + target + tcross + top_left_arrow + top_left_corner + top_right_corner + top_side + top_tee + trek + ul_angle + umbrella + ur_angle + watch + xterm + ) + + orig_cursor = c.cursor + col = 0 + row = 0 + + cursors.each{|cur| + x = col * 50 + y = row * 40 + + begin + c.cursor = cur + + r = TkcRectangle.new(c, x, y, x+50, y+40, + :fill=>'gray90', :outline=>'black', :width=>2) + t = TkcText.new(c, x+50/2, y+4, :text=>cur, :anchor=>:n, :width=>42) + + col += 1 + if col >= 10 + col = 0 + row += 1 + end + + r.bind('Enter', proc{c.cursor = cur; r.fill = 'linen'}) + r.bind('Leave', proc{c.cursor = ''; r.fill = 'gray90'}) + + t.bind('Enter', proc{c.cursor = cur}) + t.bind('Leave', proc{c.cursor = ''}) + rescue + c.cursor = orig_cursor + end + } + + c.cursor = orig_cursor + c.height = (row + 1) * 40 +end + +cursor_window() + +############################################## + +# A little screen magnifier for X11 +if Tk::PLATFORM['platform'] == 'unix' && Tk.windowingsystem != 'aqua' + def show_loupe(setting=nil) + loupe = (setting.kind_of?(Hash))? setting: {} + loupe[:zoom] = 3 unless loupe[:zoom] + loupe[:x] = 0 unless loupe[:x] + loupe[:y] = 0 unless loupe[:y] + loupe[:auto] = true unless loupe[:auto] + loupe[:delay] = 500 unless loupe[:delay] + loupe[:image] = + TkPhotoImage.new(:width=>150, :height=>150) unless loupe[:image] + + top = TkToplevel.new(:geometry=>'-0+30', + :title=>'A little screen magnifier for X11') + TkLabel.new(top, :image=>loupe[:image]).pack + + TkTimer.new(proc{loupe[:delay]}, -1, proc{ + x, y = TkWinfo.pointerxy(Tk.root) + if loupe[:auto] || loupe[:x] != x || loupe[:y] != y + w = loupe[:image].width + h = loupe[:image].height + Tk::TreeCtrl.loupe(loupe[:image], x, y, w, h, loupe[:zoom]) + loupe[:x] = x + loupe[:y] = y + end + }).start + end + + show_loupe() +end + +############################################## + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/treectrl/explorer.rb b/ext/tk/sample/tkextlib/treectrl/explorer.rb new file mode 100644 index 000000000..8ee002ef9 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/explorer.rb @@ -0,0 +1,442 @@ + +def demoExplorerAux(t, dir_proc, file_proc) + base_dir = File.dirname(File.dirname(@ScriptDir)) + + clicks = Tk::Clock.clicks + globDirs = Dir.glob(File.join(base_dir, '*')).find_all{|file| + FileTest.directory?(file) + } + clickGlobDirs = Tk::Clock.clicks - clicks + + clicks = Tk::Clock.clicks + list = globDirs.sort + clickSortDirs = Tk::Clock.clicks - clicks + + clicks = Tk::Clock.clicks + list.each{|file| dir_proc.call(file)} + clickAddDirs = Tk::Clock.clicks - clicks + + clicks = Tk::Clock.clicks + globFiles = Dir.glob(File.join(base_dir, '*')).find_all{|file| + FileTest.file?(file) + } + clickGlobFiles = Tk::Clock.clicks - clicks + + clicks = Tk::Clock.clicks + list = globFiles.sort + clickSortFiles = Tk::Clock.clicks - clicks + + clicks = Tk::Clock.clicks + list.each{|file| file_proc.call(file)} + clickAddFiles = Tk::Clock.clicks - clicks + + gd = '%.2g' % (clickGlobDirs / 1000000.0) + sd = '%.2g' % (clickSortDirs / 1000000.0) + ad = '%.2g' % (clickAddDirs / 1000000.0) + gf = '%.2g' % (clickGlobFiles / 1000000.0) + sf = '%.2g' % (clickSortFiles / 1000000.0) + af = '%.2g' % (clickAddFiles / 1000000.0) + + puts "dirs(#{globDirs.length}) glob/sort/add #{gd}/#{sd}/#{ad} files(#{globFiles.length}) glob/sort/add #{gf}/#{sf}/#{af}" + + @Priv[:DirCnt, t] = globDirs.length +end + +# +# Demo: explorer files +# +def demoExplorerDetails(t) + height = t.font.metrics(:linespace) + 2 + hehght = 18 if height < 18 + + t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false, + :itemheight=>height, :selectmode=>:extended, + :xscrollincrement=>20, :scrollmargin=>16, + :xscrolldelay=>[500, 50], :yscrolldelay=>[500, 50]) + + init_pics('small-*') + + if $HasColumnCreate + t.column_create(:text=>'Name', :tag=>'name', + :width=>200, :arrow=>:up, :arrowpad=>6) + t.column_create(:text=>'Size', :tag=>'size', :justify=>:right, + :width=>60, :arrowside=>:left, :arrowgravity=>:right) + t.column_create(:text=>'Type', :tag=>'type', :width=>120) + t.column_create(:text=>'Modified', :tag=>'modified', :width=>130) + else + t.column_configure(0, :text=>'Name', :tag=>'name', + :width=>200, :arrow=>:up, :arrowpad=>6) + t.column_configure(1, :text=>'Size', :tag=>'size', :justify=>:right, + :width=>60, :arrowside=>:left, :arrowgravity=>:right) + t.column_configure(2, :text=>'Type', :tag=>'type', :width=>120) + t.column_configure(3, :text=>'Modified', :tag=>'modified', :width=>130) + end + + t.element_create('e1', :image, + :image=>[ + @sel_images['small-folder'], ['selected'], + @images['small-folder'], [] + ]) + t.element_create('e2', :text, :lines=>1, + :fill=>[@SystemHighlightText, ['selected', 'focus']]) + t.element_create('txtType', :text, :lines=>1) + t.element_create('txtSize', :text, :lines=>1, + :datatype=>:integer, :format=>'%dKB') + t.element_create('txtDate', :text, :lines=>1, + :datatype=>:time, :format=>'%d/%m/%y %I:%M %p') + t.element_create('e4', :rect, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected', 'focus'], + 'gray', ['selected', '!focus'] + ]) + + # image + text + s = t.style_create('styName', :orient=>:horizontal) + t.style_elements(s, ['e4', 'e1', 'e2']) + t.style_layout(s, 'e1', :expand=>:ns) + t.style_layout(s, 'e2', :padx=>[2,0], :squeeze=>:x, :expand=>:ns) + t.style_layout(s, 'e4', :union=>['e2'], :iexpand=>:ns, :ipadx=>2) + + # column 1: text + s = t.style_create('stySize') + t.style_elements(s, ['txtSize']) + t.style_layout(s, 'txtSize', :padx=>6, :squeeze=>:x, :expand=>:ns) + + # column 2: text + s = t.style_create('styType') + t.style_elements(s, ['txtType']) + t.style_layout(s, 'txtType', :padx=>6, :squeeze=>:x, :expand=>:ns) + + # column 3: text + s = t.style_create('styDate') + t.style_elements(s, ['txtDate']) + t.style_layout(s, 'txtDate', :padx=>6, :squeeze=>:x, :expand=>:ns) + + @Priv[:edit, t] = ['e2'] + @Priv[:sensitive, t] = [ ['name', 'styName', 'e1', 'e2'] ] + @Priv[:dragimage, t] = [ ['name', 'styName', 'e1', 'e2'] ] + + t.notify_bind(t, 'Edit-accept', + proc{|w, i, tt| w.item_text(i, 0, tt)}, '%T %I %t') + + dir_proc = proc{|file| + item = t.item_create + t.item_style_set(item, 0, 'styName', 2, 'styType', 3, 'styDate') + t.item_complex(item, + [['e2', {:text=>File.basename(file)}]], + [], + [['txtType', {:text=>'Folder'}]], + [['txtDate', {:data=>File.mtime(file).tv_sec}]]) + t.item_lastchild(:root, item) + } + + file_proc = proc{|file| + item = t.item_create + t.item_style_set(item, 0, 'styName', 1, 'stySize', + 2, 'styType', 3, 'styDate') + + ext = File.extname(file) + case ext + when '.dll' + img = 'small-dll' + when '.exe' + img = 'small-exe' + when '.txt' + img = 'small-txt' + else + if FileTest.executable?(file) + img = 'small-exe' + else + img = 'small-file' + end + end + + type = ext.upcase + type = type[1..-1] << ' ' unless type.empty? + type << 'File' + + t.item_complex(item, + [ + ['e1', {:image=>[@sel_images[img], ['selected'], + @images[img], []]}], + ['e2', {:text=>File.basename(file)}] + ], + [ ['txtSize', {:data=>File.size(file)/1024 + 1}] ], + [ ['txtType', {:text=>type}] ], + [ ['txtDate', {:data=>File.mtime(file).tv_sec}] ] + ) + t.item_lastchild(:root, item) + } + + demoExplorerAux(t, dir_proc, file_proc) + + @SortColumn = 0 + t.notify_bind(t, 'Header-invoke', + proc{|w, c| explorerHeaderInvoke(t, w, c)}, '%T %C') + + t.bindtags = [ t, 'TreeCtrlFileList', Tk::TreeCtrl, t.winfo_toplevel, :all ] +end + +def explorerHeaderInvoke(t, w, c) + if (c == @SortColumn) + if t.column_cget(@SortColumn, :arrow) == 'down' + order = :increasing + arrow = :up + else + order = :decreasing + arrow = :down + end + else + if t.column_cget(@SortColumn, :arrow) == 'down' + order = :decreasing + arrow = :down + else + order = :increasing + arrow = :up + end + t.column_configure(@SortColumn, :arrow=>:none) + @SortColumn = c + end + + t.column_configure(c, :arrow=>arrow) + dirCount = TkComm.number(@Priv[:DirCnt, t]) + lastDir = dirCount - 1 + case t.column_cget(c, :tag) + when 'name' + if dirCount > 0 + t.item_sort(:root, order, {:last=>"root child #{lastDir}"}, + {:column=>c, :dictionary=>true}) + end + if dirCount < t.numitems - 1 + t.item_sort(:root, order, {:first=>"root child #{dirCount}"}, + {:column=>c, :dictionary=>true}) + end + + when 'size' + if dirCount < t.numitems - 1 + t.item_sort(:root, order, {:first=>"root child #{dirCount}"}, + {:column=>c, :integer=>true}, + {:column=>'name', :dictionary=>true}) + end + + when 'type' + if dirCount < t.numitems - 1 + t.item_sort(:root, order, {:first=>"root child #{dirCount}"}, + {:column=>c, :dictionary=>true}, + {:column=>'name', :dictionary=>true}) + end + + when 'modified' + if dirCount > 0 + t.item_sort(:root, order, {:last=>"root child #{lastDir}"}, + {:column=>c, :integer=>true}, + {:column=>'name', :dictionary=>true}) + end + if dirCount < t.numitems - 1 + t.item_sort(:root, order, {:first=>"root child #{dirCount}"}, + {:column=>c, :integer=>true}, + {:column=>'name', :dictionary=>true}) + end + + end +end + +def demoExplorerLargeIcons(t) + # Item height is 32 for icon, 4 padding, 3 lines of text + itemHeight = 32 + 4 + t.font.metrics(:linespace) * 3 + + t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false, + :selectmode=>:extended, :wrap=>:window, :orient=>:horizontal, + :itemheight=>itemHeight, :showheader=>false, :scrollmargin=>16, + :xscrolldelay=>[500, 50], :yscrolldelay=>[500, 50]) + + init_pics('big-*') + + if $HasColumnCreate + t.column_create(:width=>75) + else + t.column_configure(0, :width=>75) + end + + t.element_create('elemImg', :image, + :image=>[ + @sel_images['big-folder'], ['selected'], + @images['big-folder'], [] + ]) + t.element_create('elemTxt', :text, :justify=>:center, + :lines=>1, :width=>71, :wrap=>:word, + :fill=>[@SystemHighlightText, ['selected', 'focus']]) + t.element_create('elemSel', :rect, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected', 'focus'], + 'gray', ['selected'] + ]) + + # image + text + s = t.style_create('STYLE', :orient=>:vertical) + t.style_elements(s, ['elemSel', 'elemImg', 'elemTxt']) + t.style_layout(s, 'elemImg', :expand=>:we) + t.style_layout(s, 'elemTxt', + :pady=>[4,0], :padx=>2, :squeeze=>:x, :expand=>:we) + t.style_layout(s, 'elemSel', :union=>['elemTxt']) + + @Priv[:edit, t] = ['elemTxt'] + @Priv[:sensitive, t] = [ [0, 'STYLE', 'elemImg', 'elemTxt'] ] + @Priv[:dragimage, t] = [ [0, 'STYLE', 'elemImg', 'elemTxt'] ] + + t.notify_bind(t, 'Edit-accept', + proc{|w, i, tt| w.item_text(i, 0, tt)}, '%T %I %t') + + dir_proc = proc{|file| + item = t.item_create + t.item_style_set(item, 0, 'STYLE') + t.item_text(item, 0, File.basename(file)) + t.item_lastchild(:root, item) + } + + file_proc = proc{|file| + item = t.item_create + t.item_style_set(item, 0, 'STYLE') + + ext = File.extname(file) + case ext + when '.dll' + img = 'big-dll' + when '.exe' + img = 'big-exe' + when '.txt' + img = 'big-txt' + else + if FileTest.executable?(file) + img = 'big-exe' + else + img = 'big-file' + end + end + + type = ext.upcase + type = type[1..-1] << ' ' unless type.empty? + type << 'File' + + t.item_complex(item, + [ + ['elemImg', {:image=>[@sel_images[img], ['selected'], + @images[img], []]}], + ['elemTxt', {:text=>File.basename(file)}] + ]) + t.item_lastchild(:root, item) + } + + demoExplorerAux(t, dir_proc, file_proc) + + t.activate(t.index('root firstchild')) + + t.notify_bind(t, 'ActiveItem', + proc{|w, a, c| + w.item_element_configure(a, 0, 'elemTxt', :lines=>'') + w.item_element_configure(c, 0, 'elemTxt', :lines=>3) + }, '%T %p %c') + + t.bindtags = [ t, 'TreeCtrlFileList', Tk::TreeCtrl, t.winfo_toplevel, :all ] +end + +# Tree is horizontal, wrapping occurs at right edge of window, each item +# is as wide as the smallest needed multiple of 110 pixels +def demoExplorerSmallIcons(t) + demoExplorerList(t) + t.configure(:orient=>:horizontal, :xscrollincrement=>0) + t.column_configure(0, :width=>'', :stepwidth=>110, :widthhack=>false) +end + +# Tree is vertical, wrapping occurs at bottom of window, each range has the +# same width (as wide as the longest item), xscrollincrement is by range +def demoExplorerList(t) + height = t.font.metrics(:linespace) + 2 + height = 18 if height < 18 + + t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false, + :itemheight=>height, :selectmode=>:extended, :wrap=>:window, + :showheader=>false, :scrollmargin=>16, + :xscrolldelay=>[500, 50], :yscrolldelay=>[500, 50]) + + init_pics('small-*') + + if $HasColumnCreate + t.column_create(:widthhack=>true) + else + t.column_configure(0, :widthhack=>true) + end + + t.element_create('elemImg', :image, + :image=>[ + @sel_images['small-folder'], ['selected'], + @images['small-folder'], [] + ]) + t.element_create('elemTxt', :text, :lines=>1, + :fill=>[@SystemHighlightText, ['selected', 'focus']]) + t.element_create('elemSel', :rect, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected', 'focus'], + 'gray', ['selected', '!focus'] + ]) + + # image + text + s = t.style_create('STYLE') + t.style_elements(s, ['elemSel', 'elemImg', 'elemTxt']) + t.style_layout(s, 'elemImg', :expand=>:ns) + t.style_layout(s, 'elemTxt', :squeeze=>:x, :expand=>:ns, :padx=>[2,0]) + t.style_layout(s, 'elemSel', :union=>['elemTxt'], :iexpand=>:ns, :ipadx=>2) + + @Priv[:edit, t] = ['elemTxt'] + @Priv[:sensitive, t] = [ [0, 'STYLE', 'elemImg', 'elemTxt'] ] + @Priv[:dragimage, t] = [ [0, 'STYLE', 'elemImg', 'elemTxt'] ] + + t.notify_bind(t, 'Edit-accept', + proc{|w, i, tt| w.item_text(i, 0, tt)}, '%T %I %t') + + dir_proc = proc{|file| + item = t.item_create + t.item_style_set(item, 0, 'STYLE') + t.item_text(item, 0, File.basename(file)) + t.item_lastchild(:root, item) + } + + file_proc = proc{|file| + item = t.item_create + t.item_style_set(item, 0, 'STYLE') + + ext = File.extname(file) + case ext + when '.dll' + img = 'small-dll' + when '.exe' + img = 'small-exe' + when '.txt' + img = 'small-txt' + else + if FileTest.executable?(file) + img = 'small-exe' + else + img = 'small-file' + end + end + + type = ext.upcase + type = type[1..-1] << ' ' unless type.empty? + type << 'File' + + t.item_complex(item, + [ + ['elemImg', {:image=>[@sel_images[img], ['selected'], + @images[img], []]}], + ['elemTxt', {:text=>File.basename(file)}] + ]) + t.item_lastchild(:root, item) + } + + demoExplorerAux(t, dir_proc, file_proc) + + t.activate(t.item_firstchild(:root)) + + t.bindtags = [ t, 'TreeCtrlFileList', Tk::TreeCtrl, t.winfo_toplevel, :all ] +end diff --git a/ext/tk/sample/tkextlib/treectrl/help.rb b/ext/tk/sample/tkextlib/treectrl/help.rb new file mode 100644 index 000000000..01e075bdf --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/help.rb @@ -0,0 +1,405 @@ +# +# Demo: Help contents +# +def demoHelpContents(t) + height = t.font.metrics(:linespace) + 2 + hehght = 18 if height < 18 + t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false, + :itemheight=>height, :selectmode=>:browse) + + init_pics('help-*') + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.column_create(:text=>'Help Contents') + else # TreeCtrl 1.0 + t.column_configure(0, :text=>'Help Contents') + end + + # Define a new item state + t.state_define('mouseover') + + t.element_create('e1', :image, :image=>@images['help-page']) + t.element_create('e2', :image, :image=>[ + @images['help-book-open'], ['open'], + @images['help-book-closed'], [], + ]) + t.element_create('e3', :text, + :font=>[t.font.dup.underline(true), ['mouseover']], + :fill=>[ + @SystemHighlightText, ['selected', 'focus'], + 'blue', ['mouseover'] + ]) + t.element_create('e4', :rect, :showfocus=>true, + :fill=>[@SystemHighligh, ['selected', 'focus']]) + + # book + s = t.style_create('s1') + t.style_elements(s, ['e4', 'e1', 'e3']) + t.style_layout(s, 'e1', :padx=>[0,4], :expand=>:ns) + t.style_layout(s, 'e3', :expand=>:ns) + t.style_layout(s, 'e4', :union=>['e3'], :iexpand=>:ns, :ipadx=>2) + + # page + s = t.style_create('s2') + t.style_elements(s, ['e4', 'e2', 'e3']) + t.style_layout(s, 'e2', :padx=>[0,4], :expand=>:ns) + t.style_layout(s, 'e3', :expand=>:ns) + t.style_layout(s, 'e4', :union=>['e3'], :iexpand=>:ns, :ipadx=>2) + + parentList = [:root, '', '', '', '', '', ''] + parent = :root + [ + [0, 's1', "Welcome to Help"], + [0, 's2', "Introducing Windows 98"], + [1, 's2', "How to Use Help"], + [2, 's1', "Find a topic"], + [2, 's1', "Get more out of help"], + [1, 's2', "Register Your Software"], + [2, 's1', "Registering Windows 98 online"], + [1, 's2', "What's New in Windows 98"], + [2, 's1', "Innovative, easy-to-use features"], + [2, 's1', "Improved reliability"], + [2, 's1', "A faster operating system"], + [2, 's1', "True Web integration"], + [2, 's1', "More entertaining and fun"], + [1, 's2', "If You're New to Windows 98"], + [2, 's2', "Tips for Macintosh Users"], + [3, 's1', "Why does the mouse have two buttons?"] + ].each{|depth, style, text| + item = t.item_create + t.item_style_set(item, 0, style) + t.item_element_configure(item, 0, 'e3', :text=>text) + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_collapse(item) + else # TreeCtrl 1.0 + t.collapse(item) + end + t.item_lastchild(parentList[depth], item) + depth += 1 + parentList[depth] = item + } + + treeCtrlHelp = TkBindTag.new + + treeCtrlHelp.bind('Double-ButtonPress-1', + proc{|w, x, y| + if w.identify(x, y)[0] == 'header' + Tk::TreeCtrl::BindCallback.doubleButton1(w, x, y) + else + helpButton1(w, x, y) + end + Tk.callback_break + }, '%W %x %y') + + treeCtrlHelp.bind('ButtonPress-1', + proc{|w, x, y| + helpButton1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlHelp.bind('Button1-Motion', + proc{|w, x, y| + helpMotion1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlHelp.bind('Button1-Leave', + proc{|w, x, y| + helpLeave1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlHelp.bind('ButtonRelease-1', + proc{|w, x, y| + helpRelease1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlHelp.bind('Motion', proc{|w, x, y| helpMotion(w, x, y) }, '%W %x %y') + + treeCtrlHelp.bind('Leave', proc{|w, x, y| helpMotion(w, x, y) }, '%W %x %y') + + treeCtrlHelp.bind('Button1-Motion', + proc{|w, x, y| + if w.selection_get.length == 1 + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, + '1.1') >= 0) + w.item_toggle(w.selection_get[0]) + else # TreeCtrl 1.0 + w.toggle(w.selection_get[0]) + end + end + Tk.callback_break + }, '%W %x %y') + + @Priv[:help, :prev] = '' + + t.bindtags = [ t, treeCtrlHelp, Tk::TreeCtrl, t.winfo_toplevel, :all ] +end + +# This is an alternate implementation that does not define a new item state +# to change the appearance of the item under the cursor. +def demoHelpContents2(t) + height = t.font.metrics(:linespace) + 2 + hehght = 18 if height < 18 + t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false, + :itemheight=>height, :selectmode=>:browse) + + init_pics('help-*') + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.column_create(:text=>'Help Contents') + else # TreeCtrl 1.0 + t.column_configure(0, :text=>'Help Contents') + end + + t.element_create('e1', :image, :image=>@images['help-page']) + t.element_create('e2', :image, :image=>[ + @images['help-book-open'], ['open'], + @images['help-book-closed'], [], + ]) + t.element_create('e3', :text, + :fill=>[ + @SystemHighlightText, ['selected', 'focus'], + 'blue', [] + ]) + t.element_create('e4', :rect, :showfocus=>true, + :fill=>[@SystemHighligh, ['selected', 'focus']]) + t.element_create('e5', :text, :font=>t.font.dup.underline(true), + :fill=>[ + @SystemHighlightText, ['selected', 'focus'], + 'blue', [] + ]) + + # book + s = t.style_create('s1') + t.style_elements(s, ['e4', 'e1', 'e3']) + t.style_layout(s, 'e1', :padx=>[0,4], :expand=>:ns) + t.style_layout(s, 'e3', :expand=>:ns) + t.style_layout(s, 'e4', :union=>['e3'], :iexpand=>:ns, :ipadx=>2) + + # page + s = t.style_create('s2') + t.style_elements(s, ['e4', 'e2', 'e3']) + t.style_layout(s, 'e2', :padx=>[0,4], :expand=>:ns) + t.style_layout(s, 'e3', :expand=>:ns) + t.style_layout(s, 'e4', :union=>['e3'], :iexpand=>:ns, :ipadx=>2) + + # book (focus) + s = t.style_create('s1.f') + t.style_elements(s, ['e4', 'e1', 'e5']) + t.style_layout(s, 'e1', :padx=>[0,4], :expand=>:ns) + t.style_layout(s, 'e5', :expand=>:ns) + t.style_layout(s, 'e4', :union=>['e5'], :iexpand=>:ns, :ipadx=>2) + + # page (focus) + s = t.style_create('s2') + t.style_elements(s, ['e4', 'e2', 'e5']) + t.style_layout(s, 'e2', :padx=>[0,4], :expand=>:ns) + t.style_layout(s, 'e5', :expand=>:ns) + t.style_layout(s, 'e4', :union=>['e5'], :iexpand=>:ns, :ipadx=>2) + + parentList = [:root, '', '', '', '', '', ''] + parent = :root + [ + [0, 's1', "Welcome to Help"], + [0, 's2', "Introducing Windows 98"], + [1, 's2', "How to Use Help"], + [2, 's1' "Find a topic"], + [2, 's1', "Get more out of help"], + [1, 's2', "Register Your Software"], + [2, 's1', "Registering Windows 98 online"], + [1, 's2', "What's New in Windows 98"], + [2, 's1', "Innovative, easy-to-use features"], + [2, 's1', "Improved reliability"], + [2, 's1', "A faster operating system"], + [2, 's1', "True Web integration"], + [2, 's1', "More entertaining and fun"], + [1, 's2', "If You're New to Windows 98"], + [2, 's2', "Tips for Macintosh Users"], + [3, 's1', "Why does the mouse have two buttons?"] + ].each{|depth, style, text| + item = t.item_create + t.item_style_set(item, 0, style) + t.item_element_configure(item, 0, 'e3', :text=>text) + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_collapse(item) + else # TreeCtrl 1.0 + t.collapse(item) + end + t.item_lastchild(parentList[depth], item) + depth += 1 + parentList[depth] = item + } + + treeCtrlHelp = TkBindTag.new + + treeCtrlHelp.bind('Double-ButtonPress-1', + proc{|w, x, y| + if w.identify(x, y)[0] == 'header' + Tk::TreeCtrl::BindCallback.doubleButton1(w, x, y) + else + helpButton1(w, x, y) + end + Tk.callback_break + }, '%W %x %y') + + treeCtrlHelp.bind('ButtonPress-1', + proc{|w, x, y| + helpButton1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlHelp.bind('Button1-Motion', + proc{|w, x, y| + helpMotion1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlHelp.bind('Button1-Leave', + proc{|w, x, y| + helpLeave1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlHelp.bind('ButtonRelease-1', + proc{|w, x, y| + helpRelease1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlHelp.bind('Motion', proc{|w, x, y| helpMotion(w, x, y) }, '%W %x %y') + + treeCtrlHelp.bind('Leave', proc{|w, x, y| helpMotion(w, x, y) }, '%W %x %y') + + treeCtrlHelp.bind('Button1-Motion', + proc{|w, x, y| + if w.selection_get.length == 1 + w.item_toggle(w.selection_get[0]) + end + Tk.callback_break + }, '%W %x %y') + + @Priv[:help, :prev] = '' + + t.bindtags = [ t, treeCtrlHelp, Tk::TreeCtrl, t.winfo_toplevel, :all ] +end + +def helpButton1(w, x, y) + w.set_focus + id = w.identify(x, y) + @Priv['buttonMode'] = '' + if id[0] == 'header' + Tk::TreeCtrl::BindCallback.buttonPress1(w, x, y) + elsif id[0] == 'item' + item = id[1] + # didn't click an element + return if id.length != 6 + if w.selection_includes(item) + w.toggle(item) + return + end + if w.selection_get.length > 0 + item2 = w.selection_get[0] + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + w.item_collapse(item2) + else # TreeCtrl 1.0 + w.collapse(item2) + end + w.item_ancestors(item2).each{|i| + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + w.item_collapse(i) if w.compare(item, '!=', i) + else # TreeCtrl 1.0 + w.collapse(i) if w.compare(item, '!=', i) + end + } + end + w.activate(item) + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + w.item_ancestors(item).each{|i| + w.item_expand(i) + } + w.item_toggle(item) + else # TreeCtrl 1.0 + w.expand(*(w.item_ancestors(item))) + w.toggle(item) + end + w.selection_modify(item, :all) + end +end + +def helpMotion1(w, x, y) + case @Priv['buttonMode'] + when 'resize', 'header' + Tk::TreeCtrl::BindCallback.motion1(w, x, y) + end +end + +def helpLeave1(w, x, y) + # This is called when I do ButtonPress-1 on Unix for some reason, + # and buttonMode is undefined. + return unless @Priv.exist?('buttonMode') + case @Priv['buttonMode'] + when 'header' + w.column_configure(@Priv['column'], :sunken=>false) + end +end + +def helpRelease1(w, x, y) + case @Priv['buttonMode'] + when 'resize', 'header' + Tk::TreeCtrl::BindCallback.Release1(w, x, y) + end + @Priv['buttonMode'] = '' +end + +def helpMotion(w, x, y) + id = w.identify(x, y) + if id.empty? + elsif id[0] == 'header' + elsif id[0] == 'item' + item = id[1] + if id.length == 6 + if @Priv[:help, :prev] != TkComm._get_eval_string(item) + if @Priv[:help, :prev] != '' + w.item_state_set(@Priv[:help, :prev], '!mouseover') + end + w.item_state_set(item, 'mouseover') + @Priv[:help, :prev] = item + end + return + end + end + if @Priv[:help, :prev] != '' + w.item_state_set(@Priv[:help, :prev], '!mouseover') + @Priv[:help, :prev] = '' + end +end + +# Alternate implementation doesn't rely on mouseover state +def helpMotion2(w, x, y) + id = w.identify(x, y) + if id[0] == 'header' + elsif !id.empty? + item = id[1] + if id.kength == 6 + if @Priv[:help, :prev] != TkComm._get_eval_string(item) + if @Priv[:help, :prev] != '' + style = w.item_style_set(@Priv[:help, :prev], 0) + style.sub!(/\.f$/, '') + w.item_style_map(@Priv[:help, :prev], 0, style, ['e5', 'e3']) + end + style = w.item_style_set(item, 0) + w.item_style_map(item, 0, style + '.f', ['e3', 'e5']) + @Priv[:help, :prev] = item + end + return + end + end + if @Priv[:help, :prev] != '' + style = w.item_style_set(@Priv[:help, :prev], 0) + style.sub!(/\.f$/, '') + w.item_style_map(@Priv[:help, :prev], 0, style, ['e5', 'e3']) + @Priv[:help, :prev] = '' + end +end diff --git a/ext/tk/sample/tkextlib/treectrl/imovie.rb b/ext/tk/sample/tkextlib/treectrl/imovie.rb new file mode 100644 index 000000000..3c394fa12 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/imovie.rb @@ -0,0 +1,130 @@ +# +# Demo: iMovie +# +def demoIMovie(t) + t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false, + :selectmode=>:browse, :orient=>:horizontal, :wrap=>:window, + :showheader=>false, :background=>'#dcdcdc') + + if $HasColumnCreate + t.column_create + end + + init_pics('imovie-*') + + case @thisPlatform + when 'macintosh', 'macosx' + font1 = TkFont.new(['Geneva', 9]) + font2 = TkFont.new(['Geneva', 10]) + when 'unix' + font1 = TkFont.new(['Helvetica', -12]) + font2 = TkFont.new(['Helvetica', -14]) + else + font1 = TkFont.new(['Helvetica', 8]) + font2 = TkFont.new(['Helvetica', 10]) + end + + t.element_create('elemTime', :text, :font=>font1) + t.element_create('elemName', :text, :font=>font2, :lines=>1, :width=>80) + t.element_create('elemRect', :rect, :outline=>'#827878', :outlinewidth=>1, + :fill=>['#ffdc5a', ['selected'], 'white', []]) + t.element_create('elemImg', :image) + t.element_create('elemShadow', :rect, :outline=>'gray', :outlinewidth=>1, + :open=>:wn) + + s = t.style_create('STYLE', :orient=>:vertical) + t.style_elements(s, [ + 'elemShadow', 'elemRect', 'elemTime', + 'elemImg', 'elemName' + ]) + t.style_layout(s, 'elemShadow', :detach=>true, + :padx=>[1,2], :pady=>[1,2], :iexpand=>:es) + t.style_layout(s, 'elemTime', :padx=>[2,0]) + t.style_layout(s, 'elemImg', :pady=>[0,1]) + t.style_layout(s, 'elemName', :expand=>:we, :ipady=>[0,2], :padx=>[0,3], + :squeeze=>:x) + t.style_layout(s, 'elemRect', :union=>['elemTime', 'elemImg', 'elemName'], + :ipadx=>6, :padx=>[0,3], :pady=>[0,3]) + + # Set default item style + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.defaultstyle([s]) + end + + (0..4).each{|i| + [ + ['15:20', 'Clip 1', @images['imovie-01']], + ['19:18', 'Clip 2', @images['imovie-02']], + ['07:20', 'Clip 3', @images['imovie-03']], + ['07:20', 'Clip 4', @images['imovie-04']], + ['07:20', 'Clip 5', @images['imovie-05']], + ['07:20', 'Clip 6', @images['imovie-06']], + ['07:20', 'Clip 7', @images['imovie-07']] + ].each{|time, name, image| + item = t.item_create + unless (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_style_set(item, 0, s) + end + t.item_element_configure(item, 0, 'elemTime', :text=>time) + t.item_element_configure(item, 0, 'elemName', :text=>name) + t.item_element_configure(item, 0, 'elemImg', :image=>image) + t.item_lastchild(:root, item) + } + } + + t.notify_bind(t, 'Edit-accept', proc{|w, i, c, e, tt| + w.item_element_configure(i, c, e, :text=>tt) + }, '%T %I %C %E %t') + + iMovie = TkBindTag.new + iMovie.bind('ButtonPress-1', proc{|w, x, y| + iMovieButton1(w, x, y) + }, '%W %x %y') + + t.bindtags = [t, iMovie, Tk::TreeCtrl, t.winfo_toplevel, TkBindTag::ALL] +end + +def iMovieButton1(w, x, y) + w.set_focus + id = w.identify(x,y) + + if id.empty? + # Click outside any item + + elsif id[0] == 'header' + # Click in header + Tk::TreeCtrl::BindCallback.buttonPress1(w, x, y) + + elsif id[0] == 'item' + # Click in item + Tk::TreeCtrl::BindCallback.buttonPress1(w, x, y) + Tk.update + where, item, arg1, arg2, arg3, arg4 = id + case arg1 + when 'column' + i = id[1] + if id.length == 6 + e = id[-1] + if e == 'elemName' + exists = TkWinfo.exist?(w.path + '.entry') + Tk::TreeCtrl::BindCallback.entryOpen(w, i, 0, e) + ent = TkComm.window(w.path + '.entry') + unless exists + ent.configure(:borderwidth=>0, :justify=>:center, + :background=>'#ffdc5a') + x1, y1, x2, y2 = w.item_bbox(i, 0, e) + ent.place(:y=>y1 - 1) + end + ent.selection_clear + x1, y1, x2, y2 = t.item_bbox(i) + ent.place(:x=>x1 + 1, :width=>x2 - x1 - 5) + puts "@#{x - (x1 + 1)}" + # ent.icursor = ent.index("@#{x - (x1 + 1)}") + ent.icursor = ent.index(TkComm._at(x - (x1 + 1))) + end + end + end + end + + Tk.callback_break +end diff --git a/ext/tk/sample/tkextlib/treectrl/layout.rb b/ext/tk/sample/tkextlib/treectrl/layout.rb new file mode 100644 index 000000000..0ab65ac24 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/layout.rb @@ -0,0 +1,159 @@ +# +# Demo: Layout +# +def demoLayout(t) + t.configure(:showroot=>false, :showrootbutton=>true, :showbuttons=>true, + :showlines=>true, :itemheight=>0, :selectmode=>:browse) + + if $HasColumnCreate + t.column_create(:text=>'Layout') + else + t.column_configure(0, :text=>'Layout') + end + + t.element_create('e1', :rect, :width=>30, :height=>30, :fill=>'gray20') + t.element_create('e2', :rect, :width=>30, :height=>30, :fill=>'gray40', + :outline=>'blue', :outlinewidth=>3) + t.element_create('e3', :rect, :fill=>'gray60') + t.element_create('e4', :rect, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected', 'focus'], 'gray80', [] + ]) + t.element_create('e5', :rect, :fill=>'{sky blue}', :width=>20, :height=>20) + t.element_create('e6', :rect, :fill=>'{sea green}', :width=>30, :height=>16) + t.element_create('e7', :rect, :fill=>'{sky blue}', :width=>30, :height=>16) + t.element_create('e8', :rect, :fill=>'gray70', :height=>1) + + s = t.style_create('s1') + t.style_elements(s, ['e4', 'e3', 'e1', 'e2', 'e5', 'e6', 'e7']) + t.style_layout(s, 'e1', :padx=>[28, 4], :pady=>4) + t.style_layout(s, 'e2', :expand=>:es, :padx=>[0, 38]) + t.style_layout(s, 'e3', :union=>['e1', 'e2'], :ipadx=>4, :ipady=>4, :pady=>2) + t.style_layout(s, 'e4', :detach=>true, :iexpand=>:es) + t.style_layout(s, 'e5', :detach=>true, :padx=>[2,0], :pady=>2, :iexpand=>:s) + t.style_layout(s, 'e6', :detach=>true, :expand=>:ws, + :padx=>[0,2], :pady=>[2,0]) + t.style_layout(s, 'e7', :detach=>true, :expand=>:wn, + :padx=>[0,2], :pady=>[0,2]) + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + i = t.item_create(:button=>true) + else + i = t.item_create + t.item_hasbutton(i, true) + end + t.item_style_set(i, 0, s) + t.item_lastchild(:root, i) + parent = i + + i = t.item_create() + unless (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_hasbutton(i, false) + end + t.item_style_set(i, 0, s) + t.item_lastchild(parent, i) + + ### + + s = t.style_create('s2') + t.style_elements(s, ['e4', 'e3', 'e1']) + t.style_layout(s, 'e1', :padx=>8, :pady=>8, :iexpand=>:e) + t.style_layout(s, 'e3', :union=>['e1'], :ipadx=>[20,4], :ipady=>[4,12]) + t.style_layout(s, 'e4', :detach=>true, :iexpand=>:es) + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + i = t.item_create(:button=>true) + else + i = t.item_create + t.item_hasbutton(i, true) + end + t.item_style_set(i, 0, s) + t.item_lastchild(:root, i) + + i2 = t.item_create() + unless (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_hasbutton(i2, false) + end + t.item_style_set(i2, 0, s) + t.item_lastchild(i, i2) + + ### + + s = t.style_create('s3') + t.style_elements(s, ['e4', 'e3', 'e1', 'e5', 'e6']) + t.style_layout(s, 'e4', :union=>['e1', 'e6'], :ipadx=>8, :ipady=>[8,0]) + t.style_layout(s, 'e3', :union=>['e1', 'e5'], :ipadx=>4, :ipady=>4) + t.style_layout(s, 'e5', :ipady=>[0,20]) + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + i = t.item_create(:button=>true) + else + i = t.item_create + t.item_hasbutton(i, true) + end + t.item_style_set(i, 0, s) + t.item_lastchild(:root, i) + + i2 = t.item_create() + unless (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_hasbutton(i2, false) + end + t.item_style_set(i2, 0, s) + t.item_lastchild(i, i2) + + ### + + t.element_create('eb', :border, :background=>@SystemButtonFace, + :relief=>[:sunken, ['selected'], :raised, []], + :thickness=>2, :filled=>true) + t.element_create('et', :text) + + text = "Here is a text element surrounded by a border element.\nResize the column to watch me wrap." + + s = t.style_create('e4') + t.style_elements(s, ['eb', 'et']) + t.style_layout(s, 'eb', :union=>['et'], :ipadx=>2, :ipady=>2) + t.style_layout(s, 'et', :squeeze=>:x) + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + i = t.item_create(:button=>true) + else + i = t.item_create + t.item_hasbutton(i, true) + end + t.item_style_set(i, 0, s) + t.item_text(i, 0, text) + t.item_lastchild(:root, i) + parent = i + + i = t.item_create() + unless (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_hasbutton(i, false) + end + t.item_style_set(i, 0, s) + t.item_text(i, 0, text) + t.item_lastchild(parent, i) + + ### + + styleNum = 5 + [ + [:horizontal, [:s, :ns, :n]], + [:vertical, [:e, :we, :w]] + ].each{|orient, expandList| + expandList.each{|expand| + s = t.style_create("s#{styleNum}", :orient=>orient) + t.style_elements(s, ['e4', 'e8', 'e2', 'e5', 'e6']) + t.style_layout(s, 'e4', :detach=>true, :iexpand=>:es) + t.style_layout(s, 'e8', :detach=>true, :expand=>:n, :iexpand=>:e) + t.style_layout(s, 'e2', :expand=>expand) + t.style_layout(s, 'e5', :expand=>expand) + t.style_layout(s, 'e6', :expand=>expand) + styleNum += 1 + + i = t.item_create() + t.item_style_set(i, 0, s) + t.item_lastchild(:root, i) + } + } +end diff --git a/ext/tk/sample/tkextlib/treectrl/mailwasher.rb b/ext/tk/sample/tkextlib/treectrl/mailwasher.rb new file mode 100644 index 000000000..b695db510 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/mailwasher.rb @@ -0,0 +1,269 @@ +# +# Demo: MailWasher +# +def demoMailWasher(t) + init_pics('*checked') + + height = t.font.metrics(:linespace) + 2 + height = 18 if height < 18 + + t.configure(:showroot=>false, :showrootbutton=>false, :showbuttons=>false, + :showlines=>false, :itemheight=>height, :selectmode=>:browse, + :xscrollincrement=>1) + + pad = 4 + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.column_create(:text=>'Delete', :textpadx=>pad, :tag=>'delete') + t.column_create(:text=>'Bounce', :textpadx=>pad, :tag=>'bounce') + t.column_create(:text=>'Status', :width=>80, :textpadx=>pad, + :tag=>'status') + t.column_create(:text=>'Size', :width=>40, :textpadx=>pad, + :justify=>:right, :tag=>'size') + t.column_create(:text=>'From', :width=>140, :textpadx=>pad, :tag=>'from') + t.column_create(:text=>'Subject', :width=>240, :textpadx=>pad, + :tag=>'subject') + t.column_create(:text=>'Received', :textpadx=>pad, :arrow=>:up, + :arrowpad=>[4,0], :tag=>'received') + t.column_create(:text=>'Attachments', :textpadx=>pad, :tag=>'attachments') + + t.state_define('CHECK') + + t.element_create('imgCheck', :image, :image=>[ + @images['checked'], ['CHECK'], @images['unchecked'], [] + ]) + + else # TreeCtrl 1.0 + t.column_configure(0, :text=>'Delete', :textpadx=>pad, :tag=>'delete') + t.column_configure(1, :text=>'Bounce', :textpadx=>pad, :tag=>'bounce') + t.column_configure(2, :text=>'Status', :width=>80, :textpadx=>pad, + :tag=>'status') + t.column_configure(3, :text=>'Size', :width=>40, :textpadx=>pad, + :justify=>:right, :tag=>'size') + t.column_configure(4, :text=>'From', :width=>140, :textpadx=>pad, + :tag=>'from') + t.column_configure(5, :text=>'Subject', :width=>240, :textpadx=>pad, + :tag=>'subject') + t.column_configure(6, :text=>'Received', :textpadx=>pad, :arrow=>:up, + :arrowpad=>[4,0], :tag=>'received') + t.column_configure(7, :text=>'Attachments', :textpadx=>pad, + :tag=>'attachments') + + t.element_create('imgOff', :image, :image=>@images['unchecked']) + t.element_create('imgOn', :image, :image=>@images['checked']) + end + + t.element_create('border', :rect, :open=>:nw, :outline=>'gray', + :outlinewidth=>1, :fill=>[@SystemHighlight, ['selected']]) + t.element_create('txtAny', :text, :lines=>1, + :fill=>[@SystemHighlightText, ['selected']]) + t.element_create('txtNone', :text, :text=>'none', :lines=>1, + :fill=>[@SystemHighlightText, ['selected']]) + t.element_create('txtYes', :text, :text=>'yes', :lines=>1, + :fill=>[@SystemHighlightText, ['selected']]) + t.element_create('txtNormal', :text, :text=>'Normal', :lines=>1, + :fill=>[@SystemHighlightText, ['selected'], '#006800', []]) + t.element_create('txtPossSpam', :text, :text=>'Possible Spam', :lines=>1, + :fill=>[@SystemHighlightText, ['selected'], '#787800', []]) + t.element_create('txtProbSpam', :text, :text=>'Probably Spam', :lines=>1, + :fill=>[@SystemHighlightText, ['selected'], '#FF9000', []]) + t.element_create('txtBlacklist', :text, :text=>'Blacklisted', :lines=>1, + :fill=>[@SystemHighlightText, ['selected'], '#FF5800', []]) + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + s = t.style_create('styCheck') + t.style_elements(s, ['border', 'imgCheck']) + t.style_layout(s, 'border', :detach=>true, :iexpand=>:es) + t.style_layout(s, 'imgCheck', :expand=>:news) + else + ['Off', 'On'].each{|name| + s = t.style_create('sty' << name) + i = 'img' << name + t.style_elements(s, ['border', i]) + t.style_layout(s, 'border', :detach=>true, :iexpand=>:es) + t.style_layout(s, i, :expand=>:news) + } + end + + pad = 4 + + %w(Any None Yes Normal PossSpam ProbSpam Blacklist).each{|name| + s = t.style_create('sty' << name) + e = 'txt' << name + t.style_elements(s, ['border', e]) + t.style_layout(s, 'border', :detach=>true, :iexpand=>:es) + t.style_layout(s, e, :padx=>pad, :squeeze=>:x, :expand=>:ns) + } + + [ + ['baldy@spammer.com', "Your hair is thinning"], + ['flat@spammer.com', "Your breasts are too small"], + ['tiny@spammer.com', "Your penis is too small"], + ['dumbass@spammer.com', "You are not very smart"], + ['bankrobber@spammer.com', "You need more money"], + ['loser@spammer.com', "You need better friends"], + ['gossip@spammer.com', "Find out what your coworkers think about you"], + ['whoami@spammer.com', "Find out what you think about yourself"], + ['downsized@spammer.com', "You need a better job"], + ['poorhouse@spammer.com', "Your mortgage is a joke"], + ['spam4ever@spammer.com' "You need more spam"] + ].each{|frm, subj| + item = t.item_create + status = ['styNormal','styPossSpam','styProbSpam','styBlacklist'][rand(4)] + attachments = ['styNone','styYes'][rand(2)] + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + delete = [false, true][rand(2)] + bounce = [false, true][rand(2)] + t.item_style_set(item, + 0, 'styCheck', 1, 'styCheck', 2, status, 3, 'styAny', + 4, 'styAny', 5, 'styAny', 6, 'styAny', 7, attachments) + t.item_state_forcolumn(item, 'delete', 'CHECK') if delete + t.item_state_forcolumn(item, 'bounce', 'CHECK') if bounce + + else # TreeCtrl 1.0 + delete = ['styOn', 'styOff'][rand(2)] + bounce = ['styOn', 'styOff'][rand(2)] + t.item_style_set(item, + 0, delete, 1, bounce, 2, status, 3, 'styAny', + 4, 'styAny', 5, 'styAny', 6, 'styAny', 7, attachments) + end + + bytes = 512 + rand(1024 * 12) + size = "#{bytes / 1024 + 1}KB" + seconds = Tk::Clock.seconds - rand(100000) + received = Tk::Clock.format(seconds, '%d/%m/%y %I:%M %p') + t.item_text(item, 3, size, 4, frm, 5, subj, 6, received) + t.item_lastchild(:root, item) + } + + sortColumn = 6 + t.notify_bind(t, 'Header-invoke', + proc{|c, w| + if c == sortColumn + if w.column_cget(sortColumn, :arrow) == 'down' + order = :increasing + arrow = :up + else + order = :decreasing + arrow = :down + end + else + if w.column_cget(sortColumn, :arrow) == 'down' + order = :decreasing + arrow = :down + else + order = :increasing + arrow = :up + end + w.column_configure(sortColumn, :arrow=>:none) + sortColumn = c + end + w.column_configure(c, :arrow=>arrow) + case w.column_cget(c, :tag) + when 'bounce', 'delete' + w.item_sort(:root, order, + { + :column=>c, + :command=>proc{|item1, item2| + compareOnOff(w, c, item1, item2) + } + }, + { :column=>'subject', :dictionary=>true }) + when 'status' + w.item_sort(:root, order, + { :column=>c, :dictionary=>true }) + when 'from' + w.item_sort(:root, order, + { :column=>c, :dictionary=>true }, + { :column=>'subject', :dictionary=>true }) + when 'subject' + w.item_sort(:root, order, + { :column=>c, :dictionary=>true }) + when 'size' + w.item_sort(:root, order, + { :column=>c, :dictionary=>true }, + { :column=>'subject', :dictionary=>true }) + when 'received' + w.item_sort(:root, order, + { :column=>c, :dictionary=>true }, + { :column=>'subject', :dictionary=>true }) + when 'attachments' + w.item_sort(:root, order, + { :column=>c, :dictionary=>true }, + { :column=>'subject', :dictionary=>true }) + end + }, '%C %T') + + mailWasher = TkBindTag.new + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + mailWasher.bind('ButtonPress-1', + proc{|w, x, y| + id = w.identify(x, y) + if id.empty? + elsif id[0] == 'header' + else + what, item, where, arg1, arg2, arg3 = id + if where == 'column' + tag = w.column_cget(arg1, :tag) + if tag == 'delete' || tag == 'bounce' + w.item_state_forcolumn(item, arg1, '~CHECK') + end + end + end + }, '%W %x %y') + else # TreeCtrl 1.0 + mailWasher.bind('ButtonPress-1', + proc{|w, x, y| + id = w.identify(x, y) + if id.empty? + elsif id[0] == 'header' + else + what, item, where, arg1, arg2, arg3 = id + if where == 'column' + tag = w.column_cget(arg1, :tag) + if tag == 'delete' || tag == 'bounce' + style = w.item_style_set(item, arg1) + if style == 'styOn' + style = 'styOff' + else + style = 'styOn' + end + w.item_style_set(item, arg1, style) + @display_styles_in_item.call(item) + end + end + end + }, '%W %x %y') + end + + t.bindtags = [t, mailWasher, Tk::TreeCtrl, t.winfo_toplevel, TkBindTag::ALL] +end + +if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + def compareOnOff(w, c, item1, item2) + s1 = w.item_state_forcolumn(item1, c) + s2 = w.item_state_forcolumn(item2, c) + if (s1 == s2) + 0 + elsif (s1 == 'CHECK') + -1 + else + 1 + end + end + +else # TreeCtrl 1.0 + def compareOnOff(w, c, item1, item2) + s1 = w.item_style_set(item1, c) + s2 = w.item_style_set(item2, c) + if (s1 == s2) + 0 + elsif (s1 == 'styOff') + -1 + else + 1 + end + end +end diff --git a/ext/tk/sample/tkextlib/treectrl/outlook-folders.rb b/ext/tk/sample/tkextlib/treectrl/outlook-folders.rb new file mode 100644 index 000000000..e56ba3f88 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/outlook-folders.rb @@ -0,0 +1,124 @@ +# +# Demo: Outlook Express folder list +# +def demoOutlookFolders(t) + init_pics('outlook-*') + + height = t.font.metrics(:linespace) + 2 + height = 18 if height < 18 + + t.configure(:itemheight=>height, :selectmode=>:browse, :showlines=>true, + :showroot=>true, :showrootbutton=>false, :showbuttons=>true) + + if $HasColumnCreate + t.column_create(:text=>'Folders') + else + t.column_configure(0, :text=>'Folders') + end + + t.element_create('e1', :image) + t.element_create('e2', :text, :lines=>1, + :fill=>[@SystemHighlightText, ['selected', 'focus']]) + t.element_create('e3', :text, :lines=>1, :font=>t.font.dup.weight(:bold), + :fill=>[@SystemHighlightText, ['selected', 'focus']]) + t.element_create('e4', :text, :fill=>'blue') + t.element_create('e5', :image, :image=>@images['outlook-folder']) + t.element_create('e6', :rect, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected', 'focus'], + 'gray', ['selected', '!focus'] + ]) + + # image + text + s = t.style_create('s1') + t.style_elements(s, ['e6', 'e1', 'e2']) + t.style_layout(s, 'e1', :expand=>:ns) + t.style_layout(s, 'e2', :padx=>[4,0], :expand=>:ns, :squeeze=>:x) + t.style_layout(s, 'e6', :union=>['e2'], :iexpand=>:ns, :ipadx=>2) + + # image + text + text + s = t.style_create('s2') + t.style_elements(s, ['e6', 'e1', 'e3', 'e4']) + t.style_layout(s, 'e1', :expand=>:ns) + t.style_layout(s, 'e3', :padx=>4, :expand=>:ns, :squeeze=>:x) + t.style_layout(s, 'e4', :expand=>:ns) + t.style_layout(s, 'e6', :union=>['e3'], :iexpand=>:ns, :ipadx=>2) + + # folder + text + s = t.style_create('s3') + t.style_elements(s, ['e6', 'e5', 'e2']) + t.style_layout(s, 'e5', :expand=>:ns) + t.style_layout(s, 'e2', :padx=>[4,0], :expand=>:ns, :squeeze=>:x) + t.style_layout(s, 'e6', :union=>['e2'], :iexpand=>:ns, :ipadx=>2) + + # folder + text + text + s = t.style_create('s4') + t.style_elements(s, ['e6', 'e5', 'e3', 'e4']) + t.style_layout(s, 'e5', :expand=>:ns) + t.style_layout(s, 'e3', :padx=>4, :expand=>:ns, :squeeze=>:x) + t.style_layout(s, 'e4', :expand=>:ns) + t.style_layout(s, 'e6', :union=>['e3'], :iexpand=>:ns, :ipadx=>2) + + t.item_style_set(:root, 0, 's1') + t.item_complex(:root, + [ + ['e1', {:image=>@images['outlook-main']}], + ['e2', {:text=>'Outlook Express'}] + ]) + + parentList = [:root, '', '', '', '', '', ''] + parent = :root + [ + [0, :local, "Local Folders", true, 0], + [1, :inbox, 'Inbox', false, 5], + [1, :outbox, 'Outbox', false, 0], + [1, :sent, "Sent Items", false, 0], + [1, :deleted, "Deleted Items", false, 50], + [1, :draft, 'Drafts', false, 0], + [1, :folder, "Messages to Dad", false, 0], + [1, :folder, "Messages to Sis", false, 0], + [1, :folder, "Messages to Me", false, 0], + [2, :folder, "2001", false, 0], + [2, :folder, "2000", false, 0], + [2, :folder, "1999", false, 0], + [0, :server, "news.gmane.org", true, 0], + [1, :group, "gmane.comp.lang.lua.general", false, 498] + ].each{|depth, img, text, button, unread| + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + item = t.item_create(:button=>button) + else + item = t.item_create + t.item_hasbutton(item, button) + end + if img == :folder + if unread != 0 + t.item_style_set(item, 0, 's4') + t.item_complex(item, + [['e3', {:text=>text}], ['e4', {:text=>"(#{unread})"}]]) + else + t.item_style_set(item, 0, 's3') + t.item_complex(item, [['e2', {:text=>text}]]) + end + else + if unread != 0 + t.item_style_set(item, 0, 's2') + t.item_complex(item, + [ + ['e1', {:image=>@images["outlook-#{img}"]}], + ['e3', {:text=>text}], + ['e4', {:text=>"(#{unread})"}] + ]) + else + t.item_style_set(item, 0, 's1') + t.item_complex(item, + [ + ['e1', {:image=>@images["outlook-#{img}"]}], + ['e2', {:text=>text}] + ]) + end + end + t.item_lastchild(parentList[depth], item) + depth += 1 + parentList[depth] = item + } +end diff --git a/ext/tk/sample/tkextlib/treectrl/outlook-newgroup.rb b/ext/tk/sample/tkextlib/treectrl/outlook-newgroup.rb new file mode 100644 index 000000000..41b7fbb86 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/outlook-newgroup.rb @@ -0,0 +1,447 @@ +# +# Demo: Outlook Express newsgroup messages +# +def demoOutlookNewsgroup(t) + init_pics('outlook-*') + + height = t.font.metrics(:linespace) + 2 + hehght = 18 if height < 18 + t.configure(:itemheight=>height, :selectmode=>:browse, :showlines=>false, + :showroot=>false, :showrootbutton=>false, :showbuttons=>true) + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.column_create(:image=>@images['outlook-clip'], :tag=>'clip') + t.column_create(:image=>@images['outlook-arrow'], :tag=>'arrow') + t.column_create(:image=>@images['outlook-watch'], :tag=>'watch') + t.column_create(:text=>'Subject', :width=>250, :tag=>'subject') + t.column_create(:text=>'From', :width=>150, :tag=>'from') + t.column_create(:text=>'Sent', :width=>150, :tag=>'sent') + t.column_create(:text=>'Size', :width=>60, :justify=>:right, :tag=>'size') + else # TreeCtrl 1.0 + t.column_configure(0, :image=>@images['outlook-clip'], :tag=>'clip') + t.column_configure(1, :image=>@images['outlook-arrow'], :tag=>'arrow') + t.column_configure(2, :image=>@images['outlook-watch'], :tag=>'watch') + t.column_configure(3, :text=>'Subject', :width=>250, :tag=>'subject') + t.column_configure(4, :text=>'From', :width=>150, :tag=>'from') + t.column_configure(5, :text=>'Sent', :width=>150, :tag=>'sent') + t.column_configure(6, :text=>'Size', :width=>60, :justify=>:right, + :tag=>'size') + end + + # Would be nice if I could specify a column -tag too + t.treecolumn = 3 + + # State for a read message + t.state_define('read') + + # State for a message with unread descendants + t.state_define('unread') + + t.element_create('elemImg', :image, + :image=>[ + @images['outlook-read-2Sel'], + ['selected', 'read', 'unread', '!open'], + @images['outlook-read-2'], ['read', 'unread', '!open'], + @images['outlook-readSel'], ['selected', 'read'], + @images['outlook-read'], ['read'], + @images['outlook-unreadSel'], ['selected'], + @images['outlook-unread'], [] + ]) + t.element_create('elemTxt', :text, :lines=>1, + :fill=>[@SystemHighlightText, ['selected', 'focus']], + :font=>[ + t.font.dup.weight(:bold), ['read', 'unread', '!open'], + t.font.dup.weight(:bold), ['!read'] + ]) + t.element_create('sel.e', :rect, :open=>:e, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected', 'focus'], + 'gray', ['selected', '!focus'] + ]) + t.element_create('sel.w', :rect, :open=>:w, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected', 'focus'], + 'gray', ['selected', '!focus'] + ]) + t.element_create('sel.we', :rect, :open=>:we, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected', 'focus'], + 'gray', ['selected', '!focus'] + ]) + + # Image + text + s = t.style_create('s1') + t.style_elements(s, ['sel.e', 'elemImg', 'elemTxt']) + t.style_layout(s, 'elemImg', :expand=>:ns) + t.style_layout(s, 'elemTxt', :padx=>[2,6], :squeeze=>:x, :expand=>:ns) + t.style_layout(s, 'sel.e', :union=>['elemTxt'], + :iexpand=>:nes, :ipadx=>[2,0]) + + # Text + s = t.style_create('s2.we') + t.style_elements(s, ['sel.we', 'elemTxt']) + t.style_layout(s, 'elemTxt', :padx=>6, :squeeze=>:x, :expand=>:ns) + t.style_layout(s, 'sel.we', :detach=>true, :iexpand=>:es) + + # Text + s = t.style_create('s2.w') + t.style_elements(s, ['sel.w', 'elemTxt']) + t.style_layout(s, 'elemTxt', :padx=>6, :squeeze=>:x, :expand=>:ns) + t.style_layout(s, 'sel.w', :detach=>true, :iexpand=>:es) + + # Set default item style + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.defaultstyle = ['', '', '', 's1', 's2.we', 's2.we', 's2.w'] + end + + msgCnt = 100 + thread = 0 + + @Message = Hash.new{|k, v| k[v] = Hash.new} + @Message[:count][0] = 0 + + items = [t.index(:root)] + + (1...(msgCnt)).each{|i| + item_i = t.item_create + item_j = nil + j = nil + loop { + j = rand(i) + item_j = items[j] + break if j == 0 + next if t.depth(item_j) == 5 + next if @Message[:count][@Message[:thread][item_j]] == 15 + break + } + t.item_lastchild(item_j, item_i) + + @Message[:read][item_i] = (rand(2) == 0) + if j == 0 + thread += 1 + @Message[:thread][item_i] = thread + @Message[:seconds][item_i] = (Tk::Clock.seconds - rand(500000)) + @Message[:seconds2][item_i] = @Message[:seconds][item_i] + @Message[:count][thread] = 1 + else + @Message[:thread][item_i] = @Message[:thread][item_j] + @Message[:seconds][item_i] = (@Message[:seconds2][item_j] + rand(10000)) + @Message[:seconds2][item_i] = @Message[:seconds][item_i] + @Message[:seconds2][item_j] = @Message[:seconds][item_i] + @Message[:count][@Message[:thread][item_j]] += 1 + end + items << item_i + } + + (1...(msgCnt)).each{|i| + item_i = items[i] + subject = "This is thread number #{@Message[:thread][item_i]}" + from = 'somebody@somewhere.net' + sent = Tk::Clock.format(@Message[:seconds][item_i], "%d/%m/%y %I:%M %p") + size = "#{1 + rand(10)}KB" + + # This message has been read + t.item_state_set(item_i, 'read') if @Message[:read][item_i] + + # This message has unread descendants + t.item_state_set(item_i, 'unread') if anyUnreadDescendants(t, item_i) + + if t.item_numchildren(item_i) > 0 + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_configure(item_i, :button=>true) + else # TreeCtrl 1.0 + t.item_hasbutton(item_i, true) + end + + # Collapse some messages + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_collapse(item_i) if rand(2) == 0 + else # TreeCtrl 1.0 + t.collapse(item_i) if rand(2) == 0 + end + end + + unless (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_style_set(item_i, 3, 's1', 4, 's2.we', 5, 's2.we', 6, 's2.w') + end + t.item_text(item_i, 3, subject, 4, from, 5, sent, 6, size) + } + + # Do something when the selection changes + t.notify_bind(t, 'Selection', + proc{|w| + if w.selection_count == 1 + # One item is selected + if @Message[:afterID][:id] + Tk.after_cancel(@Message[:afterID][:id]) + end + @Message[:afterID][:item] = w.selection_get[0] + @Message[:afterID][:id] = Tk.after(500, proc{ + messageReadDelayed(w) + }) + end + }, '%T') +end + +def messageReadDelayed(t) + @Message[:afterID].delete(:id) + i = @Message[:afterID][:item] + return unless t.selection_includes(i) + + # This message is not read + unless @Message[:read][i] + # Read the message + t.item_state_set(i, 'read') + @Message[:read][i] = true + + # Check ancestors (except root) + t.item_ancestors(i)[0..-2].each{|i2| + # This ancestor has no more unread descendants + t.item_state_set(i2, '!unread') unless anyUnreadDescendants(t, i2) + } + end +end + +# Alternate implementation which does not rely on run-time states +def demoOutlookNewsgroup2(t) + init_pics('outlook-*') + + height = t.font.metrics(:linespace) + 2 + hehght = 18 if height < 18 + t.configure(:itemheight=>height, :selectmode=>:browse, :showlines=>false, + :showroot=>false, :showrootbutton=>false, :showbuttons=>true) + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.column_create(:image=>@images['outlook-clip'], :tag=>'clip') + t.column_create(:image=>@images['outlook-arrow'], :tag=>'arrow') + t.column_create(:image=>@images['outlook-watch'], :tag=>'watch') + t.column_create(:text=>'Subject', :width=>250, :tag=>'subject') + t.column_create(:text=>'From', :width=>150, :tag=>'from') + t.column_create(:text=>'Sent', :width=>150, :tag=>'sent') + t.column_create(:text=>'Size', :width=>60, :justify=>:right, :tag=>'size') + else # TreeCtrl 1.0 + t.column_configure(0, :image=>@images['outlook-clip'], :tag=>'clip') + t.column_configure(1, :image=>@images['outlook-arrow'], :tag=>'arrow') + t.column_configure(2, :image=>@images['outlook-watch'], :tag=>'watch') + t.column_configure(3, :text=>'Subject', :width=>250, :tag=>'subject') + t.column_configure(4, :text=>'From', :width=>150, :tag=>'from') + t.column_configure(5, :text=>'Sent', :width=>150, :tag=>'sent') + t.column_configure(6, :text=>'Size', :width=>60, :justify=>:right, + :tag=>'size') + end + + t.treecolumn = 3 + + t.element_create('image.unread', :image, :image=>@images['outlook-unread']) + t.element_create('image.read', :image, :image=>@images['outlook-read']) + t.element_create('image.read2', :image, :image=>@images['outlook-read-2']) + t.element_create('text.read', :text, :lines=>1, + :fill=>[@SystemHighlightText, ['selected', 'focus']]) + t.element_create('text.unread', :text, :lines=>1, + :fill=>[@SystemHighlightText, ['selected', 'focus']], + :font=>t.font.dup.weight(:bold)) + t.element_create('sel.e', :rect, :open=>:e, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected', 'focus'], + 'gray', ['selected', '!focus'] + ]) + t.element_create('sel.w', :rect, :open=>:w, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected', 'focus'], + 'gray', ['selected', '!focus'] + ]) + t.element_create('sel.we', :rect, :open=>:we, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected', 'focus'], + 'gray', ['selected', '!focus'] + ]) + + # Image + text + s = t.style_create('unread') + t.style_elements(s, ['sel.e', 'image.unread', 'text.unread']) + t.style_layout(s, 'image.unread', :expand=>:ns) + t.style_layout(s, 'text.unread', :padx=>[2,6], :squeeze=>:x, :expand=>:ns) + t.style_layout(s, 'sel.e', :union=>['text.unread'], + :iexpand=>:nes, :ipadx=>[2,0]) + + # Image + text + s = t.style_create('read') + t.style_elements(s, ['sel.e', 'image.read', 'text.read']) + t.style_layout(s, 'image.read', :expand=>:ns) + t.style_layout(s, 'text.read', :padx=>[2,6], :squeeze=>:x, :expand=>:ns) + t.style_layout(s, 'sel.e', :union=>['text.read'], + :iexpand=>:nes, :ipadx=>[2,0]) + + # Image + text + s = t.style_create('read2') + t.style_elements(s, ['sel.e', 'image.read2', 'text.unread']) + t.style_layout(s, 'image.read2', :expand=>:ns) + t.style_layout(s, 'text.unread', :padx=>[2,6], :squeeze=>:x, :expand=>:ns) + t.style_layout(s, 'sel.e', :union=>['text.unread'], + :iexpand=>:nes, :ipadx=>[2,0]) + + # Text + s = t.style_create('unread.we') + t.style_elements(s, ['sel.we', 'text.unread']) + t.style_layout(s, 'text.unread', :padx=>6, :squeeze=>:x, :expand=>:ns) + t.style_layout(s, 'sel.we', :detach=>true, :iexpand=>:es) + + # Text + s = t.style_create('read.we') + t.style_elements(s, ['sel.we', 'text.read']) + t.style_layout(s, 'text.read', :padx=>6, :squeeze=>:x, :expand=>:ns) + t.style_layout(s, 'sel.we', :detach=>true, :iexpand=>:es) + + # Text + s = t.style_create('unread.w') + t.style_elements(s, ['sel.w', 'text.unread']) + t.style_layout(s, 'text.unread', :padx=>6, :squeeze=>:x, :expand=>:ns) + t.style_layout(s, 'sel.w', :detach=>true, :iexpand=>:es) + + # Text + s = t.style_create('read.w') + t.style_elements(s, ['sel.w', 'text.read']) + t.style_layout(s, 'text.read', :padx=>6, :squeeze=>:x, :expand=>:ns) + t.style_layout(s, 'sel.w', :detach=>true, :iexpand=>:es) + + msgCnt = 100 + thread = 0 + + @Message = Hash.new{|k, v| k[v] = Hash.new} + @Message[:count][0] = 0 + + (1...(msgCnt)).each{|i| + t.item_create + j = nil + loop { + j = rand(i) + break if j == 0 + next if t.depth(j) == 5 + next if @Message[:count][@Message[:thread][j]] == 15 + break + } + t.item_lastchild(j, i) + + @Message[:read][i] = (rand(2) == 0) + if j == 0 + thread += 1 + @Message[:thread][i] = thread + @Message[:seconds][i] = (Tk::Clock.seconds - rand(500000)) + @Message[:seconds2][i] = @Message[:seconds][i] + @Message[:count][thread] = 1 + else + @Message[:thread][i] = @Message[:thread][j] + @Message[:seconds][i] = (@Message[:seconds2][j] + rand(10000)) + @Message[:seconds2][i] = @Message[:seconds][i] + @Message[:seconds2][j] = @Message[:seconds][i] + @Message[:count][@Message[:thread][j]] += 1 + end + } + + (1...(msgCnt)).each{|i| + subject = "This is thread number #{@Message[:thread][i]}" + from = 'somebody@somewhere.net' + sent = Tk::Clock.format(@Message[:seconds][i], "%d/%m/%y %I:%M %p") + size = "#{1 + rand(10)}KB" + if @Message[:read][i] + style = 'read' + style2 = 'read2' + else + style = 'unread' + style2 = 'unread2' + end + t.item_style_set(i, 3, style, 4, "#{style2}.we", 5, "#{style2}.we", + 6, "#{style2}.w") + t.item_text(i, 3, subject, 4, from, 5, sent, 6, size) + if t.item_numchildren(i) > 0 + t.item_configure(item_i, :button=>true) + end + } + + # Do something when the selection changes + t.notify_bind(t, 'Selection', + proc{|w| + if w.selection_count == 1 + i = t.selection_get[0] + unless @Message[:read][i] + if t.item_isopen(i) || !anyUnreadDescendants(t, i) + # unread -> read + t.item_style_map(i, 'subject', 'read', + ['text.unread', 'text.read']) + t.item_style_map(i, 'from', 'read.we', + ['text.unread', 'text.read']) + t.item_style_map(i, 'sent', 'read.we', + ['text.unread', 'text.read']) + t.item_style_map(i, 'size', 'read.w', + ['text.unread', 'text.read']) + else + # unread -> read2 + t.item_style_map(i, 'subject', 'read2', + ['text.unread', 'text.unread']) + end + + @Message[:read][i] = true + @display_styles_in_item.call(i) + end + end + }, '%T') + + t.notify_bind(t, 'Expand-after', + proc{|w| + if @Messge[:read][i] && anyUnreadDescendants(t, i) + # read2 -> read + t.item_style_map(i, 'subject', 'read', + ['text.unread', 'text.read']) + # unread -> read + t.item_style_map(i, 'from', 'read.we', + ['text.unread', 'text.read']) + t.item_style_map(i, 'sent', 'read.we', + ['text.unread', 'text.read']) + t.item_style_map(i, 'size', 'read.w', + ['text.unread', 'text.read']) + end + }, '%T') + + t.notify_bind(t, 'Collapse-after', + proc{|w| + if @Messge[:read][i] && anyUnreadDescendants(t, i) + # read -> read2 + t.item_style_map(i, 'subject', 'read2', + ['text.read', 'text.unread']) + # read -> unread + t.item_style_map(i, 'from', 'unread.we', + ['text.read', 'text.unread']) + t.item_style_map(i, 'sent', 'unread.we', + ['text.read', 'text.unread']) + t.item_style_map(i, 'size', 'unread.w', + ['text.read', 'text.unread']) + end + }, '%T') + + (1...(msgCnt)).each{|i| + if rand(2) == 0 + if t.item_numchildren(i) > 0 + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_collapse(i) + else # TreeCtrl 1.0 + t.collapse(i) + end + end + end + } +end + +def anyUnreadDescendants(t, i) + itemList = [ t.item_firstchild(i) ] + while(itemList.length > 0) + item = itemList.pop + + return true unless @Message[:read][item] + + item2 = t.item_nextsibling(item) + itemList.push(item2) if item2 != '' + item2 = t.item_firstchild(item) + itemList.push(item2) if item2 != '' + end + false +end diff --git a/ext/tk/sample/tkextlib/treectrl/pics/big-dll.gif b/ext/tk/sample/tkextlib/treectrl/pics/big-dll.gif Binary files differnew file mode 100644 index 000000000..09170c0e2 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/big-dll.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/big-exe.gif b/ext/tk/sample/tkextlib/treectrl/pics/big-exe.gif Binary files differnew file mode 100644 index 000000000..e19aac1a2 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/big-exe.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/big-file.gif b/ext/tk/sample/tkextlib/treectrl/pics/big-file.gif Binary files differnew file mode 100644 index 000000000..6c752312a --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/big-file.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/big-folder.gif b/ext/tk/sample/tkextlib/treectrl/pics/big-folder.gif Binary files differnew file mode 100644 index 000000000..186c9749f --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/big-folder.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/big-txt.gif b/ext/tk/sample/tkextlib/treectrl/pics/big-txt.gif Binary files differnew file mode 100644 index 000000000..a93492586 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/big-txt.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/checked.gif b/ext/tk/sample/tkextlib/treectrl/pics/checked.gif Binary files differnew file mode 100644 index 000000000..3b9b176ab --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/checked.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/file.gif b/ext/tk/sample/tkextlib/treectrl/pics/file.gif Binary files differnew file mode 100644 index 000000000..a64c2a06b --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/file.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/folder-closed.gif b/ext/tk/sample/tkextlib/treectrl/pics/folder-closed.gif Binary files differnew file mode 100644 index 000000000..0a064376c --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/folder-closed.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/folder-open.gif b/ext/tk/sample/tkextlib/treectrl/pics/folder-open.gif Binary files differnew file mode 100644 index 000000000..3fac27ffd --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/folder-open.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/help-book-closed.gif b/ext/tk/sample/tkextlib/treectrl/pics/help-book-closed.gif Binary files differnew file mode 100644 index 000000000..0a0497bfa --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/help-book-closed.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/help-book-open.gif b/ext/tk/sample/tkextlib/treectrl/pics/help-book-open.gif Binary files differnew file mode 100644 index 000000000..40656c519 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/help-book-open.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/help-page.gif b/ext/tk/sample/tkextlib/treectrl/pics/help-page.gif Binary files differnew file mode 100644 index 000000000..e1ce1d72f --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/help-page.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-01.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-01.gif Binary files differnew file mode 100644 index 000000000..5fd921555 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-01.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-02.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-02.gif Binary files differnew file mode 100644 index 000000000..3d2d1c17c --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-02.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-03.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-03.gif Binary files differnew file mode 100644 index 000000000..9fccf12b5 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-03.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-04.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-04.gif Binary files differnew file mode 100644 index 000000000..eff851c9b --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-04.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-05.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-05.gif Binary files differnew file mode 100644 index 000000000..ad00c827f --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-05.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-06.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-06.gif Binary files differnew file mode 100644 index 000000000..238bf162a --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-06.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-07.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-07.gif Binary files differnew file mode 100644 index 000000000..a9287e1b1 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-07.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-check-off.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-check-off.gif Binary files differnew file mode 100644 index 000000000..e64866a39 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-check-off.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-check-on.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-check-on.gif Binary files differnew file mode 100644 index 000000000..cf652beff --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-check-on.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-print.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-print.gif Binary files differnew file mode 100644 index 000000000..7ac25b10e --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-print.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-radio-off.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-radio-off.gif Binary files differnew file mode 100644 index 000000000..90ef62971 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-radio-off.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-radio-on.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-radio-on.gif Binary files differnew file mode 100644 index 000000000..9de742c19 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-radio-on.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-search.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-search.gif Binary files differnew file mode 100644 index 000000000..1f9a04770 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-search.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-security.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-security.gif Binary files differnew file mode 100644 index 000000000..86d394378 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-security.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/mac-collapse.gif b/ext/tk/sample/tkextlib/treectrl/pics/mac-collapse.gif Binary files differnew file mode 100644 index 000000000..81302c80c --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/mac-collapse.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/mac-expand.gif b/ext/tk/sample/tkextlib/treectrl/pics/mac-expand.gif Binary files differnew file mode 100644 index 000000000..0a2cd8004 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/mac-expand.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-arrow.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-arrow.gif Binary files differnew file mode 100644 index 000000000..b1c2afd42 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-arrow.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-clip.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-clip.gif Binary files differnew file mode 100644 index 000000000..857813270 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-clip.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-deleted.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-deleted.gif Binary files differnew file mode 100644 index 000000000..7cc8369b4 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-deleted.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-draft.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-draft.gif Binary files differnew file mode 100644 index 000000000..f19585050 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-draft.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-folder.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-folder.gif Binary files differnew file mode 100644 index 000000000..b3f733563 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-folder.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-group.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-group.gif Binary files differnew file mode 100644 index 000000000..29ad9b466 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-group.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-inbox.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-inbox.gif Binary files differnew file mode 100644 index 000000000..f41d80444 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-inbox.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-local.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-local.gif Binary files differnew file mode 100644 index 000000000..0c74970d3 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-local.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-main.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-main.gif Binary files differnew file mode 100644 index 000000000..92325fa85 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-main.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-outbox.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-outbox.gif Binary files differnew file mode 100644 index 000000000..c7e80527a --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-outbox.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-read-2.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-read-2.gif Binary files differnew file mode 100644 index 000000000..2f15a3af0 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-read-2.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-read.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-read.gif Binary files differnew file mode 100644 index 000000000..a6f956207 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-read.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-sent.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-sent.gif Binary files differnew file mode 100644 index 000000000..963b56c4c --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-sent.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-server.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-server.gif Binary files differnew file mode 100644 index 000000000..c950845d6 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-server.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-unread.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-unread.gif Binary files differnew file mode 100644 index 000000000..3df4b9943 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-unread.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-watch.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-watch.gif Binary files differnew file mode 100644 index 000000000..87ec86131 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-watch.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/sky.gif b/ext/tk/sample/tkextlib/treectrl/pics/sky.gif Binary files differnew file mode 100644 index 000000000..b7fbf14a0 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/sky.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/small-dll.gif b/ext/tk/sample/tkextlib/treectrl/pics/small-dll.gif Binary files differnew file mode 100644 index 000000000..d8875ec23 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/small-dll.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/small-exe.gif b/ext/tk/sample/tkextlib/treectrl/pics/small-exe.gif Binary files differnew file mode 100644 index 000000000..69d30beac --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/small-exe.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/small-file.gif b/ext/tk/sample/tkextlib/treectrl/pics/small-file.gif Binary files differnew file mode 100644 index 000000000..f34066287 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/small-file.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/small-folder.gif b/ext/tk/sample/tkextlib/treectrl/pics/small-folder.gif Binary files differnew file mode 100644 index 000000000..ad1b24da8 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/small-folder.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/small-txt.gif b/ext/tk/sample/tkextlib/treectrl/pics/small-txt.gif Binary files differnew file mode 100644 index 000000000..cdc7cbfe9 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/small-txt.gif diff --git a/ext/tk/sample/tkextlib/treectrl/pics/unchecked.gif b/ext/tk/sample/tkextlib/treectrl/pics/unchecked.gif Binary files differnew file mode 100644 index 000000000..833e48268 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/pics/unchecked.gif diff --git a/ext/tk/sample/tkextlib/treectrl/random.rb b/ext/tk/sample/tkextlib/treectrl/random.rb new file mode 100644 index 000000000..05b6c2123 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/random.rb @@ -0,0 +1,505 @@ +# +def random_N + @RandomN[0] || 500 +end + +# +# Demo: random N items +# +def demoRandom(t) + init_pics('folder-*', 'small-*') + + height = t.font.metrics(:linespace) + 2 + hehght = 18 if height < 18 + t.configure(:itemheight=>height, :selectmode=>:extended, + :showroot=>true, :showrootbutton=>true, :showbuttons=>true, + :showlines=>true, :scrollmargin=>16, + :xscrolldelay=>[500, 50], :yscrolldelay=>[500, 50]) + + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.column_create(:expand=>true, :text=>'Item', + :itembackground=>['#e0e8f0', []], :tag=>'item') + t.column_create(:text=>'Parent', :justify=>:center, + :itembackground=>['gray90', []], :tag=>'parent') + t.column_create(:text=>'Depth', :justify=>:center, + :itembackground=>['linen', []], :tag=>'depth') + else # TreeCtrl 1.0 + t.column_configure(0, :expand=>true, :text=>'Item', + :itembackground=>['#e0e8f0', []], :tag=>'item') + t.column_configure(1, :text=>'Parent', :justify=>:center, + :itembackground=>['gray90', []], :tag=>'parent') + t.column_configure(2, :text=>'Depth', :justify=>:center, + :itembackground=>['linen', []], :tag=>'depth') + end + + t.element_create('e1', :image, :image=>[ + @images['folder-open'], ['open'], + @images['folder-closed'], [] + ]) + t.element_create('e2', :image, :image=>@images['small-file']) + t.element_create('e3', :text, + :fill=>[@SystemHighlightText, ['selected', 'focus']]) + t.element_create('e4', :text, :fill=>'blue') + t.element_create('e6', :text) + t.element_create('e5', :rect, :showfocus=>true, + :fill=>[ + @SystemHighlight, ['selected', 'focus'], + 'gray', ['selected', '!focus'] + ]) + + s = t.style_create('s1') + t.style_elements(s, ['e5', 'e1', 'e3', 'e4']) + t.style_layout(s, 'e1', :padx=>[0,4], :expand=>:ns) + t.style_layout(s, 'e3', :padx=>[0,4], :expand=>:ns) + t.style_layout(s, 'e4', :padx=>[0,6], :expand=>:ns) + t.style_layout(s, 'e5', :union=>['e3'], :iexpand=>:ns, :ipadx=>2) + + s = t.style_create('s2') + t.style_elements(s, ['e5', 'e2', 'e3']) + t.style_layout(s, 'e2', :padx=>[0,4], :expand=>:ns) + t.style_layout(s, 'e3', :padx=>[0,4], :expand=>:ns) + t.style_layout(s, 'e5', :union=>['e3'], :iexpand=>:ns, :ipadx=>2) + + s = t.style_create('s3') + t.style_elements(s, ['e6']) + t.style_layout(s, 'e6', :padx=>6, :expand=>:ns) + + @Priv[:sensitive, t] = [ + [:item, 's1', 'e5', 'e1', 'e3'], + [:item, 's2', 'e5', 'e2', 'e3'] + ] + @Priv[:dragimage, t] = [ + [:item, 's1', 'e1', 'e3'], + [:item, 's2', 'e2', 'e3'] + ] + + clicks = Tk::Clock.clicks + items = [ t.index(:root) ] + (1...(random_N())).each{|i| + item_i = t.item_create + item_j = nil + loop { + j = rand(i) + item_j = items[j] + break if t.depth(item_j) < 5 + } + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_collapse(item_i) if rand(2) == 0 + else # TreeCtrl 1.0 + t.collapse(item_i) if rand(2) == 0 + end + if rand(2) == 0 + t.item_lastchild(item_j, item_i) + else + t.item_firstchild(item_j, item_i) + end + items << item_i + } + puts "created #{random_N() - 1} items in #{Tk::Clock.clicks - clicks} clicks" + + clicks = Tk::Clock.clicks + (0...(random_N())).each{|i| + item_i = items[i] + item_j = nil + numChildren = t.item_numchildren(item_i) + if numChildren > 0 + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_configure(item_i, :button=>true) + else # TreeCtrl 1.0 + t.item_hasbutton(item_i, true) + end + t.item_style_set(item_i, 0, 's1', 1, 's3', 2, 's3') + t.item_complex(item_i, + [ ['e3', {:text=>"Item #{i}"}], + ['e4', {:text=>"(#{numChildren})"}] ], + [ ['e6', {:text=>"#{t.item_parent(item_i)}"}] ], + [ ['e6', {:text=>"#{t.depth(item_i)}"}] ]) + else + t.item_style_set(item_i, 1, 's3', 2, 's3', 0, 's2') + t.item_complex(item_i, + [ ['e3', {:text=>"Item #{i}"}] ], + [ ['e6', {:text=>"#{t.item_parent(item_i)}"}] ], + [ ['e6', {:text=>"#{t.depth(item_i)}"}] ]) + end + } + puts "configured #{random_N()} items in #{Tk::Clock.clicks - clicks} clicks" + + treeCtrlRandom = TkBindTag.new + + treeCtrlRandom.bind('Double-ButtonPress-1', + proc{|w, x, y| + Tk::TreeCtrl::BindCallback.doubleButton1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlRandom.bind('Control-ButtonPress-1', + proc{|w, x, y| + @Priv['selectMode'] = :toggle + randomButton1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlRandom.bind('Shift-ButtonPress-1', + proc{|w, x, y| + @Priv['selectMode'] = :add + randomButton1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlRandom.bind('ButtonPress-1', + proc{|w, x, y| + @Priv['selectMode'] = :set + randomButton1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlRandom.bind('Button1-Motion', + proc{|w, x, y| + randomMotion1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlRandom.bind('Button1-Leave', + proc{|w, x, y| + randomLeave1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + treeCtrlRandom.bind('ButtonRelease-1', + proc{|w, x, y| + randomRelease1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + t.bindtags = [ t, treeCtrlRandom, Tk::TreeCtrl, t.winfo_toplevel, :all ] +end + +def randomButton1(t, x, y) + t.set_focus + id = t.identify(x, y) + puts id.inspect + @Priv['buttonMode'] = '' + if id.empty? + # Click outside any item + + elsif id[0] == 'header' + # Click in header + Tk::TreeCtrl::BindCallback.buttonPress1(w, x, y) + + else + # Click in item + where, item, arg1, arg2, arg3, arg4 = id + case arg1 + when 'button' + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_toggle(item) + else # TreeCtrl 1.0 + t.toggle(item) + end + + when 'line' + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_toggle(arg2) + else # TreeCtrl 1.0 + t.toggle(arg2) + end + + when 'column' + ok = false + # Clicked an element + if id.length == 6 + column = id[3] + e = id[5] + @Priv.list_element(:sensitive, t).each{|lst| + c, s, *eList = TkComm.simplelist(lst) + next if column != t.column_index(c) + next if t.item_style_set(item, c) != s + next if eList.find{|le| le == e} == nil + ok = true + break + } + end + unless ok + t.selection_clear + return + end + + @Priv[:drag, :motion] = 0 + @Priv[:drag, :x] = t.canvasx(x) + @Priv[:drag, :y] = t.canvasy(y) + @Priv[:drop] = '' + + if @Priv['selectMode'] == 'add' + Tk::TreeCtrl::BindCallback.beginExtend(t, item) + elsif @Priv['selectMode'] == 'toggle' + Tk::TreeCtrl::BindCallback.beginToggle(t, item) + elsif ! t.selection_includes(item) + Tk::TreeCtrl::BindCallback.beginSelect(t, item) + end + t.activate(item) + + if t.selection_includes(item) + @Priv['buttonMode'] = 'drag' + end + end + end +end + +def randomMotion1(t, x, y) + case @Priv['buttonMode'] + when 'resize', 'header' + Tk::TreeCtrl::BindCallback.motion1(t, x, y) + when 'drag' + randomAutoScanCheck(t, x, y) + randomMotion(t, x, y) + end +end + +def randomMotion(t, x, y) + case @Priv['buttonMode'] + when 'resize', 'header' + Tk::TreeCtrl::BindCallback.motion1(t, x, y) + + when 'drag' + # Detect initial mouse movement + unless @Priv.bool_element(:drag, :motion) + @Priv[:selection] = t.selection_get + @Priv[:drop] = '' + t.dragimage_clear + # For each selected item, add 2nd and 3rd elements of + # column "item" to the dragimage + @Priv.list_element(:selection).each{|i| + @Priv.list_element(:dragimage,t).each{|lst| + c, s, *eList = TkComm.simplelist(lst) + if t.item_style_set(i, c) == s + t.dragimage_add(i, c, *eList) + end + } + } + @Priv[:drag,:motion] = true + end + + # Find the item under the cursor + cursor = 'X_cursor' + drop = '' + id = t.identify(x, y) + ok = false + if !id.empty? && id[0] == 'item' && id.length == 6 + item = id[1] + column = id[3] + e = id[5] + @Priv.list_element(:sensitive,t).each{|lst| + c, s, *eList = TkComm.simplelist(lst) + next if column != t.column_index(c) + next if t.item_style_set(item, c) != s + next unless eList.find{|val| val == e} + ok = true + break + } + ok = true if @Priv.list_element(:sensitive,t).find{|val| TkComm.simplelist(val).index(e)} + end + + if ok + # If the item is not in the pre-drag selection + # (i.e. not being dragged) see if we can drop on it + unless @Priv.list_element(:selection).find{|val| val == item} + drop = item + # We can drop if dragged item isn't an ancestor + @Priv.list_element(:selection).each{|item2| + if t.item_isancestor(item2, item) + drop = '' + break + end + } + if drop != '' + x1, y1, x2, y2 = t.item_bbox(drop) + if y < y1 + 3 + cursor = 'top_side' + @Priv[:drop,:pos] = 'prevsibling' + elsif y >= y2 - 3 + cursor = 'bottom_side' + @Priv[:drop,:pos] = 'nextsibling' + else + cursor = '' + @Priv[:drop,:pos] = 'lastchild' + end + end + end + end + + t[:cursor] = cursor if t[:cursor] != cursor + + # Select the item under the cursor (if any) and deselect + # the previous drop-item (if any) + t.selection_modify(drop, @Priv[:drop]) + @Priv[:drop] = drop + + # Show the dragimage in its new position + x = t.canvasx(x) - @Priv.numeric_element(:drag,:x) + y = t.canvasx(y) - @Priv.numeric_element(:drag,:y) + t.dragimage_offset(x, y) + t.dragimage_configure(:visible=>true) + end +end + +def randomLeave1(t, x, y) + # This is called when I do ButtonPress-1 on Unix for some reason, + # and buttonMode is undefined. + return unless @Priv.exist?('buttonMode') + case @Priv['buttonMode'] + when 'header' + Tk::TreeCtrl::BindCallback.leave1(t, x, y) + end +end + +def randomRelease1(t, x, y) + case @Priv['buttonMode'] + when 'resize', 'header' + Tk::TreeCtrl::BindCallback.release1(t, x, y) + when 'drag' + Tk::TreeCtrl::BindCallback.autoScanCancel(t) + t.dragimage_configure(:visible=>false) + t.selection_modify('', @Priv[:drop]) + t[:cursor] = '' + if @Priv[:drop] != '' + randomDrop(t, @Priv[:drop], @Priv.list_element(:selection), + @Priv[:drop, :pos]) + end + end + @Priv['buttonMode'] = '' +end + +def randomDrop(t, target, src, pos) + parentList = [] + case pos + when 'lastchild' + parent = target + when 'prevsibling' + parent = t.item_parent(target) + when 'nextsibling' + parent = t.item_parent(target) + end + src.each{|item| + # Ignore any item whose ancestor is also selected + ignore = false + t.item_ancestors(item).each{|ancestor| + if src.find{|val| val == ancestor} + ignore = true + break + end + } + next if ignore + + # Update the old parent of this moved item later + unless parentList.find{|val| val == item} + parentList << t.item_parent(item) + end + + # Add to target + t.__send__("item_#{pos}", target, item) + + # Update text: parent + t.item_element_configure(item, 'parent', 'e6', :text=>parent) + + # Update text: depth + t.item_element_configure(item, 'depth', 'e6', :text=>t.depth(item)) + + # Recursively update text: depth + itemList = [ t.item_firstchild(item) ] + while itemList.length > 0 + item = itemList.pop + + t.item_element_configure(item, 'depth', 'e6', :text=>t.depth(item)) + + item2 = t.item_nextsibling(item) + itemList << item2 if item2 != '' + + item2 = t.item_firstchild(item) + itemList << item2 if item2 != '' + end + } + + # Update items that lost some children + parentList.each{|item| + numChildren = t.item_numchildren(item) + if numChildren == 0 + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_configure(item, :button=>false) + else # TreeCtrl 1.0 + t.item_hasbutton(item, false) + end + t.item_style_map(item, 'item', 's2', ['e3', 'e3']) + else + t.item_element_configure(item, 'item', 'e4', :text=>"(#{numChildren})") + end + } + + # Update the target that gained some children + if t.item_style_set(parent, 0) != 's1' + if (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0) + t.item_configure(parent, :button=>true) + else # TreeCtrl 1.0 + t.item_hasbutton(parent, true) + end + t.item_style_map(parent, 'item', 's1', ['e3', 'e3']) + end + numChildren = t.item_numchildren(parent) + t.item_element_configure(parent, 'item', 'e4', :text=>"(#{numChildren})") +end + +# Same as TreeCtrl::AutoScanCheck, but calls RandomMotion and +# RandomAutoScanCheckAux +def randomAutoScanCheck(t, x, y) + x1, y1, x2, y2 = t.contentbox + margin = t.winfo_pixels(t.scrollmargin) + if x < x1 + margin || x >= x2 - margin || y < y1 + margin || y >= y2 - margin + if ! @Priv.exist?(:auroscan, :afterID, t) + if y >= y2 - margin + t.yview(:scroll, 1, :units) + delay = t.yscrolldelay + elsif y < y1 + margin + t.yview(:scroll, -1, :units) + delay = t.yscrolldelay + elsif x >= x2 - margin + t.xview(:scroll, 1, :units) + delay = t.xscrolldelay + elsif x < x1 + margin + t.xview(:scroll, -1, :units) + delay = t.xscrolldelay + end + if @Priv.exist?(:autoscan, :scanning, t) + delay = delay[2] if delay.kind_of?(Array) + else + delay = delay[1] if delay.kind_of?(Array) + end + case @Priv['buttonMode'] + when 'drag', 'marquee' + randomMotion(t, x, y) + end + @Priv[:autoscan, :scanning, t] = + Tk.after(delay, proc{ randomAutoScanCheckAux(t) }) + end + return + end + Tk::TreeCtrl::BindCallback.autoScanCancel(t) +end + +def randomAutoScanCheckAux(t) + @Priv.unset(:autoscan, :afterID, t) + x = t.winfo_pointerx - t.winfo_rootx + y = t.winfo_pointery - t.winfo_rooty + randomAutoScanCheck(t, x, y) +end + +# +# Demo: random N items, button images +# +def demoRandom2(t) + demoRandom(t) + + init_pics('mac-*') + + t.configure(:openbuttonimage=>@images['mac-collapse'], + :closedbuttonimage=>@images['mac-expand'], + :showlines=>false) +end diff --git a/ext/tk/sample/tkextlib/treectrl/readme.txt b/ext/tk/sample/tkextlib/treectrl/readme.txt new file mode 100644 index 000000000..9f26ac069 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/readme.txt @@ -0,0 +1,2 @@ +The scripts and image files in this directory are based on demo files +of Tcl/Tk's TreeCtrl extention. diff --git a/ext/tk/sample/tkextlib/treectrl/www-options.rb b/ext/tk/sample/tkextlib/treectrl/www-options.rb new file mode 100644 index 000000000..2b0f75e85 --- /dev/null +++ b/ext/tk/sample/tkextlib/treectrl/www-options.rb @@ -0,0 +1,303 @@ +def demoInternetOptions (t) + @Option = TkVarAccess.new_hash('::Option') + + height = t.font.metrics(:linespace) + 2 + height = 18 if height < 18 + t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false, + :itemheight=>height, :selectmode=>:browse) + + init_pics('internet-*') + + if $HasColumnCreate + t.column_create(:text=>'Internet Options') + else + t.column_configure(0, :text=>'Internet Options') + end + + t.state_define('check') + t.state_define('radio') + t.state_define('on') + + t.element_create('e1', :image, :image=>[ + @images['internet-check-on'], ['check', 'on'], + @images['internet-check-off'], ['check'], + @images['internet-radio-on'], ['radio', 'on'], + @images['internet-radio-off'], ['radio'] + ]) + t.element_create('e2', :text, + :fill=>[@SystemHighlightText, ['selected', 'focus']]) + t.element_create('e3', :rect, :showfocus=>true, + :fill=>[@SystemHighlight, ['selected', 'focus']]) + + s = t.style_create('s1') + t.style_elements(s, ['e3', 'e1', 'e2']) + t.style_layout(s, 'e1', :padx=>[0,4], :expand=>:ns) + t.style_layout(s, 'e2', :expand=>:ns) + t.style_layout(s, 'e3', :union=>['e2'], :iexpand=>:ns, :ipadx=>2) + + parentList = [:root, '', '', '', '', '', ''] + parent = :root + [ + [0, :print, "Printing", "", ""], + [1, :off, "Print background colors and images", "o1", ""], + [0, :search, "Search from Address bar", "", ""], + [1, :search, "When searching", "", ""], + [2, :off, "Display results, and go to the most likely sites", + "o2", "r1"], + [2, :off, "Do not search from the Address bar", "o3", "r1"], + [2, :off, "Just display the results in the main window", + "o4", "r1"], + [2, :on, "Just go to the most likely site", "o5", "r1"], + [0, :security, "Security", "", ""], + [1, :on, "Check for publisher's certificate revocation", "o5", ""], + [1, :off, "Check for server certificate revocation (requires restart)", + "o6", ""] + ].each{|depth, setting, text, option, group| + item = t.item_create() + t.item_style_set(item, 0, 's1') + t.item_element_configure(item, 0, 'e2', :text=>text) + @Option[:option, item] = option + @Option[:group, item] = group + if setting == :on || setting == :off + @Option[:setting, item] = setting + if group == '' + t.item_state_set(item, 'check') + if setting == :on + t.item_state_set(item, 'on') + end + else + if setting == :on + @Option[:current, group] = item + t.item_state_set(item, 'on') + end + t.item_state_set(item, 'radio') + end + else + t.item_element_configure(item, 0, 'e1', + :image=>@images["internet-#{setting}"]) + end + t.item_lastchild(parentList[depth], item) + depth += 1 + parentList[depth] = item + } + + treeCtrlOption = TkBindTag.new + treeCtrlOption.bind('Double-ButtonPress-1', proc{|w, x, y| + Tk::TreeCtrl::BindCallback.doubleButton1(w, x, y) + }, '%W %x %y') + treeCtrlOption.bind('ButtonPress-1', proc{|w, x, y| + optionButton1(w, x, y) + Tk.callback_break + }, '%W %x %y') + treeCtrlOption.bind('Button1-Motion', proc{|w, x, y| + optionMotion1(w, x, y) + Tk.callback_break + }, '%W %x %y') + treeCtrlOption.bind('Button1-Leave', proc{|w, x, y| + optionLeave1(w, x, y) + Tk.callback_break + }, '%W %x %y') + treeCtrlOption.bind('ButtonRelease-1', proc{|w, x, y| + optionRelease1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + t.bindtags = [ + t, treeCtrlOption, Tk::TreeCtrl, t.winfo_toplevel, TkBindTag::ALL + ] +end + +def optionButton1(w, x, y) + w.set_focus + id = w.identify(x, y) + if id[0] == 'header' + Tk::TreeCtrl::BindCallback.buttonPress1(w, x, y) + elsif id.empty? + @Priv['buttonMode'] = '' + else + @Priv['buttonMode'] = '' + item = id[1] + w.selection_modify(item, :all) + w.activate(item) + return if @Option[:option, item] == '' + group = @Option[:group, item] + if group == '' + # a checkbutton + w.item_state_set(item, '~on') + if @Option[:setting, item] == 'on' + setting = :off + else + setting = :on + end + @Option[:setting, item] = setting + else + # a radiobutton + current = @Option[:current, group] + return if current == item.to_s + w.item_state_set(current, '!on') + w.item_state_set(item, 'on') + @Option[:setting, item] = :on + @Option[:current, group] = item + end + end +end + +# Alternate implementation that doesn't rely on run-time styles +def demoInternetOptions_2(t) + height = t.font.metrics(:linespace) + 2 + height = 18 if height < 18 + t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false, + :itemheight=>height, :selectmode=>:browse) + + init_pics('internet-*') + + t.column_configure(0, :text=>'Internet Options') + + t.element_create('e1', :image) + t.element_create('e2', :text, + :fill=>[@SystemHighlightText, ['selected', 'focus']]) + t.element_create('e3', :rect, :showfocus=>true, + :fill=>[@SystemHighlight, ['selected', 'focus']]) + + s = t.style_create('s1') + t.style_elements('s1', ['e3', 'e1', 'e2']) + t.style_layout(s, 'e1', :padx=>[0,4], :expand=>:ns) + t.style_layout(s, 'e2', :expand=>:ns) + t.style_layout(s, 'e3', :union=>['e2'], :iexpand=>:ns, :ipadx=>2) + + parentList = [:root, '', '', '', '', '', ''] + parent = :root + [ + [0, :print, "Printing", "", ""], + [1, :off, "Print background colors and images", "o1", ""], + [0, :search, "Search from Address bar", "", ""], + [1, :search, "When searching", "", ""], + [2, :off, "Display results, and go to the most likely sites", + "o2", "r1"], + [2, :off, "Do not search from the Address bar", "o3", "r1"], + [2, :off, "Just display the results in the main window", + "o4", "r1"], + [2, :on, "Just go to the most likely site", "o5", "r1"], + [0, :security, "Security", "", ""], + [1, :on, "Check for publisher's certificate revocation", "o5", ""], + [1, :off, "Check for server certificate revocation (requires restart)", + "o6", ""] + ].each{|depth, setting, text, option, group| + item = t.item_create() + t.item_style_set(item, 0, 's1') + t.item_element_configure(item, 0, 'e2', :text=>text) + @Option[:option, item] = option + @Option[:group, item] = group + if setting == :on || setting == :off + @Option[:setting, item] = setting + if group == '' + img = @images["internet-check-#{setting}"] + t.item_element_configure(item, 0, 'e1', :image=>img) + else + if setting == :on + @Option[:current, group] = item + end + img = @images["internet-radio-#{setting}"] + t.item_element_configure(item, 0, 'e1', :image=>img) + end + else + t.item_element_configure(item, 0, 'e1', + :image=>@images["internet-#{setting}"]) + end + t.item_lastchild(parentList[depth], item) + depth += 1 + parentList[depth] = item + } + + treeCtrlOption = TkBindTag.new + treeCtrlOption.bind('Double-ButtonPress-1', proc{|w, x, y| + Tk::TreeCtrl::BindCallback.doubleButton1(w, x, y) + }, '%W %x %y') + treeCtrlOption.bind('ButtonPress-1', proc{|w, x, y| + optionButton1(w, x, y) + Tk.callback_break + }, '%W %x %y') + treeCtrlOption.bind('Button1-Motion', proc{|w, x, y| + optionMotion1(w, x, y) + Tk.callback_break + }, '%W %x %y') + treeCtrlOption.bind('Button1-Leave', proc{|w, x, y| + optionLeave1(w, x, y) + Tk.callback_break + }, '%W %x %y') + treeCtrlOption.bind('ButtonRelease-1', proc{|w, x, y| + optionRelease1(w, x, y) + Tk.callback_break + }, '%W %x %y') + + t.bindtags = [ + t, treeCtrlOption, Tk::TreeCtrl, t.winfo_toplevel, TkBindTag::ALL + ] +end + +def optionButton1_2(w, x, y) + w.set_focus + id = w.identify(x, y) + if id[0] == 'header' + Tk::TreeCtrl::BindCallback.buttonPress1(w, x, y) + elsif id.empty? + @Priv['buttonMode'] = '' + else + @Priv['buttonMode'] = '' + item = id[1] + w.selection_modify(item, :all) + w.activate(item) + return if @Option[:option, item] == '' + group = @Option[:group, item] + if group == '' + # a checkbutton + if @Option[:setting, item] == 'on' + setting = :off + else + setting = :on + end + w.item_element_configure(item, 0, 'e1', + :image=>@images["internet-check-#{setting}"]) + @Option[:setting, item] = setting + else + # a radiobutton + current = @Option[:current, group] + return if current == item.to_s + w.item_element_configure(current, 0, 'e1', + :image=>@images["internet-radio-off"]) + w.item_element_configure(item, 0, 'e1', + :image=>@images["internet-radio-on"]) + @Option[:setting, item] = :on + @Option[:current, group] = item + end + end +end + +def optionMotion1(w, x, y) + case @Priv['buttonMode'] + when 'resize', 'header' + Tk::TreeCtrl::BindCallback.Motion1(w, x, y) + end +end + +def optionLeave1(w, x, y) + # This is called when I do ButtonPress-1 on Unix for some reason, + # and buttonMode is undefined. + begin + mode = @Priv['buttonMode'] + rescue + else + case mode + when 'header' + t.column_configure(@Priv['column'], :sunken=>false) + end + end +end + +def optionRelease1(w, x, y) + case @Priv['buttonMode'] + when 'resize', 'header' + Tk::TreeCtrl::BindCallback.Release1(w, x, y) + end + @Priv['buttonMode'] = '' +end |