rspreadsheet 0.2.0 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,54 +1,64 @@
1
- require('rspreadsheet/cell')
2
- require('forwardable')
1
+ require 'rspreadsheet/cell'
2
+ require 'rspreadsheet/xml_tied'
3
3
 
4
4
  # Currently this is only syntax sugar for cells and contains no functionality
5
5
 
6
6
  module Rspreadsheet
7
7
 
8
- class Row < RowOrNode
8
+ class Row < XMLTiedItem
9
+ include XMLTiedArray
9
10
  attr_reader :worksheet, :rowi
11
+ def xml_repeated_attribute; 'number-rows-repeated' end
12
+ def xml_items_node_name; 'table-row' end
13
+ def xml_options; {:xml_items_node_name => xml_items_node_name, :xml_repeated_attribute => xml_repeated_attribute} end
14
+ def subitem_xml_options; {:xml_items_node_name => 'table-cell', :xml_repeated_attribute => 'number-columns-repeated'} end
15
+
10
16
  def initialize(aworksheet,arowi)
11
17
  @worksheet = aworksheet
12
18
  @rowi = arowi
19
+ @itemcache = Hash.new #TODO: move to module XMLTiedArray
13
20
  end
14
- def xmlnode; @worksheet.rowxmlnode(@rowi) end
15
- def cells(coli)
16
- coli = coli.to_i
17
- if coli.to_i<=0
18
- nil
19
- else
20
- Cell.new(@worksheet,@rowi,coli)
21
+ def xmlnode; parent.find_my_subnode_respect_repeated(index, xml_options) end
22
+
23
+ # XMLTiedItem things and extensions
24
+ def parent; @worksheet end
25
+ def index; @rowi end
26
+ def set_index(value); @rowi=value end
27
+
28
+ # XMLTiedArray rozšíření
29
+ def prepare_subitem(coli); Cell.new(@worksheet,@rowi,coli) end
30
+ def cells(*params)
31
+ raise 'Invalid row reference' if invalid_reference?
32
+ case params.length
33
+ when 0 then subitems_array
34
+ when 1 then subitem(params[0])
35
+ else raise Exception.new('Wrong number of arguments.')
21
36
  end
22
37
  end
23
- def self.empty_xmlnode(repeats=1)
24
- node = LibXML::XML::Node.new('table-row',nil, Tools.get_namespace('table'))
25
- Tools.set_ns_attribute(node,'table','number-rows-repeated',repeats, 1)
26
- node
27
- end
28
- def detach_if_needed;
29
- detach if repeated?
30
- end
31
- def detach
32
- @worksheet.detach_row_in_xml(@rowi)
33
- self
34
- end
35
- def repeated
36
- (Tools.get_ns_attribute_value(self.xmlnode, 'table', 'number-rows-repeated') || 1).to_i
37
- end
38
- def repeated?; mode==:repeated || mode==:outbound end
39
- alias :is_repeated? :repeated?
38
+ # syntactis sugar to cells and its values
39
+ def [](coli); cells(coli).value end
40
+ def []=(coli,avalue); cells(coli).value=avalue end
41
+
42
+ # další
40
43
  def style_name=(value);
41
44
  detach_if_needed
42
45
  Tools.set_ns_attribute(xmlnode,'table','style-name',value)
43
46
  end
44
- def used_range
45
- @worksheet.rowrange(@rowi)
46
- end
47
47
  def nonemptycells
48
- nonemptycellsindexes.collect{ |index| cells(index) }
48
+ nonemptycellsindexes.collect{ |index| subitem(index) }
49
49
  end
50
50
  def nonemptycellsindexes
51
- @worksheet.row_nonempty_cells_col_indexes(@rowi)
51
+ myxmlnode = xmlnode
52
+ if myxmlnode.nil?
53
+ []
54
+ else
55
+ @worksheet.find_nonempty_subnode_indexes(myxmlnode, {:xml_items_node_name => 'table-cell', :xml_repeated_attribute => 'number-columns-repeated'})
56
+ end
57
+ end
58
+ alias :used_range :range
59
+ def shift_by(diff)
60
+ super
61
+ @itemcache.each_value{ |cell| cell.set_rowi(@rowi) }
52
62
  end
53
63
  end
54
64
 
@@ -68,189 +78,175 @@ end
68
78
  # --------------------------
69
79
 
70
80
 
71
- # XmlTiedArrayItemGroup is internal representation of repeated items in XmlTiedArray.
72
- class XmlTiedArrayItemGroup
73
- # extend Forwardable
74
- # delegate [:normalize ] => :@row_group
75
-
76
- def normalize; @rowgroup.normalize end
77
- def range; @rowgroup.range end
78
- def repeated?; self.range.size>1 end
79
- def xmlnode; @rowgroup.xmlnode end
81
+ # # XmlTiedArrayItemGroup is internal representation of repeated items in XmlTiedArray.
82
+ # class XmlTiedArrayItemGroup
83
+ # # extend Forwardable
84
+ # # delegate [:normalize ] => :@row_group
85
+ #
86
+ # def normalize; @rowgroup.normalize end
80
87
 
81
- def initialize(aparent_array,arange,axmlnode=nil)
82
- @rowgroup = RowGroup.new(aparent_array,arange,axmlnode)
83
- end
84
- def self.new_from_xml
85
- end
86
- def to_rowgroup
87
- @rowgroup
88
- end
89
- def range=(arange)
90
-
91
- end
92
- end
88
+ # end
93
89
 
94
90
  # array which synchronizes with xml structure and reflects. number-xxx-repeated attributes
95
91
  # also caches returned objects for indexes.
96
92
  # options must contain
97
93
  # :xml_items, :xml_repeated_attribute, :object_type
98
94
 
99
- class XmlTiedArray < Array
100
- def initialize(axmlnode, options={}) # TODO get rid of XmlTiedArray
101
- @xmlnode = axmlnode
102
- @options = options
103
-
104
- missing_options = [:xml_repeated_attribute,:xml_items_node_name,:object_type]-@options.keys
105
- raise "Some options missing (#{missing_options.inspect})" unless missing_options.empty?
106
-
107
- unless @xmlnode.nil?
108
- @xmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |group_source_node|
109
- self << parse_xml_to_group(group_source_node) # it is in @xmlnode so suffices to add object to @rowgroups
110
- end
111
- end
112
- @itemcache=Hash.new()
113
- end
114
- def parse_xml_to_group(size_or_xmlnode) # parses xml to new RowGroup which can be added at the end
115
- # reading params
116
- if size_or_xmlnode.kind_of? LibXML::XML::Node
117
- size = (size_or_xmlnode[@options[:xml_repeated_attribute]] || 1).to_i
118
- node = size_or_xmlnode
119
- elsif size_or_xmlnode.to_i>0
120
- size = size_or_xmlnode.to_i
121
- node = nil
122
- else
123
- return nil
124
- end
125
- index = first_unused_index
126
- # construct result
127
- Rspreadsheet::XmlTiedArrayItemGroup.new(self,index..index+size-1,node)
128
- end
129
- def add_item_group(size_or_xmlnode)
130
- result = parse_xml_to_group(size_or_xmlnode)
131
- self << result
132
- @xmlnode << result.xmlnode
133
- result
134
- end
135
- def first_unused_index
136
- empty? ? 1 : last.range.end+1
137
- end
138
- # prolonges the RowArray to cantain rowi and returns it
139
- def detach_of_bound_item(index)
140
- fill_row_group_size = index-first_unused_index
141
- if fill_row_group_size>0
142
- add_item_group(fill_row_group_size)
143
- end
144
- add_item_group(1)
145
- get_item(index) # aby se odpoved nacacheovala
146
- end
147
- def get_item_group(index)
148
- find{ |item_group| item_group.range.cover?(index) }
149
- end
150
- def detach_item(index); get_item(index) end # TODO předělat do lazy podoby, kdy tohle nebude stejny
151
- def get_item(index)
152
- if index>= first_unused_index
153
- nil
154
- else
155
- @itemcache[index] ||= Rspreadsheet::XmlTiedArrayItem.new(self,index)
156
- end
157
- end
158
- # This detaches item index from the group and perhaps splits the RowGroup
159
- # into two pieces. This makes the row individually editable.
160
- def detach(index)
161
- group_index = get_group_index(index)
162
- item_group = self[group_index]
163
- range = item_group.range
164
- return self if range==(index..index)
165
-
166
- # prepare new components
167
- replaceby = []
168
- replaceby << RowGroup.new(self,range.begin..index-1)
169
- replaceby << (result = SingleRow.new(self,index))
170
- replaceby << RowGroup.new(self,index+1..range.end)
171
-
172
- # put original range somewhere in replaceby and shorten it
173
-
174
- if index>range.begin
175
- replaceby[0] = item_group
176
- item_group.range = range.begin..index-1
177
- else
178
- replaceby[2] = item_group
179
- item_group.range = index+1..range.end
180
- end
181
-
182
- # normalize and delete empty parts
183
- replaceby = replaceby.map(&:normalize).compact
184
-
185
- # do the replacement in xml
186
- marker = LibXML::XML::Node.new('temporarymarker')
187
- item_group.xmlnode.next = marker
188
- item_group.xmlnode.remove!
189
- replaceby.each{ |rg|
190
- marker.prev = rg.xmlnode
191
- }
192
- marker.remove!
193
-
194
- # do the replacement in array
195
- self[group_index..group_index]=replaceby
196
- result
197
- end
198
- private
199
- def get_group_index(index)
200
- self.find_index{ |rowgroup| rowgroup.range.cover?(index) }
201
- end
202
- end
95
+ # class XmlTiedArray < Array
96
+ # def initialize(axmlnode, options={}) # TODO get rid of XmlTiedArray
97
+ # @xmlnode = axmlnode
98
+ # @options = options
99
+ #
100
+ # missing_options = [:xml_repeated_attribute,:xml_items_node_name,:object_type]-@options.keys
101
+ # raise "Some options missing (#{missing_options.inspect})" unless missing_options.empty?
102
+ #
103
+ # unless @xmlnode.nil?
104
+ # @xmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |group_source_node|
105
+ # self << parse_xml_to_group(group_source_node) # it is in @xmlnode so suffices to add object to @rowgroups
106
+ # end
107
+ # end
108
+ # @itemcache=Hash.new()
109
+ # end
110
+ # def parse_xml_to_group(size_or_xmlnode) # parses xml to new RowGroup which can be added at the end
111
+ # # reading params
112
+ # if size_or_xmlnode.kind_of? LibXML::XML::Node
113
+ # size = (size_or_xmlnode[@options[:xml_repeated_attribute]] || 1).to_i
114
+ # node = size_or_xmlnode
115
+ # elsif size_or_xmlnode.to_i>0
116
+ # size = size_or_xmlnode.to_i
117
+ # node = nil
118
+ # else
119
+ # return nil
120
+ # end
121
+ # index = first_unused_index
122
+ # # construct result
123
+ # Rspreadsheet::XmlTiedArrayItemGroup.new(self,index..index+size-1,node)
124
+ # end
125
+ # def add_item_group(size_or_xmlnode)
126
+ # result = parse_xml_to_group(size_or_xmlnode)
127
+ # self << result
128
+ # @xmlnode << result.xmlnode
129
+ # result
130
+ # end
131
+ # def first_unused_index
132
+ # empty? ? 1 : last.range.end+1
133
+ # end
134
+ # # prolonges the RowArray to cantain rowi and returns it
135
+ # def detach_of_bound_item(index)
136
+ # fill_row_group_size = index-first_unused_index
137
+ # if fill_row_group_size>0
138
+ # add_item_group(fill_row_group_size)
139
+ # end
140
+ # add_item_group(1)
141
+ # get_item(index) # aby se odpoved nacacheovala
142
+ # end
143
+ # def get_item_group(index)
144
+ # find{ |item_group| item_group.range.cover?(index) }
145
+ # end
146
+ # def detach_item(index); get_item(index) end # TODO předělat do lazy podoby, kdy tohle nebude stejny
147
+ # def get_item(index)
148
+ # if index>= first_unused_index
149
+ # nil
150
+ # else
151
+ # @itemcache[index] ||= Rspreadsheet::XmlTiedArrayItem.new(self,index)
152
+ # end
153
+ # end
154
+ # # This detaches item index from the group and perhaps splits the RowGroup
155
+ # # into two pieces. This makes the row individually editable.
156
+ # def detach(index)
157
+ # group_index = get_group_index(index)
158
+ # item_group = self[group_index]
159
+ # range = item_group.range
160
+ # return self if range==(index..index)
161
+ #
162
+ # # prepare new components
163
+ # replaceby = []
164
+ # replaceby << RowGroup.new(self,range.begin..index-1)
165
+ # replaceby << (result = SingleRow.new(self,index))
166
+ # replaceby << RowGroup.new(self,index+1..range.end)
167
+ #
168
+ # # put original range somewhere in replaceby and shorten it
169
+ #
170
+ # if index>range.begin
171
+ # replaceby[0] = item_group
172
+ # item_group.range = range.begin..index-1
173
+ # else
174
+ # replaceby[2] = item_group
175
+ # item_group.range = index+1..range.end
176
+ # end
177
+ #
178
+ # # normalize and delete empty parts
179
+ # replaceby = replaceby.map(&:normalize).compact
180
+ #
181
+ # # do the replacement in xml
182
+ # marker = LibXML::XML::Node.new('temporarymarker')
183
+ # item_group.xmlnode.next = marker
184
+ # item_group.xmlnode.remove!
185
+ # replaceby.each{ |rg|
186
+ # marker.prev = rg.xmlnode
187
+ # }
188
+ # marker.remove!
189
+ #
190
+ # # do the replacement in array
191
+ # self[group_index..group_index]=replaceby
192
+ # result
193
+ # end
194
+ # private
195
+ # def get_group_index(index)
196
+ # self.find_index{ |rowgroup| rowgroup.range.cover?(index) }
197
+ # end
198
+ # end
203
199
 
204
- class XmlTiedArrayItem
205
- attr_reader :index
206
- def initialize(aarray,aindex)
207
- @array = aarray
208
- @index = aindex
209
- if self.virtual?
210
- @object = nil
211
- else
212
- @object = @array.options[:object_type].new(group.xmlnode)
213
- end
214
- end
215
- def group; @array.get_item_group(index) end
216
- def repeated?; group.repeated? end
217
- def virtual?; ! self.repeated? end
218
- def array
219
- raise 'Group empty' if @group.nil?
220
- @array
221
- end
222
- end
200
+ # class XmlTiedArrayItem
201
+ # attr_reader :index
202
+ # def initialize(aarray,aindex)
203
+ # @array = aarray
204
+ # @index = aindex
205
+ # if self.virtual?
206
+ # @object = nil
207
+ # else
208
+ # @object = @array.options[:object_type].new(group.xmlnode)
209
+ # end
210
+ # end
211
+ # def group; @array.get_item_group(index) end
212
+ # def repeated?; group.repeated? end
213
+ # def virtual?; ! self.repeated? end
214
+ # def array
215
+ # raise 'Group empty' if @group.nil?
216
+ # @array
217
+ # end
218
+ # end
223
219
 
224
- class RowArray < XmlTiedArray
225
- attr_reader :row_array_cache
226
- def initialize(aworksheet,aworksheet_node)
227
- @worksheet = aworksheet
228
- @row_array_cache = Hash.new()
229
- super(aworksheet_node, :xml_items_node_name => 'table-row', :xml_repeated_attribute => 'number-rows-repeated', :object_type=>Row)
230
- end
231
- def get_row(rowi)
232
- if @row_array_cache.has_key?(rowi)
233
- return @row_array_cache[rowi]
234
- end
235
- item = self.get_item(rowi)
236
- @row_array_cache[rowi] = if item.nil?
237
- if rowi>0 then Rspreadsheet::UninitializedEmptyRow.new(self,rowi) else nil end
238
- else
239
- if item.repeated?
240
- Rspreadsheet::MemberOfRowGroup.new(item.index, item.group.to_rowgroup)
241
- else
242
- Rspreadsheet::SingleRow.new_from_rowgroup(item.group.to_rowgroup)
243
- end
244
- end
245
- end
246
- # aliases
247
- def first_unused_row_index; first_unused_index end
248
- def worksheet; @worksheet end
249
- def detach_of_bound_row_group(index)
250
- super(index)
251
- return get_row(index)
252
- end
253
- end
220
+ # class RowArray < XmlTiedArray
221
+ # attr_reader :row_array_cache
222
+ # def initialize(aworksheet,aworksheet_node)
223
+ # @worksheet = aworksheet
224
+ # @row_array_cache = Hash.new()
225
+ # super(aworksheet_node, :xml_items_node_name => 'table-row', :xml_repeated_attribute => xml_repeated_attribute, :object_type=>Row)
226
+ # end
227
+ # def get_row(rowi)
228
+ # if @row_array_cache.has_key?(rowi)
229
+ # return @row_array_cache[rowi]
230
+ # end
231
+ # item = self.get_item(rowi)
232
+ # @row_array_cache[rowi] = if item.nil?
233
+ # if rowi>0 then Rspreadsheet::UninitializedEmptyRow.new(self,rowi) else nil end
234
+ # else
235
+ # if item.repeated?
236
+ # Rspreadsheet::MemberOfRowGroup.new(item.index, item.group.to_rowgroup)
237
+ # else
238
+ # Rspreadsheet::SingleRow.new_from_rowgroup(item.group.to_rowgroup)
239
+ # end
240
+ # end
241
+ # end
242
+ # # aliases
243
+ # def first_unused_row_index; first_unused_index end
244
+ # def worksheet; @worksheet end
245
+ # def detach_of_bound_row_group(index)
246
+ # super(index)
247
+ # return get_row(index)
248
+ # end
249
+ # end
254
250
 
255
251
  # class Row
256
252
  # def initialize
@@ -272,177 +268,147 @@ end
272
268
  # end
273
269
  # end
274
270
 
275
- class RowWithXMLNode < Row
276
- attr_accessor :xmlnode
277
- def style_name=(value); Tools.set_ns_attribute(@xmlnode,'table','style-name',value) end
278
- def get_cell(coli)
279
- Cell.new(self,coli,cellnodes(coli))
280
- end
281
- def nonemptycells
282
- nonemptycellsindexes.collect{ |index| cells(index) }
283
- end
284
- def nonemptycellsindexes
285
- used_col_range.to_a.select do |coli|
286
- cellnode = cellnodes(coli)
287
- !(cellnode.content.nil? or cellnode.content.empty? or cellnode.content =='') or
288
- !cellnode.attributes.to_a.reject{ |attr| attr.name == 'number-columns-repeated'}.empty?
289
- end
290
- end
291
- def cellnodes(coli)
292
- cellnode = nil
293
- while true
294
- curr_coli=1
295
- cellnode = @xmlnode.elements.select{|n| n.name=='table-cell'}.find do |el|
296
- curr_coli += (Tools.get_ns_attribute_value(el, 'table', 'number-columns-repeated') || 1).to_i
297
- curr_coli > coli
298
- end
299
- unless cellnode.nil?
300
- return cellnode
301
- else
302
- add_cell
303
- end
304
- end
305
- end
306
- def add_cell(repeated=1)
307
- cell = Cell.new(self,first_unused_column_index)
308
- Tools.set_ns_attribute(cell.xmlnode,'table','number-columns-repeated',repeated) if repeated>1
309
- @xmlnode << cell.xmlnode
310
- cell
311
- end
312
- def first_unused_column_index
313
- 1 + @xmlnode.elements.select{|n| n.name=='table-cell'}.reduce(0) do |sum, el|
314
- sum + (Tools.get_ns_attribute_value(el, 'table', 'number-columns-repeated') || 1).to_i
315
- end
316
- end
317
- end
318
-
319
- class RowGroup < RowWithXMLNode
320
- @readonly = :yes_always
321
- attr_reader :range
322
- attr_accessor :parent_array, :xmlnode
323
- def initialize(aparent_array,arange,axmlnode=nil)
324
- super()
325
- @parent_array = aparent_array
326
- @range = arange
327
- if axmlnode.nil?
328
- axmlnode = Row.empty_row_node
329
- Tools.set_ns_attribute(axmlnode,'table','number-rows-repeated',range.size) if range.size>1
330
- end
331
- @xmlnode = axmlnode
332
- end
333
- # returns SingleRow if size of range is 1 and nil if it is 0 or less
334
- def normalize
335
- case range.size
336
- when 2..Float::INFINITY then self
337
- when 1 then SingleRow.new_from_rowgroup(self)
338
- else nil
339
- end
340
- end
341
- def repeated; range.size end
342
- def repeated?; range.size>1 end
343
- def range=(arange)
344
- @range=arange
345
- Tools.set_ns_attribute(@xmlnode,'table','number-rows-repeated',range.size, 1)
346
- end
347
- end
271
+ # class RowWithXMLNode < Row
272
+ # attr_accessor :xmlnode
273
+ # def style_name=(value); Tools.set_ns_attribute(@xmlnode,'table','style-name',value) end
274
+ # def get_cell(coli)
275
+ # Cell.new(self,coli,cellnodes(coli))
276
+ # end
277
+ # def nonemptycells
278
+ # nonemptycellsindexes.collect{ |index| cells(index) }
279
+ # end
280
+ # def nonemptycellsindexes
281
+ # used_col_range.to_a.select do |coli|
282
+ # cellnode = cellnodes(coli)
283
+ # !(cellnode.content.nil? or cellnode.content.empty? or cellnode.content =='') or
284
+ # !cellnode.attributes.to_a.reject{ |attr| attr.name == 'number-columns-repeated'}.empty?
285
+ # end
286
+ # end
287
+ # def cellnodes(coli)
288
+ # cellnode = nil
289
+ # while true
290
+ # curr_coli=1
291
+ # cellnode = @xmlnode.elements.select{|n| n.name=='table-cell'}.find do |el|
292
+ # curr_coli += (Tools.get_ns_attribute_value(el, 'table', 'number-columns-repeated') || 1).to_i
293
+ # curr_coli > coli
294
+ # end
295
+ # unless cellnode.nil?
296
+ # return cellnode
297
+ # else
298
+ # add_cell
299
+ # end
300
+ # end
301
+ # end
302
+ # def add_cell(repeated=1)
303
+ # cell = Cell.new(self,first_unused_column_index)
304
+ # Tools.set_ns_attribute(cell.xmlnode,'table','number-columns-repeated',repeated) if repeated>1
305
+ # @xmlnode << cell.xmlnode
306
+ # cell
307
+ # end
308
+ # def first_unused_column_index
309
+ # 1 + @xmlnode.elements.select{|n| n.name=='table-cell'}.reduce(0) do |sum, el|
310
+ # sum + (Tools.get_ns_attribute_value(el, 'table', 'number-columns-repeated') || 1).to_i
311
+ # end
312
+ # end
313
+ # end
348
314
 
349
- class SingleRow < RowWithXMLNode
350
- @readonly = :no
351
- attr_accessor :xmlnode
352
- # index Integer
353
- def initialize(aparent_array,aindex,axmlnode=nil)
354
- super()
355
- @parent_array = aparent_array
356
- @index = aindex
357
- if axmlnode.nil?
358
- axmlnode = Row.empty_row_node
359
- end
360
- @xmlnode = axmlnode
361
- end
362
- def self.new_from_rowgroup(rg)
363
- anode = rg.xmlnode
364
- Tools.remove_ns_attribute(anode,'table','number-rows-repeated')
365
- SingleRow.new(rg.parent_array,rg.range.begin,anode)
366
- end
367
- def normalize; self end
368
- def repeated?; false end
369
- def repeated; 1 end
370
- def range; (@index..@index) end
371
- def detach; self end
372
- def row; @index end
373
- def still_out_of_used_range?; false end
374
- end
315
+ # class RowGroup < RowWithXMLNode
316
+ # @readonly = :yes_always
317
+ # attr_reader :range
318
+ # attr_accessor :parent_array, :xmlnode
319
+ # def initialize(aparent_array,arange,axmlnode=nil)
320
+ # super()
321
+ # @parent_array = aparent_array
322
+ # @range = arange
323
+ # if axmlnode.nil?
324
+ # axmlnode = Row.empty_row_node
325
+ # Tools.set_ns_attribute(axmlnode,'table','number-rows-repeated',range.size) if range.size>1
326
+ # end
327
+ # @xmlnode = axmlnode
328
+ # end
329
+ # # returns SingleRow if size of range is 1 and nil if it is 0 or less
330
+ # def normalize
331
+ # case range.size
332
+ # when 2..Float::INFINITY then self
333
+ # when 1 then SingleRow.new_from_rowgroup(self)
334
+ # else nil
335
+ # end
336
+ # end
337
+ # def repeated; range.size end
338
+ # def repeated?; range.size>1 end
339
+ # def range=(arange)
340
+ # @range=arange
341
+ # Tools.set_ns_attribute(@xmlnode,'table','number-rows-repeated',range.size, 1)
342
+ # end
343
+ # end
375
344
 
376
- class LazyDetachableRow < Row
377
- @readonly = :yes_but_detachable
378
- def initialize(rowi)
379
- super()
380
- @index = rowi.to_i
381
- end
382
- def add_cell; detach.add_cell end
383
- def style_name=(value); detach.style_name=value end
384
- def row; @index end
385
- end
345
+ # class SingleRow < RowWithXMLNode
346
+ # @readonly = :no
347
+ # attr_accessor :xmlnode
348
+ # # index Integer
349
+ # def initialize(aparent_array,aindex,axmlnode=nil)
350
+ # super()
351
+ # @parent_array = aparent_array
352
+ # @index = aindex
353
+ # if axmlnode.nil?
354
+ # axmlnode = Row.empty_row_node
355
+ # end
356
+ # @xmlnode = axmlnode
357
+ # end
358
+ # def self.new_from_rowgroup(rg)
359
+ # anode = rg.xmlnode
360
+ # Tools.remove_ns_attribute(anode,'table','number-rows-repeated')
361
+ # SingleRow.new(rg.parent_array,rg.range.begin,anode)
362
+ # end
363
+ # def normalize; self end
364
+ # def repeated?; false end
365
+ # def repeated; 1 end
366
+ # def range; (@index..@index) end
367
+ # def detach; self end
368
+ # def row; @index end
369
+ # def still_out_of_used_range?; false end
370
+ # end
386
371
 
387
- ## there are not data in this object, they are taken from RowGroup, but this is only readonly
388
- class MemberOfRowGroup < LazyDetachableRow
389
- @readonly = :yes_but_detachable
390
- extend Forwardable
391
- delegate [:repeated?, :repeated, :xmlnode, :parent_array] => :@row_group
392
- attr_accessor :row_group # for dubugging
372
+ # class LazyDetachableRow < Row
373
+ # @readonly = :yes_but_detachable
374
+ # def initialize(rowi)
375
+ # super()
376
+ # @index = rowi.to_i
377
+ # end
378
+ # def add_cell; detach.add_cell end
379
+ # def style_name=(value); detach.style_name=value end
380
+ # def row; @index end
381
+ # end
393
382
 
394
- # @index Integer
395
- # @row_group RepeatedRow
396
- def initialize(arowi,arow_group)
397
- super(arowi)
398
- @row_group = arow_group
399
- raise 'Wrong parameter given - class is '+@row_group.class.to_a unless @row_group.is_a? RowGroup
400
- end
401
- def detach # detaches MemberOfRowGroup from its RowGroup perhaps splitting RowGroup
402
- @row_group.parent_array.detach(@index)
403
- end
404
- def get_cell(coli)
405
- c = Cell.new(self,coli,@row_group.cellnodes(coli))
406
- c.mode = :repeated
407
- c
408
- end
409
- def first_unused_column_index
410
- @row_group.first_unused_column_index
411
- end
412
- def nonemptycells
413
- @row_group.nonemptycellsindexes.collect{ |coli| cells(coli) }
414
- end
415
- end
383
+ # ## there are not data in this object, they are taken from RowGroup, but this is only readonly
384
+ # class MemberOfRowGroup < LazyDetachableRow
385
+ # @readonly = :yes_but_detachable
386
+ # extend Forwardable
387
+ # delegate [:repeated?, :repeated, :xmlnode, :parent_array] => :@row_group
388
+ # attr_accessor :row_group # for dubugging
389
+ #
390
+ # # @index Integer
391
+ # # @row_group RepeatedRow
392
+ # def initialize(arowi,arow_group)
393
+ # super(arowi)
394
+ # @row_group = arow_group
395
+ # raise 'Wrong parameter given - class is '+@row_group.class.to_a unless @row_group.is_a? RowGroup
396
+ # end
397
+ # def detach # detaches MemberOfRowGroup from its RowGroup perhaps splitting RowGroup
398
+ # @row_group.parent_array.detach(@index)
399
+ # end
400
+ # def get_cell(coli)
401
+ # c = Cell.new(self,coli,@row_group.cellnodes(coli))
402
+ # c.mode = :repeated
403
+ # c
404
+ # end
405
+ # def first_unused_column_index
406
+ # @row_group.first_unused_column_index
407
+ # end
408
+ # def nonemptycells
409
+ # @row_group.nonemptycellsindexes.collect{ |coli| cells(coli) }
410
+ # end
411
+ # end
416
412
 
417
- ## this is a row outside the used bounds. the main purpose of this object is to magically synchronize to existing data, once they are created
418
- class UninitializedEmptyRow < LazyDetachableRow
419
- @readonly = :yes_but_detachable
420
- attr_reader :parent_array # debug only
421
- def initialize(aparent_array,arowi)
422
- super(arowi)
423
- @parent_array = aparent_array
424
- end
425
- def get_cell(coli)
426
- if still_out_of_used_range?
427
- Cell.new(self,coli,nil)
428
- else
429
- @parent_array.get_row(@index).cells(coli)
430
- end
431
- end
432
- def normalize
433
- if still_out_of_used_range?
434
- self
435
- else
436
- @parent_array.get_row(@index)
437
- end
438
- end
439
- def detach; @parent_array.detach_item(@index) end
440
- def detach_cell(col)
441
- self.detach.detach_cell(col)
442
- end
443
- def still_out_of_used_range?; @index >= @parent_array.first_unused_row_index end
444
- def xmlnode; Row.empty_row_node end
445
- def first_unused_column_index; 1 end
446
- end
447
413
 
448
414
  end