OSDN Git Service

1c81e698e309be6903b28c2bfbac14afa7b975bf
[pettanr/pettanr.git] / app / models / panel.rb
1 #コマ
2 class Panel < Peta::Content
3   load_manifest
4   belongs_to :author
5   has_many :scroll_panels
6   has_many :sheet_panels
7   has_many :panel_pictures, :dependent => :destroy
8   has_many :speech_balloons, :dependent => :destroy
9   has_many :ground_pictures, :dependent => :destroy
10   has_many :ground_colors, :dependent => :destroy
11   accepts_nested_attributes_for :panel_pictures, :allow_destroy => true
12   accepts_nested_attributes_for :speech_balloons, :allow_destroy => true
13   accepts_nested_attributes_for :ground_pictures, :allow_destroy => true
14   accepts_nested_attributes_for :ground_colors, :allow_destroy => true
15
16   validates :width, :presence => true, :numericality => true, :natural_number => true
17   validates :height, :presence => true, :numericality => true, :natural_number => true
18   validates :border, :presence => true, :numericality => {:greater_than_or_equal_to => 0}
19   validates :author_id, :presence => true, :numericality => true, :existence => {:both => false}
20   validates :publish, :presence => true, :numericality => true
21   
22   def self.valid_encode_columns
23     super + ['caption']
24   end
25   
26   def self.each_element_class_names
27     Manifest.manifest.system_resources.elements.each do |k, n|
28       yield k
29     end
30   end
31   
32   def self.class_name_to_class k
33     Object.const_get k
34   end
35   
36   def self.each_element_classes
37     self.each_element_class_names do |k|
38       e = self.class_name_to_class k
39       yield e
40     end
41   end
42   
43   def elements_by_class_name class_name
44     self.__send__ class_name.tableize
45   end
46   
47   def supply_default
48     self.border = 2
49     self.publish = 0
50   end
51   
52   def overwrite operators
53     return false unless operators.author
54     self.author_id = operators.author.id
55   end
56   
57   def visible? operators
58     return true if super
59     return true if self.new_record?
60     self.publish?
61   end
62   
63   def usable? operators
64     self.visible? operators
65   end
66   
67   def publish?
68     self.publish > 0
69   end
70   
71   # ground_picture element template 
72   def style_wh
73     {
74       'width' => self.width.to_s + 'px', 'height' => self.height.to_s + 'px'
75     }
76   end
77   
78   def tag_id c = nil
79     'panel' + self.tag_panel_id + c.to_s
80   end
81   
82   def tag_panel_id
83     self.new_record? ? '0' : self.id.to_s
84   end
85   
86   def field_tag_id f
87     self.tag_id + f.to_s
88   end
89   
90   def tag_attributes column = nil, opt = {}
91     {
92       :id => self.field_tag_id(column), :panel_id => self.tag_panel_id
93     }.merge(opt)
94   end
95   
96   def select_tag_attributes(selected, column, opt = {})
97     [
98       {:html => {:selected => selected}}, 
99       self.field_tag_attributes(column, opt)
100     ]
101   end
102   
103   def field_tag_attributes column, no_attr, opt = {}
104     self.tag_attributes(column).merge(
105       {:column => column}
106     ).merge(opt)
107   end
108   
109   def tag_attr column = nil, opt = {}
110     self.tag_attributes(column, opt).to_attr
111   end
112   
113   def field_tag_attr column, no_attr, opt = {}
114     self.field_tag_attributes(column, no_attr, opt).to_attr
115   end
116   
117     def render_count
118       @render_count ||= 1
119     end
120     
121     def rendered
122       @render_count = render_count + 1
123     end
124     
125   def self.list_where
126     'panels.publish > 0'
127   end
128   
129   def self.list_order
130     'panels.updated_at desc'
131   end
132   
133   def self.list_opt
134     r = {
135       :author => {}
136     }
137     self.each_element_classes do |e|
138       r.merge!(e.list_opt_for_panel)
139     end
140     r
141   end
142   
143   def self.show_opt
144     r = {
145       :author => {}
146     }
147     self.each_element_classes do |e|
148       r.merge!(e.show_opt_for_panel)
149     end
150     {:include => r}
151   end
152   
153   def parts_element
154     r = []
155     self.class.each_element_class_names do |k|
156       r += (self.elements_by_class_name(k) || [])
157     end
158     r
159   end
160   
161   def zorderd_elements
162     res = []
163     self.parts_element.each do |e|
164       res[e.z-1] = e
165     end
166     res
167   end
168   
169   def panel_elements
170     res = []
171     self.parts_element.each do |e|
172       res[e.t] = e
173     end
174     res
175   end
176   
177   def elements
178     self.panel_elements.map {|e|
179       #(-_-;)<... kore wa hidoi
180       JSON.parse e.to_json({:include => e.class.json_opt_for_panel})
181     }
182   end
183   
184   def panel_elements_as_json
185     self.to_json({:include => {:author => {}}, :methods => :elements})
186   end
187   
188   def self.list_as_json_text ary
189     '[' + ary.map {|i| i.panel_elements_as_json }.join(',') + ']'
190   end
191   
192   def new_t
193     self.panel_elements.size
194   end
195   
196   def new_z
197     self.panel_elements.size + 1
198   end
199   
200   def scenario
201     panel_elements.map { |e|
202       e.scenario
203     }.join
204   end
205   
206   def plain_scenario
207     panel_elements.map { |e|
208       e.plain_scenario
209     }.join
210   end
211   
212   def licensed_pictures
213     r = {}
214     self.panel_elements.each do |elm|
215       next unless elm.class.has_picture?
216       r[elm.picture_id] = elm.picture unless r[elm.picture_id]
217     end
218     r
219   end
220   
221   def self.visible_count
222     Panel.count
223   end
224   
225   def self.collect_element_value elements, name
226     elements.map {|e|
227       e.map {|o|
228         if o['_destroy'] or o[:_destroy]
229           nil
230         else
231           o[name]
232         end
233       }.compact
234     }.flatten
235   end
236   
237   def self.validate_serial ary, offset = 0
238     i = offset
239     ary.compact.sort.each do |n|
240       break false unless n == i
241       i += 1
242     end
243     ary.compact.size == i - offset
244   end
245   
246   def self.validate_element_serial elements, name, offset = 0
247     Panel.validate_serial(Panel.collect_element_value(elements, name), offset)
248   end
249   
250   def self.validate_elements_serial c
251     c.map {|conf|
252       Panel.validate_element_serial(conf[:elements], conf[:name], conf[:offset]) ? nil : false
253     }.compact.empty?
254   end
255   
256   def validate_serial_list
257     l = []
258     self.class.each_element_class_names do |k|
259       l << self.elements_by_class_name(k)
260     end
261     [
262       {:elements => l, :name => :t, :offset => 0}, 
263       {:elements => l, :name => :z, :offset => 1}
264     ]
265   end
266   def validate_child
267 #    r1 = Panel.validate_elements_id validate_id_list
268     Panel.validate_elements_serial validate_serial_list
269   end
270   
271   def boost
272     @new_element_index = 0
273     self.panel_elements.each do |elm|
274       if elm.new_record?
275         elm.new_index = @new_element_index
276         @new_element_index += 1
277       end
278     end
279   end 
280   
281   def store attr, operators
282     if attr == false
283       self.errors.add :base, I18n.t('errors.invalid_json')
284       return false
285     end
286     self.attributes = attr
287     self.overwrite operators
288     res = false
289     Panel.transaction do
290       self.panel_elements.each do |elm|
291         elm.new_panel = self
292         elm.boost
293       end
294 #self.publish = nil
295       res = self.save
296       unless validate_child
297         res = false
298         self.errors.add :base, I18n.t('errors.invalid_t')
299         raise ActiveRecord::Rollback
300       end
301     end
302     res
303   end
304   
305   def remove_element target, operators
306     ct = target.t
307     cz = target.z
308     panel_attributes = {}
309     self.panel_elements.each do |elm|
310       attr = elm.attributes
311       if elm == target
312         attr['_destroy'] = true
313       end
314       if elm.t > ct
315         attr['t']  -= 1 
316       end
317       if elm.z > cz
318         attr['z']  -= 1 
319       end
320       panel_attributes[elm.class.to_s.tableize + '_attributes'] ||= {}
321       panel_attributes[elm.class.to_s.tableize + '_attributes'][elm.id] = attr
322     end
323     self.store(panel_attributes, operators)
324   end
325   
326   def destroy_with_elements
327     res = false
328     Panel.transaction do
329       self.parts_element.each do |element|
330         raise ActiveRecord::Rollback unless element.destroy
331       end
332       raise ActiveRecord::Rollback unless self.destroy
333       res = true
334     end
335     res
336   end
337   
338   def copy
339     attr = self.copy_attributes
340     Panel.each_element_class_names do |n|
341       attr.merge! Panel.class_name_to_class(n).panelize(self.elements_by_class_name(n).map {|elm|  elm.copy_attributes})
342     end
343     attr
344   end
345   
346   def copy_attributes
347     r = self.attributes
348     r.delete 'id'
349     r.delete 'author_id'
350     r.delete 'created_at'
351     r.delete 'updated_at'
352     r
353   end
354   
355   def self.panelize panel
356     attr = panel.attributes
357     attr.delete 'id'
358     attr
359   end
360   
361   
362 =begin
363   def self.validate_id ary, pid
364     ary.map {|v|
365       if pid
366         (v == pid or v == nil) ? nil : false
367       else
368         v ? false : nil
369       end
370     }.compact.empty?
371   end
372   
373   def self.validate_element_id elements, name, pid
374     Panel.validate_id(Panel.collect_element_value(elements, name), pid)
375   end
376   
377   def self.validate_elements_id c
378     c.map {|conf|
379       Panel.validate_element_id(conf[:elements], conf[:name], conf[:parent_id]) ? nil : false
380     }.compact.empty?
381   end
382   
383   def validate_id_list
384     r = self.speech_balloons.map {|sb|
385       {:elements => [sb.speeches, sb.balloons], :name => :speech_balloon_id, :parent_id => sb.id}
386     }
387     r.unshift({:elements => [self.panel_pictures, self.speech_balloons], :name => :panel_id, :parent_id => self.id})
388     r
389   end
390 =end
391   
392 end