OSDN Git Service

566e48def3cfeaee2cb1b1c1c87bce98d4db76f3
[splhack/AndroidRuby.git] / lib / ruby-1.9.1-rc1 / ext / tk / lib / tkextlib / tile / treeview.rb
1 #
2 #  treeview widget
3 #                               by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
4 #
5 require 'tk'
6 require 'tkextlib/tile.rb'
7
8 module Tk
9   module Tile
10     class Treeview < TkWindow
11     end
12   end
13 end
14
15 Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Treeview, :TkTreeview)
16
17
18 module Tk::Tile::TreeviewConfig
19   include TkItemConfigMethod
20
21   def __item_configinfo_struct(id)
22     # maybe need to override
23     {:key=>0, :alias=>nil, :db_name=>nil, :db_class=>nil, 
24       :default_value=>nil, :current_value=>1}
25   end
26   private :__item_configinfo_struct
27
28   def __itemconfiginfo_core(tagOrId, slot = nil)
29     if TkComm::GET_CONFIGINFO_AS_ARRAY
30       if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
31         fontkey  = $2
32         return [slot.to_s, tagfontobj(tagid(tagOrId), fontkey)]
33       else
34         if slot
35           slot = slot.to_s
36
37           alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot}
38           if real_name
39             slot = real_name.to_s
40           end
41
42           case slot
43           when /^(#{__tile_specific_item_optkeys(tagid(tagOrId)).join('|')})$/
44             begin
45               # On tile-0.7.{2-8}, 'state' options has no '-' at its head.
46               val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << slot))
47             rescue
48               # Maybe, 'state' option has '-' in future.
49               val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
50             end
51             return [slot, val]
52
53           when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
54             method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot]
55             optval = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
56             begin
57               val = method.call(tagOrId, optval)
58             rescue => e
59               warn("Warning:: #{e.message} (when #{method}lcall(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
60               val = optval
61             end
62             return [slot, val]
63
64           when /^(#{__item_methodcall_optkeys(tagid(tagOrId)).keys.join('|')})$/
65             method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot]
66             return [slot, self.__send__(method, tagOrId)]
67
68           when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
69             begin
70               val = number(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
71             rescue
72               val = nil
73             end
74             return [slot, val]
75
76           when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
77             val = num_or_str(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
78             return [slot, val]
79
80           when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
81             begin
82               val = bool(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
83             rescue
84               val = nil
85             end
86             return [slot, val]
87
88           when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
89             val = simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
90             return [slot, val]
91
92           when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
93             val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
94             if val =~ /^[0-9]/
95               return [slot, list(val)]
96             else
97               return [slot, val]
98             end
99
100           when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
101             val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
102             return [slot, val]
103
104           when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
105             val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
106             if val.empty?
107               return [slot, nil]
108             else
109               return [slot, TkVarAccess.new(val)]
110             end
111
112           else
113             val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
114             if val.index('{')
115               return [slot, tk_split_list(val)]
116             else
117               return [slot, tk_tcl2ruby(val)]
118             end
119           end
120
121         else # ! slot
122           ret = Hash[*(tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false))].to_a.collect{|conf|
123             conf[0] = conf[0][1..-1] if conf[0][0] == ?-
124             case conf[0]
125             when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
126               method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[conf[0]]
127               optval = conf[1]
128               begin
129                 val = method.call(tagOrId, optval)
130               rescue => e
131                 warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
132                 val = optval
133               end
134               conf[1] = val
135
136             when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
137               # do nothing
138
139             when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
140               begin
141                 conf[1] = number(conf[1])
142               rescue
143                 conf[1] = nil
144               end
145
146             when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
147               conf[1] = num_or_str(conf[1])
148
149             when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
150               begin
151                 conf[1] = bool(conf[1])
152               rescue
153                 conf[1] = nil
154               end
155
156             when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
157               conf[1] = simplelist(conf[1])
158
159             when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
160               if conf[1] =~ /^[0-9]/
161                 conf[1] = list(conf[1])
162               end
163
164             when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
165               if conf[1].empty?
166                 conf[1] = nil
167               else
168                 conf[1] = TkVarAccess.new(conf[1])
169               end
170
171             else
172               if conf[1].index('{')
173                 conf[1] = tk_split_list(conf[1])
174               else
175                 conf[1] = tk_tcl2ruby(conf[1])
176               end
177             end
178
179             conf
180           }
181
182           __item_font_optkeys(tagid(tagOrId)).each{|optkey|
183             optkey = optkey.to_s
184             fontconf = ret.assoc(optkey)
185             if fontconf
186               ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/}
187               fontconf[1] = tagfontobj(tagid(tagOrId), optkey)
188               ret.push(fontconf)
189             end
190           }
191
192           __item_methodcall_optkeys(tagid(tagOrId)).each{|optkey, method|
193             ret << [optkey.to_s, self.__send__(method, tagOrId)]
194           }
195
196           ret
197         end
198       end
199
200     else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
201       if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
202         fontkey  = $2
203         return {slot.to_s => tagfontobj(tagid(tagOrId), fontkey)}
204       else
205         if slot
206           slot = slot.to_s
207
208           alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot}
209           if real_name
210             slot = real_name.to_s
211           end
212
213           case slot
214           when /^(#{__tile_specific_item_optkeys(tagid(tagOrId)).join('|')})$/
215             begin
216               # On tile-0.7.{2-8}, 'state' option has no '-' at its head.
217               val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << slot))
218             rescue
219               # Maybe, 'state' option has '-' in future.
220               val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
221             end
222             return {slot => val}
223
224           when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
225             method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot]
226             optval = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
227             begin
228               val = method.call(tagOrId, optval)
229             rescue => e
230               warn("Warning:: #{e.message} (when #{method}lcall(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
231               val = optval
232             end
233             return {slot => val}
234
235           when /^(#{__item_methodcall_optkeys(tagid(tagOrId)).keys.join('|')})$/
236             method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot]
237             return {slot => self.__send__(method, tagOrId)}
238
239           when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
240             begin
241               val = number(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
242             rescue
243               val = nil
244             end
245             return {slot => val}
246
247           when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
248             val = num_or_str(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
249             return {slot => val}
250
251           when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
252             begin
253               val = bool(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
254             rescue
255               val = nil
256             end
257             return {slot => val}
258
259           when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
260             val = simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
261             return {slot => val}
262
263           when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
264             val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
265             if val =~ /^[0-9]/
266               return {slot => list(val)}
267             else
268               return {slot => val}
269             end
270
271           when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
272             val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
273             return {slot => val}
274
275           when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
276             val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
277             if val.empty?
278               return {slot => nil}
279             else
280               return {slot => TkVarAccess.new(val)}
281             end
282
283           else
284             val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
285             if val.index('{')
286               return {slot => tk_split_list(val)}
287             else
288               return {slot => tk_tcl2ruby(val)}
289             end
290           end
291
292         else # ! slot
293           ret = {}
294           ret = Hash[*(tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false))].to_a.collect{|conf|
295             conf[0] = conf[0][1..-1] if conf[0][0] == ?-
296
297             optkey = conf[0]
298             case optkey
299             when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
300               method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[optkey]
301               optval = conf[1]
302               begin
303                 val = method.call(tagOrId, optval)
304               rescue => e
305                 warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
306                 val = optval
307               end
308               conf[1] = val
309
310             when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
311               # do nothing
312
313             when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
314               begin
315                 conf[1] = number(conf[1])
316               rescue
317                 conf[1] = nil
318               end
319
320             when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
321               conf[1] = num_or_str(conf[1])
322
323             when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
324               begin
325                 conf[1] = bool(conf[1])
326               rescue
327                 conf[1] = nil
328               end
329
330             when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
331               conf[1] = simplelist(conf[1])
332
333             when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
334               if conf[1] =~ /^[0-9]/
335                 conf[1] = list(conf[1])
336               end
337
338             when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
339               if conf[1].empty?
340                 conf[1] = nil
341               else
342                 conf[1] = TkVarAccess.new(conf[1])
343               end
344
345             else
346               if conf[1].index('{')
347                 return [slot, tk_split_list(conf[1])]
348               else
349                 return [slot, tk_tcl2ruby(conf[1])]
350               end
351             end
352
353             ret[conf[0]] = conf[1]
354           }
355
356           __item_font_optkeys(tagid(tagOrId)).each{|optkey|
357             optkey = optkey.to_s
358             fontconf = ret[optkey]
359             if fontconf.kind_of?(Array)
360               ret.delete(optkey)
361               ret.delete('latin' << optkey)
362               ret.delete('ascii' << optkey)
363               ret.delete('kanji' << optkey)
364               fontconf[1] = tagfontobj(tagid(tagOrId), optkey)
365               ret[optkey] = fontconf
366             end
367           }
368
369           __item_methodcall_optkeys(tagid(tagOrId)).each{|optkey, method|
370             ret[optkey.to_s] = self.__send__(method, tagOrId)
371           }
372
373           ret
374         end
375       end
376     end
377   end
378
379   ###################
380
381   def __item_cget_cmd(id)
382     [self.path, *id]
383   end
384   private :__item_cget_cmd
385
386   def __item_config_cmd(id)
387     [self.path, *id]
388   end
389   private :__item_config_cmd
390
391   def __item_numstrval_optkeys(id)
392     case id[0]
393     when :item, 'item'
394       ['width']
395     when :column, 'column'
396       super(id[1]) + ['minwidth']
397     when :tag, 'tag'
398       super(id[1])
399     when :heading, 'heading'
400       super(id[1])
401     else
402       super(id[1])
403     end
404   end
405   private :__item_numstrval_optkeys
406
407   def __item_strval_optkeys(id)
408     case id[0]
409     when :item, 'item'
410       super(id) + ['id']
411     when :column, 'column'
412       super(id[1])
413     when :tag, 'tag'
414       super(id[1])
415     when :heading, 'heading'
416       super(id[1])
417     else
418       super(id[1])
419     end
420   end
421   private :__item_strval_optkeys
422
423   def __item_boolval_optkeys(id)
424     case id[0]
425     when :item, 'item'
426       ['open']
427     when :column, 'column'
428       super(id[1]) + ['stretch']
429     when :tag, 'tag'
430       super(id[1])
431     when :heading, 'heading'
432       super(id[1])
433     end
434   end
435   private :__item_boolval_optkeys
436
437   def __item_listval_optkeys(id)
438     case id[0]
439     when :item, 'item'
440       ['values']
441     when :column, 'column'
442       []
443     when :heading, 'heading'
444       []
445     else
446       []
447     end
448   end
449   private :__item_listval_optkeys
450
451   def __item_val2ruby_optkeys(id)
452     case id[0]
453     when :item, 'item'
454       { 
455         'tags'=>proc{|arg_id, val|
456           simplelist(val).collect{|tag|
457             Tk::Tile::Treeview::Tag.id2obj(self, tag)
458           }
459         }
460       }
461     when :column, 'column'
462       {}
463     when :heading, 'heading'
464       {}
465     else
466       {}
467     end
468   end
469   private :__item_val2ruby_optkeys
470
471   def __tile_specific_item_optkeys(id)
472     case id[0]
473     when :item, 'item'
474       []
475     when :column, 'column'
476       []
477     when :heading, 'heading'
478       ['state']  # On tile-0.7.{2-8}, 'state' options has no '-' at its head.
479     else
480       []
481     end
482   end
483   private :__item_val2ruby_optkeys
484
485   def itemconfiginfo(tagOrId, slot = nil)
486     __itemconfiginfo_core(tagOrId, slot)
487   end
488
489   def current_itemconfiginfo(tagOrId, slot = nil)
490     if TkComm::GET_CONFIGINFO_AS_ARRAY
491       if slot
492         org_slot = slot
493         begin
494           conf = __itemconfiginfo_core(tagOrId, slot)
495           if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
496               || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
497             return {conf[0] => conf[-1]}
498           end
499           slot = conf[__item_configinfo_struct(tagid(tagOrId))[:alias]]
500         end while(org_slot != slot)
501         fail RuntimeError, 
502           "there is a configure alias loop about '#{org_slot}'"
503       else
504         ret = {}
505         __itemconfiginfo_core(tagOrId).each{|conf|
506           if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
507               || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
508             ret[conf[0]] = conf[-1]
509           end
510         }
511         ret
512       end
513     else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
514       ret = {}
515       __itemconfiginfo_core(tagOrId, slot).each{|key, conf|
516         ret[key] = conf[-1] if conf.kind_of?(Array)
517       }
518       ret
519     end
520   end
521
522   alias __itemcget itemcget
523   alias __itemcget_strict itemcget_strict
524   alias __itemconfigure itemconfigure
525   alias __itemconfiginfo itemconfiginfo
526   alias __current_itemconfiginfo current_itemconfiginfo
527
528   private :__itemcget, :__itemcget_strict
529   private :__itemconfigure, :__itemconfiginfo, :__current_itemconfiginfo
530
531   # Treeview Item
532   def itemcget(tagOrId, option)
533     __itemcget([:item, tagOrId], option)
534   end
535   def itemcget_strict(tagOrId, option)
536     __itemcget_strict([:item, tagOrId], option)
537   end
538   def itemconfigure(tagOrId, slot, value=None)
539     __itemconfigure([:item, tagOrId], slot, value)
540   end
541   def itemconfiginfo(tagOrId, slot=nil)
542     __itemconfiginfo([:item, tagOrId], slot)
543   end
544   def current_itemconfiginfo(tagOrId, slot=nil)
545     __current_itemconfiginfo([:item, tagOrId], slot)
546   end
547
548   # Treeview Column
549   def columncget(tagOrId, option)
550     __itemcget([:column, tagOrId], option)
551   end
552   def columncget_strict(tagOrId, option)
553     __itemcget_strict([:column, tagOrId], option)
554   end
555   def columnconfigure(tagOrId, slot, value=None)
556     __itemconfigure([:column, tagOrId], slot, value)
557   end
558   def columnconfiginfo(tagOrId, slot=nil)
559     __itemconfiginfo([:column, tagOrId], slot)
560   end
561   def current_columnconfiginfo(tagOrId, slot=nil)
562     __current_itemconfiginfo([:column, tagOrId], slot)
563   end
564   alias column_cget columncget
565   alias column_cget_strict columncget_strict
566   alias column_configure columnconfigure
567   alias column_configinfo columnconfiginfo
568   alias current_column_configinfo current_columnconfiginfo
569
570   # Treeview Heading
571   def headingcget_strict(tagOrId, option)
572     if __tile_specific_item_optkeys([:heading, tagOrId]).index(option.to_s)
573       begin
574         # On tile-0.7.{2-8}, 'state' options has no '-' at its head.
575         tk_call(*(__item_cget_cmd([:heading, tagOrId]) << option.to_s))
576       rescue
577         # Maybe, 'state' option has '-' in future.
578         tk_call(*(__item_cget_cmd([:heading, tagOrId]) << "-#{option}"))
579       end
580     else
581       __itemcget_strict([:heading, tagOrId], option)
582     end
583   end
584   def headingcget(tagOrId, option)
585     unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
586       headingcget_strict(tagOrId, option)
587     else
588       begin
589         headingcget_strict(tagOrId, option)
590       rescue => e
591         begin
592           if current_headingconfiginfo(tagOrId).has_key?(option.to_s)
593             # not tag error & option is known -> error on known option
594             fail e
595           else
596             # not tag error & option is unknown
597             nil
598           end
599         rescue
600           fail e  # tag error
601         end
602       end
603     end
604   end
605   def headingconfigure(tagOrId, slot, value=None)
606     if slot.kind_of?(Hash)
607       slot = _symbolkey2str(slot)
608       sp_kv = []
609       __tile_specific_item_optkeys([:heading, tagOrId]).each{|k|
610         sp_kv << k << _get_eval_string(slot.delete(k)) if slot.has_key?(k)
611       }
612       tk_call(*(__item_config_cmd([:heading, tagOrId]).concat(sp_kv)))
613       tk_call(*(__item_config_cmd([:heading, tagOrId]).concat(hash_kv(slot))))
614     elsif __tile_specific_item_optkeys([:heading, tagOrId]).index(slot.to_s)
615       begin
616         # On tile-0.7.{2-8}, 'state' options has no '-' at its head.
617         tk_call(*(__item_cget_cmd([:heading, tagOrId]) << slot.to_s << value))
618       rescue
619         # Maybe, 'state' option has '-' in future.
620         tk_call(*(__item_cget_cmd([:heading, tagOrId]) << "-#{slot}" << value))
621       end
622     else
623       __itemconfigure([:heading, tagOrId], slot, value)
624     end
625     self
626   end
627   def headingconfiginfo(tagOrId, slot=nil)
628     __itemconfiginfo([:heading, tagOrId], slot)
629   end
630   def current_headingconfiginfo(tagOrId, slot=nil)
631     __current_itemconfiginfo([:heading, tagOrId], slot)
632   end
633   alias heading_cget headingcget
634   alias heading_cget_strict headingcget_strict
635   alias heading_configure headingconfigure
636   alias heading_configinfo headingconfiginfo
637   alias current_heading_configinfo current_headingconfiginfo
638
639   # Treeview Tag
640   def tagcget(tagOrId, option)
641     __itemcget([:tag, :configure, tagOrId], option)
642   end
643   def tagcget_strict(tagOrId, option)
644     __itemcget_strict([:tag, :configure, tagOrId], option)
645   end
646   def tagconfigure(tagOrId, slot, value=None)
647     __itemconfigure([:tag, :configure, tagOrId], slot, value)
648   end
649   def tagconfiginfo(tagOrId, slot=nil)
650     __itemconfiginfo([:tag, :configure, tagOrId], slot)
651   end
652   def current_tagconfiginfo(tagOrId, slot=nil)
653     __current_itemconfiginfo([:tag, :configure, tagOrId], slot)
654   end
655   alias tag_cget tagcget
656   alias tag_cget_strict tagcget_strict
657   alias tag_configure tagconfigure
658   alias tag_configinfo tagconfiginfo
659   alias current_tag_configinfo current_tagconfiginfo
660 end
661
662 ########################
663
664 class Tk::Tile::Treeview::Item < TkObject
665   ItemID_TBL = TkCore::INTERP.create_table
666
667   TkCore::INTERP.init_ip_env{
668     Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
669       Tk::Tile::Treeview::Item::ItemID_TBL.clear
670     }
671   }
672
673   def self.id2obj(tree, id)
674     tpath = tree.path
675     Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
676       if Tk::Tile::Treeview::Item::ItemID_TBL[tpath]
677         (Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id])? \
678              Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]: id
679       else
680         id
681       end
682     }
683   end
684
685   def self.assign(tree, id)
686     tpath = tree.path
687     obj = nil
688     Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
689       if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] &&
690           Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]
691         return Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]
692       end
693
694       obj = self.allocate
695       obj.instance_eval{
696         @parent = @t = tree
697         @tpath = tpath
698         @path = @id = id
699       }
700       Tk::Tile::Treeview::Item::ItemID_TBL[tpath] ||= {}
701       Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id] = obj
702     }
703     obj
704   end
705
706   def _insert_item(tree, parent_item, idx, keys={})
707     keys = _symbolkey2str(keys)
708     id = keys.delete('id')
709     if id
710       num_or_str(tk_call(tree, 'insert', 
711                          parent_item, idx, '-id', id, *hash_kv(keys)))
712     else
713       num_or_str(tk_call(tree, 'insert', parent_item, idx, *hash_kv(keys)))
714     end
715   end
716   private :_insert_item
717
718   def initialize(tree, parent_item = '', idx = 'end', keys = {})
719     if parent_item.kind_of?(Hash)
720       keys = parent_item
721       idx = 'end'
722       parent_item = ''
723     elsif idx.kind_of?(Hash)
724       keys = idx
725       idx = 'end'
726     end
727
728     @parent = @t = tree
729     @tpath = tree.path
730     @path = @id = _insert_item(@t, parent_item, idx, keys)
731     Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
732       ItemID_TBL[@tpath] = {} unless ItemID_TBL[@tpath]
733       ItemID_TBL[@tpath][@id] = self
734     }
735   end
736   def id
737     @id
738   end
739
740   def cget(option)
741     @t.itemcget(@id, option)
742   end
743   def cget_strict(option)
744     @t.itemcget_strict(@id, option)
745   end
746
747   def configure(key, value=None)
748     @t.itemconfigure(@id, key, value)
749     self
750   end
751
752   def configinfo(key=nil)
753     @t.itemconfiginfo(@id, key)
754   end
755
756   def current_configinfo(key=nil)
757     @t.current_itemconfiginfo(@id, key)
758   end
759
760   def open?
761     cget('open')
762   end
763   def open
764     configure('open', true)
765     self
766   end
767   def close
768     configure('open', false)
769     self
770   end
771
772   def bbox(column=None)
773     @t.bbox(@id, column)
774   end
775
776   def children
777     @t.children(@id)
778   end
779   def set_children(*items)
780     @t.set_children(@id, *items)
781     self
782   end
783
784   def delete
785     @t.delete(@id)
786     self
787   end
788
789   def detach
790     @t.detach(@id)
791     self
792   end
793
794   def exist?
795     @t.exist?(@id)
796   end
797
798   def focus
799     @t.focus_item(@id)
800   end
801
802   def index
803     @t.index(@id)
804   end
805
806   def insert(idx='end', keys={})
807     @t.insert(@id, idx, keys)
808   end
809
810   def move(parent, idx)
811     @t.move(@id, parent, idx)
812     self
813   end
814
815   def next_item
816     @t.next_item(@id)
817   end
818
819   def parent_item
820     @t.parent_item(@id)
821   end
822
823   def prev_item
824     @t.prev_item(@id)
825   end
826
827   def see
828     @t.see(@id)
829     self
830   end
831
832   def selection_add
833     @t.selection_add(@id)
834     self
835   end
836
837   def selection_remove
838     @t.selection_remove(@id)
839     self
840   end
841
842   def selection_set
843     @t.selection_set(@id)
844     self
845   end
846
847   def selection_toggle
848     @t.selection_toggle(@id)
849     self
850   end
851
852   def get_directory
853     @t.get_directory(@id)
854   end
855   alias get_dictionary get_directory
856
857   def get(col)
858     @t.get(@id, col)
859   end
860
861   def set(col, value)
862     @t.set(@id, col, value)
863   end
864 end
865
866 ########################
867
868 class Tk::Tile::Treeview::Root < Tk::Tile::Treeview::Item
869   def self.new(tree, keys = {})
870     tpath = tree.path
871     obj = nil
872     Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
873       if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] &&
874           Tk::Tile::Treeview::Item::ItemID_TBL[tpath]['']
875         obj = Tk::Tile::Treeview::Item::ItemID_TBL[tpath]['']
876       else
877         #super(tree, keys)
878         (obj = self.allocate).instance_eval{
879           @parent = @t = tree
880           @tpath = tree.path
881           @path = @id = ''
882           Tk::Tile::Treeview::Item::ItemID_TBL[@tpath] ||= {}
883           Tk::Tile::Treeview::Item::ItemID_TBL[@tpath][@id] = self
884         }
885       end
886     }
887     obj.configure(keys) if keys && ! keys.empty?
888     obj
889   end
890
891   def initialize(tree, keys = {})
892     # dummy:: not called by 'new' method
893     @parent = @t = tree
894     @tpath = tree.path
895     @path = @id = ''
896     Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
897       Tk::Tile::Treeview::Item::ItemID_TBL[@tpath] ||= {}
898       Tk::Tile::Treeview::Item::ItemID_TBL[@tpath][@id] = self
899     }
900   end
901 end
902
903 ########################
904
905 class Tk::Tile::Treeview::Tag < TkObject
906   include TkTreatTagFont
907
908   TagID_TBL = TkCore::INTERP.create_table
909
910   (Tag_ID = ['tile_treeview_tag'.freeze, '00000'.taint]).instance_eval{
911     @mutex = Mutex.new
912     def mutex; @mutex; end
913     freeze
914   }
915
916   TkCore::INTERP.init_ip_env{
917     Tk::Tile::Treeview::Tag::TagID_TBL.mutex.synchronize{
918       Tk::Tile::Treeview::Tag::TagID_TBL.clear
919     }
920   }
921
922   def self.id2obj(tree, id)
923     tpath = tree.path
924     Tk::Tile::Treeview::Tag::TagID_TBL.mutex.synchronize{
925       if Tk::Tile::Treeview::Tag::TagID_TBL[tpath]
926         (Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id])? \
927                Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id]: id
928       else
929         id
930       end
931     }
932   end
933
934   def initialize(tree, keys=nil)
935     @parent = @t = tree
936     @tpath = tree.path
937     Tag_ID.mutex.synchronize{
938       @path = @id = Tag_ID.join(TkCore::INTERP._ip_id_)
939       Tag_ID[1].succ!
940     }
941     TagID_TBL.mutex.synchronize{
942       TagID_TBL[@tpath] = {} unless TagID_TBL[@tpath]
943       TagID_TBL[@tpath][@id] = self
944     }
945     if keys && keys != None
946       tk_call_without_enc(@tpath, 'tag', 'configure', @id, *hash_kv(keys,true))
947     end
948   end
949   def id
950     @id
951   end
952
953   def bind(seq, *args)
954     if TkComm._callback_entry?(args[0]) || !block_given?
955       cmd = args.shift
956     else
957       cmd = Proc.new
958     end
959     @t.tag_bind(@id, seq, cmd, *args)
960     self
961   end
962
963   def bind_append(seq, *args)
964     if TkComm._callback_entry?(args[0]) || !block_given?
965       cmd = args.shift
966     else
967       cmd = Proc.new
968     end
969     @t.tag_bind_append(@id, seq, cmd, *args)
970     self
971   end
972
973   def bind_remove(seq)
974     @t.tag_bind_remove(@id, seq)
975     self
976   end
977
978   def bindinfo(seq=nil)
979     @t.tag_bindinfo(@id, seq)
980   end
981
982   def cget(option)
983     @t.tagcget(@id, option)
984   end
985   def cget_strict(option)
986     @t.tagcget_strict(@id, option)
987   end
988
989   def configure(key, value=None)
990     @t.tagconfigure(@id, key, value)
991     self
992   end
993
994   def configinfo(key=nil)
995     @t.tagconfiginfo(@id, key)
996   end
997
998   def current_configinfo(key=nil)
999     @t.current_tagconfiginfo(@id, key)
1000   end
1001 end
1002
1003 ########################
1004
1005 class Tk::Tile::Treeview < TkWindow
1006   include Tk::Tile::TileWidget
1007   include Scrollable
1008
1009   include Tk::Tile::TreeviewConfig
1010
1011   if Tk::Tile::USE_TTK_NAMESPACE
1012     TkCommandNames = ['::ttk::treeview'.freeze].freeze
1013   else
1014     TkCommandNames = ['::treeview'.freeze].freeze
1015   end
1016   WidgetClassName = 'Treeview'.freeze
1017   WidgetClassNames[WidgetClassName] = self
1018
1019   def __destroy_hook__
1020     Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
1021       Tk::Tile::Treeview::Item::ItemID_TBL.delete(@path)
1022     }
1023     Tk::Tile::Treeview::Tag::ItemID_TBL.mutex.synchronize{
1024       Tk::Tile::Treeview::Tag::ItemID_TBL.delete(@path)
1025     }
1026   end
1027
1028   def self.style(*args)
1029     [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
1030   end
1031
1032   def tagid(id)
1033     if id.kind_of?(Tk::Tile::Treeview::Item) || 
1034         id.kind_of?(Tk::Tile::Treeview::Tag)
1035       id.id
1036     elsif id.kind_of?(Array)
1037       # size is 2 or 3
1038       id[0..-2] << _get_eval_string(id[-1])
1039     else
1040       _get_eval_string(id)
1041     end
1042   end
1043
1044   def root
1045     Tk::Tile::Treeview::Root.new(self)
1046   end
1047
1048   def bbox(item, column=None)
1049     list(tk_send('item', 'bbox', item, column))
1050   end
1051
1052   def children(item)
1053     simplelist(tk_send_without_enc('children', item)).collect{|id|
1054       Tk::Tile::Treeview::Item.id2obj(self, id)
1055     }
1056   end
1057   def set_children(item, *items)
1058     tk_send_without_enc('children', item, 
1059                         array2tk_list(items.flatten, true))
1060     self
1061   end
1062
1063   def delete(*items)
1064     tk_send_without_enc('delete', array2tk_list(items.flatten, true))
1065     self
1066   end
1067
1068   def detach(*items)
1069     tk_send_without_enc('detach', array2tk_list(items.flatten, true))
1070     self
1071   end
1072
1073   def exist?(item)
1074     bool(tk_send_without_enc('exists', _get_eval_enc_str(item)))
1075   end
1076
1077   def focus_item(item = nil)
1078     if item
1079       tk_send('focus', item)
1080       item
1081     else
1082       id = tk_send('focus')
1083       (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id)
1084     end
1085   end
1086
1087   def identify(x, y)
1088     # tile-0.7.2 or previous
1089     ret = simplelist(tk_send('identify', x, y))
1090     case ret[0]
1091     when 'heading', 'separator'
1092       ret[-1] = num_or_str(ret[-1])
1093     when 'cell'
1094       ret[1] = Tk::Tile::Treeview::Item.id2obj(self, ret[1])
1095       ret[-1] = num_or_str(ret[-1])
1096     when 'item', 'row'
1097       ret[1] = Tk::Tile::Treeview::Item.id2obj(self, ret[1])
1098     end
1099   end
1100
1101   def row_identify(x, y)
1102     id = tk_send('identify', 'row', x, y)
1103     (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id)
1104   end
1105
1106   def column_identify(x, y)
1107     tk_send('identify', 'column', x, y)
1108   end
1109
1110   def index(item)
1111     number(tk_send('index', item))
1112   end
1113
1114   # def insert(parent, idx='end', keys={})
1115   #   keys = _symbolkey2str(keys)
1116   #   id = keys.delete('id')
1117   #   if id
1118   #     num_or_str(tk_send('insert', parent, idx, '-id', id, *hash_kv(keys)))
1119   #   else
1120   #     num_or_str(tk_send('insert', parent, idx, *hash_kv(keys)))
1121   #   end
1122   # end
1123   def insert(parent, idx='end', keys={})
1124     Tk::Tile::Treeview::Item.new(self, parent, idx, keys)
1125   end
1126
1127   # def instate(spec, cmd=Proc.new)
1128   #   tk_send('instate', spec, cmd)
1129   # end
1130   # def state(spec=None)
1131   #   tk_send('state', spec)
1132   # end
1133
1134   def move(item, parent, idx)
1135     tk_send('move', item, parent, idx)
1136     self
1137   end
1138
1139   def next_item(item)
1140     id = tk_send('next', item)
1141     (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id)
1142   end
1143
1144   def parent_item(item)
1145     if (id = tk_send('parent', item)).empty?
1146       Tk::Tile::Treeview::Root.new(self)
1147     else
1148       Tk::Tile::Treeview::Item.id2obj(self, id)
1149     end
1150   end
1151
1152   def prev_item(item)
1153     id = tk_send('prev', item)
1154     (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id)
1155   end
1156
1157   def see(item)
1158     tk_send('see', item)
1159     self
1160   end
1161
1162   def selection
1163     simplelist(tk_send('selection')).collect{|id|
1164       Tk::Tile::Treeview::Item.id2obj(self, id)
1165     }
1166   end
1167   alias selection_get selection
1168
1169   def selection_add(*items)
1170     tk_send('selection', 'add', array2tk_list(items.flatten, true))
1171     self
1172   end
1173   def selection_remove(*items)
1174     tk_send('selection', 'remove', array2tk_list(items.flatten, true))
1175     self
1176   end
1177   def selection_set(*items)
1178     tk_send('selection', 'set', array2tk_list(items.flatten, true))
1179     self
1180   end
1181   def selection_toggle(*items)
1182     tk_send('selection', 'toggle', array2tk_list(items.flatten, true))
1183     self
1184   end
1185
1186   def get_directory(item)
1187     # tile-0.7+
1188     ret = []
1189     lst = simplelist(tk_send('set', item))
1190     until lst.empty?
1191       col = lst.shift
1192       val = lst.shift
1193       ret << [col, val]
1194     end
1195     ret
1196   end
1197   alias get_dictionary get_directory
1198
1199   def get(item, col)
1200     tk_send('set', item, col)
1201   end
1202   def set(item, col, value)
1203     tk_send('set', item, col, value)
1204     self
1205   end
1206
1207   def tag_bind(tag, seq, *args)
1208     if TkComm._callback_entry?(args[0]) || !block_given?
1209       cmd = args.shift
1210     else
1211       cmd = Proc.new
1212     end
1213     _bind([@path, 'tag', 'bind', tag], seq, cmd, *args)
1214     self
1215   end
1216   alias tagbind tag_bind
1217
1218   def tag_bind_append(tag, seq, *args)
1219     if TkComm._callback_entry?(args[0]) || !block_given?
1220       cmd = args.shift
1221     else
1222       cmd = Proc.new
1223     end
1224     _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args)
1225     self
1226   end
1227   alias tagbind_append tag_bind_append
1228
1229   def tag_bind_remove(tag, seq)
1230     _bind_remove([@path, 'tag', 'bind', tag], seq)
1231     self
1232   end
1233   alias tagbind_remove tag_bind_remove
1234
1235   def tag_bindinfo(tag, context=nil)
1236     _bindinfo([@path, 'tag', 'bind', tag], context)
1237   end
1238   alias tagbindinfo tag_bindinfo
1239 end