canis 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +45 -0
  3. data/CHANGES +52 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +24 -0
  7. data/Rakefile +2 -0
  8. data/canis.gemspec +25 -0
  9. data/examples/alpmenu.rb +46 -0
  10. data/examples/app.sample +19 -0
  11. data/examples/appemail.rb +191 -0
  12. data/examples/atree.rb +105 -0
  13. data/examples/bline.rb +181 -0
  14. data/examples/common/devel.rb +319 -0
  15. data/examples/common/file.rb +93 -0
  16. data/examples/data/README.markdown +9 -0
  17. data/examples/data/brew.txt +38 -0
  18. data/examples/data/color.2 +37 -0
  19. data/examples/data/gemlist.txt +59 -0
  20. data/examples/data/lotr.txt +12 -0
  21. data/examples/data/ports.txt +136 -0
  22. data/examples/data/table.txt +37 -0
  23. data/examples/data/tasks.csv +88 -0
  24. data/examples/data/tasks.txt +27 -0
  25. data/examples/data/todo.txt +16 -0
  26. data/examples/data/todocsv.csv +28 -0
  27. data/examples/data/unix1.txt +21 -0
  28. data/examples/data/unix2.txt +11 -0
  29. data/examples/dbdemo.rb +506 -0
  30. data/examples/dirtree.rb +177 -0
  31. data/examples/newtabbedwindow.rb +100 -0
  32. data/examples/newtesttabp.rb +92 -0
  33. data/examples/tabular.rb +212 -0
  34. data/examples/tasks.rb +179 -0
  35. data/examples/term2.rb +88 -0
  36. data/examples/testbuttons.rb +307 -0
  37. data/examples/testcombo.rb +102 -0
  38. data/examples/testdb.rb +182 -0
  39. data/examples/testfields.rb +208 -0
  40. data/examples/testflowlayout.rb +43 -0
  41. data/examples/testkeypress.rb +98 -0
  42. data/examples/testlistbox.rb +187 -0
  43. data/examples/testlistbox1.rb +199 -0
  44. data/examples/testmessagebox.rb +144 -0
  45. data/examples/testprogress.rb +116 -0
  46. data/examples/testree.rb +107 -0
  47. data/examples/testsplitlayout.rb +53 -0
  48. data/examples/testsplitlayout1.rb +49 -0
  49. data/examples/teststacklayout.rb +48 -0
  50. data/examples/testwsshortcuts.rb +68 -0
  51. data/examples/testwsshortcuts2.rb +129 -0
  52. data/lib/canis.rb +16 -0
  53. data/lib/canis/core/docs/index.txt +104 -0
  54. data/lib/canis/core/docs/list.txt +16 -0
  55. data/lib/canis/core/docs/style_help.yml +34 -0
  56. data/lib/canis/core/docs/tabbedpane.txt +15 -0
  57. data/lib/canis/core/docs/table.txt +31 -0
  58. data/lib/canis/core/docs/textpad.txt +48 -0
  59. data/lib/canis/core/docs/tree.txt +23 -0
  60. data/lib/canis/core/include/.DS_Store +0 -0
  61. data/lib/canis/core/include/action.rb +83 -0
  62. data/lib/canis/core/include/actionmanager.rb +49 -0
  63. data/lib/canis/core/include/appmethods.rb +179 -0
  64. data/lib/canis/core/include/bordertitle.rb +49 -0
  65. data/lib/canis/core/include/canisparser.rb +100 -0
  66. data/lib/canis/core/include/colorparser.rb +437 -0
  67. data/lib/canis/core/include/defaultfilerenderer.rb +64 -0
  68. data/lib/canis/core/include/io.rb +320 -0
  69. data/lib/canis/core/include/layouts/SplitLayout.rb +161 -0
  70. data/lib/canis/core/include/layouts/abstractlayout.rb +213 -0
  71. data/lib/canis/core/include/layouts/flowlayout.rb +104 -0
  72. data/lib/canis/core/include/layouts/stacklayout.rb +109 -0
  73. data/lib/canis/core/include/listbindings.rb +89 -0
  74. data/lib/canis/core/include/listeditable.rb +319 -0
  75. data/lib/canis/core/include/listoperations.rb +61 -0
  76. data/lib/canis/core/include/listselectionmodel.rb +388 -0
  77. data/lib/canis/core/include/multibuffer.rb +173 -0
  78. data/lib/canis/core/include/ractionevent.rb +73 -0
  79. data/lib/canis/core/include/rchangeevent.rb +27 -0
  80. data/lib/canis/core/include/rhistory.rb +95 -0
  81. data/lib/canis/core/include/rinputdataevent.rb +47 -0
  82. data/lib/canis/core/include/textdocument.rb +111 -0
  83. data/lib/canis/core/include/vieditable.rb +175 -0
  84. data/lib/canis/core/include/widgetmenu.rb +66 -0
  85. data/lib/canis/core/system/colormap.rb +165 -0
  86. data/lib/canis/core/system/keydefs.rb +32 -0
  87. data/lib/canis/core/system/ncurses.rb +237 -0
  88. data/lib/canis/core/system/panel.rb +129 -0
  89. data/lib/canis/core/system/window.rb +1081 -0
  90. data/lib/canis/core/util/ansiparser.rb +119 -0
  91. data/lib/canis/core/util/app.rb +696 -0
  92. data/lib/canis/core/util/basestack.rb +412 -0
  93. data/lib/canis/core/util/defaultcolorparser.rb +84 -0
  94. data/lib/canis/core/util/extras/README +5 -0
  95. data/lib/canis/core/util/extras/bottomline.rb +1815 -0
  96. data/lib/canis/core/util/extras/padreader.rb +192 -0
  97. data/lib/canis/core/util/focusmanager.rb +31 -0
  98. data/lib/canis/core/util/helpmanager.rb +160 -0
  99. data/lib/canis/core/util/oldwidgetshortcuts.rb +304 -0
  100. data/lib/canis/core/util/promptmenu.rb +235 -0
  101. data/lib/canis/core/util/rcommandwindow.rb +933 -0
  102. data/lib/canis/core/util/rdialogs.rb +520 -0
  103. data/lib/canis/core/util/textutils.rb +74 -0
  104. data/lib/canis/core/util/viewer.rb +238 -0
  105. data/lib/canis/core/util/widgetshortcuts.rb +508 -0
  106. data/lib/canis/core/widgets/applicationheader.rb +103 -0
  107. data/lib/canis/core/widgets/box.rb +58 -0
  108. data/lib/canis/core/widgets/divider.rb +310 -0
  109. data/lib/canis/core/widgets/extras/README.md +12 -0
  110. data/lib/canis/core/widgets/extras/rtextarea.rb +960 -0
  111. data/lib/canis/core/widgets/extras/stackflow.rb +474 -0
  112. data/lib/canis/core/widgets/keylabelprinter.rb +194 -0
  113. data/lib/canis/core/widgets/listbox.rb +326 -0
  114. data/lib/canis/core/widgets/listfooter.rb +86 -0
  115. data/lib/canis/core/widgets/rcombo.rb +210 -0
  116. data/lib/canis/core/widgets/rcontainer.rb +415 -0
  117. data/lib/canis/core/widgets/rlink.rb +30 -0
  118. data/lib/canis/core/widgets/rmenu.rb +970 -0
  119. data/lib/canis/core/widgets/rmenulink.rb +30 -0
  120. data/lib/canis/core/widgets/rmessagebox.rb +400 -0
  121. data/lib/canis/core/widgets/rprogress.rb +118 -0
  122. data/lib/canis/core/widgets/rtabbedpane.rb +631 -0
  123. data/lib/canis/core/widgets/rtabbedwindow.rb +70 -0
  124. data/lib/canis/core/widgets/rwidget.rb +3634 -0
  125. data/lib/canis/core/widgets/scrollbar.rb +147 -0
  126. data/lib/canis/core/widgets/statusline.rb +113 -0
  127. data/lib/canis/core/widgets/table.rb +1072 -0
  128. data/lib/canis/core/widgets/tabular.rb +264 -0
  129. data/lib/canis/core/widgets/textpad.rb +1674 -0
  130. data/lib/canis/core/widgets/tree.rb +690 -0
  131. data/lib/canis/core/widgets/tree/treecellrenderer.rb +150 -0
  132. data/lib/canis/core/widgets/tree/treemodel.rb +432 -0
  133. data/lib/canis/version.rb +3 -0
  134. metadata +229 -0
@@ -0,0 +1,150 @@
1
+ # 2010-09-18 15:35
2
+ require 'canis'
3
+ require 'canis/core/widgets/rwidget'
4
+ module Canis
5
+
6
+ ##
7
+ # This is a basic list cell renderer that will render the to_s value of anything.
8
+ #
9
+ # TODO upgrade as per new listcellrenderer
10
+ class TreeCellRenderer
11
+ PLUS_PLUS = "++"
12
+ PLUS_MINUS = "+-"
13
+ PLUS_Q = "+?"
14
+ include Canis::ConfigSetup
15
+ include Canis::Utils
16
+ dsl_accessor :justify # :right, :left, :center # added 2008-12-22 19:02
17
+ dsl_accessor :display_length # please give this to ensure the we only print this much
18
+ dsl_accessor :height # if you want a multiline label.
19
+ dsl_accessor :text # text of label
20
+ dsl_accessor :color, :bgcolor
21
+ dsl_accessor :row, :col
22
+ dsl_accessor :parent #usuall the table to get colors and other default info
23
+ attr_reader :actual_length
24
+ attr_accessor :pcol
25
+
26
+ def initialize text="", config={}, &block
27
+ @text = text
28
+ @editable = false
29
+ @focusable = false
30
+ @actual_length = 0
31
+ config_setup config # @config.each_pair { |k,v| variable_set(k,v) }
32
+ instance_eval &block if block_given?
33
+ init_vars
34
+ end
35
+ def init_vars
36
+ @justify ||= :left
37
+ @display_length ||= 10
38
+ end
39
+ def getvalue
40
+ @text
41
+ end
42
+ ##
43
+ # sets @color_pair and @attr
44
+ def prepare_default_colors focussed, selected
45
+ @color_pair = get_color $datacolor
46
+ @attr = @row_attr || Ncurses::A_NORMAL
47
+
48
+
49
+ ## determine bg and fg and attr
50
+ if selected
51
+ #@attr = Ncurses::A_BOLD if selected
52
+ ## 2010-09-18 18:32 making selected row reverse
53
+ @attr |= Ncurses::A_REVERSE
54
+
55
+ # 2010-09-18 18:33 maybe not required, just confuses the whole thing and uglifies it
56
+ #@color_pair =get_color $selectedcolor, @parent.selected_color, @parent.selected_bgcolor unless @parent.nil?
57
+ end
58
+ case focussed
59
+ when :SOFT_FOCUS
60
+ @attr |= Ncurses::A_BOLD
61
+ when true
62
+ # earlier focussed row showed up in reverse, which was confusing since it looked selected
63
+ # now focussed row has cursor on side, and can be bold. that's enough.
64
+ @attr |= Ncurses::A_BOLD
65
+ #@attr |= Ncurses::A_REVERSE
66
+ when false
67
+ end
68
+ end
69
+
70
+ ##
71
+ # paint a list box cell
72
+ # 2010-09-02 15:38 changed focussed to take true, false and :SOFT_FOCUS
73
+ # SOFT_FOCUS means the form focus is no longer on this field, but this row
74
+ # was focussed when use was last on this field. This row will take focus
75
+ # when field is focussed again
76
+ #
77
+ # @param [Buffer] window or buffer object used for printing
78
+ # @param [Fixnum] row
79
+ # @param [Fixnum] column
80
+ # @param [Fixnum] actual index into data, some lists may have actual data elsewhere and
81
+ # display data separate. e.g. rfe_renderer (directory listing)
82
+ # @param [String] text to print in cell
83
+ # @param [Boolean, :SOFT_FOCUS] cell focussed, not focussed, cell focussed but field is not focussed
84
+ # @param [Boolean] cell selected or not
85
+ #renderer.repaint @graphic, r+hh, c+@left_margin, crow, object, content, focus_type, selected, expanded, leaf
86
+ def repaint graphic, r=@row,c=@col, row_index=-1, treearraynode=nil, value=@text, leaf=nil, focussed=false, selected=false, expanded=false
87
+ #$log.debug "label :#{@text}, #{value}, #{r}, #{c} col= #{@color}, #{@bgcolor} acolor= #{acolor} j:#{@justify} dlL: #{@display_length} "
88
+
89
+ prepare_default_colors focussed, selected
90
+
91
+ value=value.to_s # ??
92
+ #icon = object.is_leaf? ? "-" : "+"
93
+ #icon = leaf ? "-" : "+"
94
+
95
+ #level = treearraynode.level
96
+ #node = treearraynode.node
97
+ level = treearraynode.level
98
+ node = treearraynode
99
+ if parent.node_expanded? node
100
+ icon = PLUS_MINUS # can collapse
101
+ else
102
+ icon = PLUS_PLUS # can expand
103
+ end
104
+ if node.children.size == 0
105
+ icon = PLUS_Q # either no children or not visited yet
106
+ if parent.has_been_expanded node
107
+ icon = PLUS_MINUS # definitely no children, we've visited
108
+ end
109
+ end
110
+ # adding 2 to level, that's the size of icon
111
+ # XXX FIXME if we put the icon here, then when we scroll right, the icon will show, it shoud not
112
+ # FIXME we ignore truncation etc on previous level and take the object as is !!!
113
+ _value = "%*s %s" % [ level+2, icon, node.user_object ]
114
+ @actual_length = _value.length
115
+ pcol = @pcol
116
+ if pcol > 0
117
+ _len = @display_length || @parent.width-2
118
+ _value = _value[@pcol..@pcol+_len-1]
119
+ end
120
+ _value ||= ""
121
+ if @height && @height > 1
122
+ else
123
+ # ensure we do not exceed
124
+ if !@display_length.nil?
125
+ if _value.length > @display_length
126
+ @actual_length = _value.length
127
+ _value = _value[0..@display_length-1]
128
+ end
129
+ end
130
+ #lablist << value
131
+ end
132
+ len = @display_length || _value.length
133
+ graphic.printstring r, c, "%-*s" % [len, _value], @color_pair,@attr
134
+ #_height = @height || 1
135
+ #0.upto(_height-1) { |i|
136
+ #graphic.printstring r+i, c, ( " " * len) , @color_pair,@attr
137
+ #}
138
+ #lablist.each_with_index do |_value, ix|
139
+ #break if ix >= _height
140
+ #if @justify.to_sym == :center
141
+ #padding = (@display_length - _value.length)/2
142
+ #_value = " "*padding + _value + " "*padding # so its cleared if we change it midway
143
+ #end
144
+ #graphic.printstring r, c, str % [len, _value], @color_pair,@attr
145
+ #r += 1
146
+ #end
147
+ end
148
+ # ADD HERE
149
+ end
150
+ end
@@ -0,0 +1,432 @@
1
+ # File TreeModel
2
+ # (c) jkepler ABCD
3
+ # Created on: Fri Sep 17 20:03:10 IST 2010
4
+ require 'canis'
5
+
6
+ module Canis
7
+ class IllegalStateException < Exception
8
+ end
9
+
10
+ class DefaultTreeModel #< TreeModel
11
+ include Canis::EventHandler
12
+ attr_reader :asks_allow_children
13
+ attr_accessor :root_visible
14
+ def initialize node=nil, asks_allow_children=false, &block
15
+ @root_visible = true
16
+ root(node, asks_allow_children) if node
17
+ instance_eval &block if block_given?
18
+ end
19
+ # insert a node the old sucky java pain in the butt way
20
+ # private
21
+ # sets node as root
22
+ #def root node, asks_allow_children=false, &block
23
+ def root *args, &block
24
+ return @root if args.empty?
25
+ node = args[0]
26
+ @asks_allow_children = args[1]
27
+ if !node.is_a? TreeNode
28
+ n = TreeNode.new node
29
+ node = n
30
+ end
31
+ @root = node
32
+ $log.debug " XXX def root created root with #{node} "
33
+ #add node, true, &block
34
+ instance_eval &block if block_given?
35
+ end
36
+ def insert_node_into nodechild, nodeparent, index
37
+ $log.debug " TODO remove from existing parent to avoid bugs XXX"
38
+ nodeparent.insert nodechild, index
39
+ if @handler # only if someone is listening, won't fire when being prepared
40
+ tme = TreeModelEvent.new(row, row,:ALL_COLUMNS, self, :INSERT)
41
+ fire_handler :TREE_MODEL_EVENT, tme
42
+ end
43
+ self
44
+ end
45
+ # add a node to root passing a block optionally
46
+ # @param [String, TreeNode, Array, Hash] node/s to add
47
+ # @param [Boolean] allow children to be added
48
+ # @see TreeNode.add
49
+ # @return [TreeNode] node just added to root (NOT self)
50
+ def add nodechild, allows_children=true, &block
51
+ # calling TreeNode.add
52
+ $log.debug " XXX def add of DTM #{nodechild} to root "
53
+ node = @root.add nodechild, allows_children, &block
54
+ if @handler # only if someone is listening, won't fire when being prepared
55
+ tme = TreeModelEvent.new(row, row,:ALL_COLUMNS, self, :INSERT)
56
+ fire_handler :TREE_MODEL_EVENT, tme
57
+ end
58
+ #return @root
59
+ return node
60
+ end
61
+ def leaf node, &block
62
+ add node, false, &block
63
+ end
64
+ def branch node, &block
65
+ add node, true, &block
66
+ end
67
+ alias :<< :add
68
+ def insert row, obj
69
+ @data.insert row, obj
70
+ if @handler # only if someone is listening, won't fire when being prepared
71
+ tme = TreeModelEvent.new(row, row,:ALL_COLUMNS, self, :INSERT)
72
+ fire_handler :TREE_MODEL_EVENT, tme
73
+ end
74
+ def child_at parent, index
75
+ end
76
+ def index_of_child parent, child
77
+ end
78
+ def child_count node
79
+ node.children.size
80
+ end
81
+
82
+ def row_count
83
+ @data.length
84
+ end
85
+ #
86
+ def set_value_at row, col, val
87
+ # if editing allowed
88
+ raise "not yet used"
89
+ @data[row][col] = val
90
+ tme = TreeModelEvent.new(row, row, col, self, :UPDATE)
91
+ fire_handler :TREE_MODEL_EVENT, tme
92
+ end
93
+ ##
94
+ # please avoid directly hitting this. Suggested to use get_value_at of jtable
95
+ # since columns could have been switched.
96
+ def get_value_at row, col
97
+ raise "not yet used"
98
+ #$log.debug " def get_value_at #{row}, #{col} "
99
+
100
+ raise "IndexError get_value_at #{row}, #{col}" if @data.nil? or row >= @data.size
101
+ return @data[row][ col]
102
+ end
103
+ #def << obj
104
+ #@data << obj
105
+ #tme = TreeModelEvent.new(@data.length-1,@data.length-1, :ALL_COLUMNS, self, :INSERT)
106
+ #fire_handler :TREE_MODEL_EVENT, tme
107
+ #end
108
+ # create tablemodelevent and fire_table_changed for all listeners
109
+ end
110
+ def delete obj
111
+ raise "not yet used"
112
+ row = @data.index obj
113
+ return if row.nil?
114
+ ret = @data.delete obj
115
+ tme = TreeModelEvent.new(row, row,:ALL_COLUMNS, self, :DELETE)
116
+ fire_handler :TREE_MODEL_EVENT, tme
117
+ # create tablemodelevent and fire_table_changed for all listeners
118
+ return ret
119
+ end
120
+ def delete_at row
121
+ raise "not yet used"
122
+ if !$multiplier or $multiplier == 0
123
+ @delete_buffer = @data.delete_at row
124
+ else
125
+ @delete_buffer = @data.slice!(row, $multiplier)
126
+ end
127
+ $multiplier = 0
128
+ #ret = @data.delete_at row
129
+ # create tablemodelevent and fire_table_changed for all listeners
130
+ # we don;t pass buffer to event as in listeditable. how to undo later?
131
+ tme = TreeModelEvent.new(row, row+@delete_buffer.length,:ALL_COLUMNS, self, :DELETE)
132
+ fire_handler :TREE_MODEL_EVENT, tme
133
+ return @delete_buffer
134
+ end
135
+ # a quick method to undo deletes onto given row. More like paste
136
+ def undo where
137
+ raise "not yet used"
138
+ return unless @delete_buffer
139
+ case @delete_buffer[0]
140
+ when Array
141
+ @delete_buffer.each do |r|
142
+ insert where, r
143
+ end
144
+ else
145
+ insert where, @delete_buffer
146
+ end
147
+ end
148
+ ##
149
+ # added 2009-01-17 21:36
150
+ # Use with caution, does not call events per row
151
+ def delete_all
152
+ raise "not yet used"
153
+ len = @data.length-1
154
+ @data=[]
155
+ tme = TreeModelEvent.new(0, len,:ALL_COLUMNS, self, :DELETE)
156
+ fire_handler :TREE_MODEL_EVENT, tme
157
+ end
158
+ ##
159
+ # for those quick cases when you wish to replace all the data
160
+ # and not have an event per row being generated
161
+ def data=(data)
162
+ raise "not yet used"
163
+ raise "Data nil or invalid" if data.nil? or data.size == 0
164
+ delete_all
165
+ @data = data
166
+ tme = TreeModelEvent.new(0, @data.length-1,:ALL_COLUMNS, self, :INSERT)
167
+ fire_handler :TREE_MODEL_EVENT, tme
168
+ end
169
+ #def ask_search_forward
170
+ #regex = get_string "Enter regex to search for:"
171
+ #ix = get_list_data_model.find_match regex
172
+ #if ix.nil?
173
+ #alert("No matching data for: #{regex}")
174
+ #else
175
+ #set_focus_on(ix)
176
+ #end
177
+ #end
178
+ ## continues previous search
179
+ ###
180
+ #def find_match regex, ix0=0, ix1=row_count()
181
+ #$log.debug " find_match got #{regex} #{ix0} #{ix1}"
182
+ #@last_regex = regex
183
+ #@search_start_ix = ix0
184
+ #@search_end_ix = ix1
185
+ #@data.each_with_index do |row, ix|
186
+ #next if ix < ix0
187
+ #break if ix > ix1
188
+ #if row.grep(/#{regex}/) != []
189
+ ##if !row.match(regex).nil?
190
+ #@search_found_ix = ix
191
+ #return ix
192
+ #end
193
+ #end
194
+ #return nil
195
+ #end
196
+ #def find_prev regex=@last_regex, start = @search_found_ix
197
+ #raise "No previous search" if @last_regex.nil?
198
+ #$log.debug " find_prev #{@search_found_ix} : #{@current_index}"
199
+ #start -= 1 unless start == 0
200
+ #@last_regex = regex
201
+ #@search_start_ix = start
202
+ #start.downto(0) do |ix|
203
+ #row = @data[ix]
204
+ #if row.grep(/#{regex}/) != []
205
+ #@search_found_ix = ix
206
+ #return ix
207
+ #end
208
+ #end
209
+ #return nil
210
+ ##return find_match @last_regex, start, @search_end_ix
211
+ #end
212
+ ### dtm findnext
213
+ #def find_next
214
+ #raise "No more search" if @last_regex.nil?
215
+ #start = @search_found_ix && @search_found_ix+1 || 0
216
+ #return find_match @last_regex, start, @search_end_ix
217
+ #end
218
+ # just a test program
219
+ def traverse node=@root, level=0
220
+ icon = node.is_leaf? ? "-" : "+"
221
+ puts "%*s %s" % [ level+1, icon, node.user_object ]
222
+ node.children.each do |e|
223
+ traverse e, level+1
224
+ end
225
+ end
226
+ end # class DTM
227
+ # When an event is fired by TableModel, contents are changed, then this object will be passed
228
+ # to trigger
229
+ # type is :INSERT :UPDATE :DELETE :HEADER_ROW
230
+ # columns: number or :ALL_COLUMNS
231
+ class TreeModelEvent
232
+ attr_accessor :firstrow, :lastrow, :source, :type
233
+ def initialize firstrow, lastrow, source, type
234
+ @firstrow = firstrow
235
+ @lastrow = lastrow
236
+ @source = source
237
+ @type = type
238
+ end
239
+ def to_s
240
+ "#{@type.to_s}, firstrow: #{@firstrow}, lastrow: #{@lastrow}, source: #{@source}"
241
+ end
242
+ def inspect
243
+ to_s
244
+ end
245
+ end
246
+ class TreeNode
247
+ #extend Forwardable
248
+
249
+ attr_accessor :parent
250
+ attr_reader :children
251
+ attr_reader :user_object
252
+ attr_reader :allows_children
253
+ def initialize user_object=nil, allows_children=true, &block #form, config={}, &block
254
+ @allows_children = allows_children
255
+ @user_object = user_object
256
+ @children = []
257
+ #super
258
+ instance_eval &block if block_given?
259
+ init_vars
260
+ end
261
+ # private
262
+ #@return [TreeNode] just creates node
263
+ def _add node, allows_children=true, &block
264
+ #raise ArgumentError, "Argument should be a node" if !node.is_a? TreeNode
265
+ $log.debug " TODO remove from existing parent to avoid bugs XXX"
266
+ if !node.is_a? TreeNode
267
+ n = TreeNode.new node, allows_children, &block
268
+ node = n
269
+ end
270
+ node.parent = self
271
+ @children << node
272
+ node
273
+ end
274
+ # add a node to this node, optionally passing a block for further adding
275
+ # add a node as child to existing node
276
+ # If node is not a TreeNode it will be converted to one.
277
+ # @param [TreeNode, Array, Hash] node/s to add
278
+ # @param [boolean] should children be allowed
279
+ # @return [TreeNode] node last added (*NOT* self)
280
+ def add node, allows_children=true, &block
281
+ raise IllegalStateException, "Cannot add a child to this node" unless @allows_children
282
+ $log.debug " XXX def add of TreeNode #{node} parent #{self} "
283
+ case node
284
+ when Array
285
+ node.each do |e|
286
+ add e, allows_children, &block
287
+ end
288
+ when Hash
289
+ node.each_pair { |name, val|
290
+ n = _add name, allows_children, &block
291
+ n.add val, allows_children, &block
292
+ }
293
+ else
294
+ return _add node, allows_children, &block
295
+ end
296
+ self
297
+ end
298
+ def leaf node, &block
299
+ add node, false, &block
300
+ end
301
+ def branch node, &block
302
+ add node, true, &block
303
+ end
304
+ alias :<< :add
305
+ def insert node, index
306
+ raise ArgumentError, "Argument should be a node. it is #{node.class} " if !node.is_a? TreeNode
307
+ @children.insert index, node
308
+ self
309
+ end
310
+ def child_after node
311
+ end
312
+ def child_before node
313
+ end
314
+ def child_at node
315
+ end
316
+ def next_node node
317
+ end
318
+ def remove
319
+ end
320
+ def remove_all_children
321
+ end
322
+ def remove_from_parent
323
+ end
324
+ def is_leaf?
325
+ @children.size == 0
326
+ end
327
+ def leaf_count
328
+ end
329
+ def level
330
+ level = 0
331
+ nodeparent = parent()
332
+ while( nodeparent != nil )
333
+ level += 1
334
+ nodeparent = nodeparent.parent()
335
+ end
336
+ return level
337
+ end
338
+ def leaf_count
339
+ end
340
+ def traverse_up &block
341
+ nodeparent = parent()
342
+ while ( nodeparent != nil )
343
+ yield nodeparent
344
+ nodeparent = nodeparent.parent()
345
+ end
346
+ end
347
+ # returns an array of user_objects for the current node
348
+ # starting from root, ending in the current one. The last node
349
+ # represents this node.
350
+ # @return [Array] Strings[]
351
+ def user_object_path
352
+ arr = []
353
+ arr << self.user_object.to_s
354
+ traverse_up do |e|
355
+ arr << e.user_object.to_s
356
+ end
357
+ arr.reverse!
358
+ end
359
+ # returns an array of nodes for the current node
360
+ # starting from root, ending in the current one. The last node
361
+ # represents this node.
362
+ # @return [Array] TreeNode[]
363
+ def tree_path
364
+ arr = []
365
+ arr << self
366
+ traverse_up do |e|
367
+ arr << e
368
+ end
369
+ arr.reverse!
370
+ end
371
+ # http://github.com/evolve75/RubyTree/blob/master/lib/tree.rb
372
+ def breadth_each(max_depth=999,&block)
373
+ node_queue = [self] # Create a queue with self as the initial entry
374
+
375
+ # Use a queue to do breadth traversal
376
+ until node_queue.empty?
377
+ node_to_traverse = node_queue.shift
378
+ yield node_to_traverse
379
+ # Enqueue the children from left to right.
380
+ node_to_traverse.children { |child| node_queue.push child }
381
+ max_depth -= 1
382
+ break if max_depth == 0
383
+ end
384
+ end
385
+ def to_s
386
+ @user_object.to_s
387
+ end
388
+ # need by textpad to calculate pad
389
+ def length
390
+ to_s.length
391
+ end
392
+ def init_vars
393
+ @repaint_required = true
394
+ end
395
+ end
396
+ end # module
397
+
398
+ if $0 == __FILE__
399
+ $log = Logger.new("canis.log")
400
+ $log.level = Logger::DEBUG
401
+
402
+ include Canis
403
+ root = TreeNode.new "ROOT"
404
+ subroot = TreeNode.new "subroot"
405
+ leaf1 = TreeNode.new "leaf 1"
406
+ leaf2 = TreeNode.new "leaf 2"
407
+
408
+ model = DefaultTreeModel.new root
409
+ #model.insert_node_into(subroot, root, 0)
410
+ #model.insert_node_into(leaf1, subroot, 0)
411
+ #model.insert_node_into(leaf2, subroot, 1)
412
+ root << subroot
413
+ # this will allow us to do a recursive add
414
+ #subroot << leaf1 << leaf2
415
+ subroot << leaf1
416
+ subroot << leaf2
417
+ leaf1 << "leaf11" << "leaf111"
418
+ leaf1 << "leaf12" << "leaf121"
419
+
420
+ root.add "blocky", true do
421
+ add "block2"
422
+ add "block3" do
423
+ add "block31"
424
+ end
425
+ end
426
+
427
+ model.traverse root
428
+ puts "tree path: ..."
429
+ puts leaf2.tree_path
430
+ puts "object path: ..."
431
+ puts leaf2.user_object_path
432
+ end