2 # Copyright (c) 2005 Tilman Sauerbeck (tilman at code-monkey de)
4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions:
12 # The above copyright notice and this permission notice shall be
13 # included in all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 attr_reader :collection, :id, :name, :dragable, :clip,
33 :mouse_events, :repeat_events
35 def initialize(collection, id, name)
36 @collection = collection
39 @name = name.to_str.dup.freeze
40 @type = TYPE_RECTANGLE
42 @repeat_events = false
44 @dragable = Dragable.new(self)
46 @descriptions = Hash.new do |h, k|
47 desc, value = k.split("\0")
50 h[k] = description_class.new(desc, value)
58 def mouse_events=(val)
59 @mouse_events = (val == true)
62 def repeat_events=(val)
63 @repeat_events = (val == true)
68 raise(ArgumentError, "cannot clip part to itself")
69 elsif !part.nil? && part.collection != @collection
70 raise(ArgumentError, "items not in the same collection")
76 def description(name = "default", value = 0.0) # :yields: desc
77 d = @descriptions[desc_key(name, value)]
79 block_given? ? (yield d) : d
92 other_desc = @descriptions.dup
93 other_desc.delete(desc_key("default", 0.0))
95 confine_id = @dragable.confine.nil? ?
96 -1 : @dragable.confine.id
100 "type" => [@type, :char],
101 "effect" => [0, :char],
102 "mouse_events" => [@mouse_events],
103 "repeat_events" => [@repeat_events],
104 "clip_to_id" => [@clip.nil? ? -1 : @clip.id],
105 "default_desc" => [description("default", 0.0)],
106 "other_desc" => [other_desc],
107 "dragable.x" => [@dragable.enabled[0], :char],
108 "dragable.step_x" => [@dragable.step[0]],
109 "dragable.count_x" => [@dragable.count[0]],
110 "dragable.y" => [@dragable.enabled[1], :char],
111 "dragable.step_y" => [@dragable.step[1]],
112 "dragable.count_y" => [@dragable.count[1]],
113 "dragable.events_id" => [-1],
114 "dragable.counfine_id" => [confine_id]} # not a typo!
118 def desc_key(name, value)
119 name + "\0" + value.to_s
123 class SwallowPart < Part
124 def initialize(collection, id, name)
131 class TextPart < Part
132 attr_accessor :effect
134 def initialize(collection, id, name)
142 def description_class
146 def to_eet_properties
147 effect = case @effect
151 when :soft_outline: 3
154 when :outline_shadow: 6
155 when :outline_soft_shadow: 7
157 raise(RedactError, "invalid effect value - #{@effect}")
160 super.merge!({"effect" => [effect, :char]})
164 class ImagePart < Part
165 def initialize(collection, id, name)
172 def description_class
178 attr_reader :enabled, :step, :count, :confine
183 @enabled = [false, false]
191 raise(ArgumentError, "cannot confine part to itself")
192 elsif !part.nil? && part.collection != @part.collection
193 raise(ArgumentError, "items not in the same collection")
201 attr_reader :rel, :to_id, :offset
203 def initialize(rel, offset)
204 @rel = [rel.to_f, rel.to_f]
206 @offset = [offset, offset]
210 @rel = [x.to_f, y.to_f]
221 def set_to(part_x, part_y = part_x)
222 @to_id = [part_x.nil? ? -1 : part_x.id,
223 part_y.nil? ? -1 : part_y.id]
228 attr_reader :rel, :aspect, :step, :visible, :color_class
229 attr_accessor :aspect_preference
231 def initialize(name = "default", value = 0.0)
232 @name = name.to_str.dup.freeze
233 @value = value.freeze
240 @aspect_preference = :none
241 @rel = [Relation.new(0.0, 0), Relation.new(1.0, -1)]
242 @color = [].fill(255, 0..3)
247 unless other.is_a?(Description)
248 raise(ArgumentError, "Cannot inherit from description")
251 prot = ["@name", "@value"]
253 (instance_variables - prot).each do |v|
254 n = other.instance_variable_get(v.intern)
256 instance_variable_set(v.intern, n)
261 @visible = (v == true)
265 @color_class = v.to_str.dup
268 def set_step(x = 0, y = 0)
272 def set_aspect(x = 0.0, y = 0.0)
276 def set_align(x = 0.5, y = 0.5)
294 @color = parse_hex_color(c)
298 def parse_hex_color(c)
299 md = c.match(/^#?(([[:xdigit:]]{2}){1,4})$/)
301 raise(ArgumentError, "Argument is not a hex string")
304 pairs = md.captures.shift.split(/(..)/).delete_if do |item|
308 pairs.push("00") while pairs.length < 3
309 pairs.push("ff") if pairs.length == 3
311 pairs.map { |p| p.hex }
315 "Edje_Part_Description"
318 def to_eet_properties
319 asp_pref = case @aspect_preference
325 raise(RedactError, "invalid aspect preference value - " +
326 @aspect_preference.to_s)
329 {"state.name" => [@name],
330 "state.value" => [@value, :double],
331 "visible" => [@visible],
332 "align.x" => [@align[0], :double],
333 "align.y" => [@align[1], :double],
334 "min.w" => [@min[0]],
335 "min.h" => [@min[1]],
336 "max.w" => [@max[0]],
337 "max.h" => [@max[1]],
338 "step.x" => [@step[0]],
339 "step.y" => [@step[1]],
340 "aspect.min" => [@aspect[0], :double],
341 "aspect.max" => [@aspect[1], :double],
342 "aspect.prefer" => [asp_pref, :char],
343 "rel1.relative_x" => [@rel[0].rel[0], :double],
344 "rel1.relative_y" => [@rel[0].rel[1], :double],
345 "rel1.offset_x" => [@rel[0].offset[0]],
346 "rel1.offset_y" => [@rel[0].offset[1]],
347 "rel1.id_x" => [@rel[0].to_id[0]],
348 "rel1.id_y" => [@rel[0].to_id[1]],
349 "rel2.relative_x" => [@rel[1].rel[0], :double],
350 "rel2.relative_y" => [@rel[1].rel[1], :double],
351 "rel2.offset_x" => [@rel[1].offset[0]],
352 "rel2.offset_y" => [@rel[1].offset[1]],
353 "rel2.id_x" => [@rel[1].to_id[0]],
354 "rel2.id_y" => [@rel[1].to_id[1]],
355 "color_class" => [@color_class],
356 "color.r" => [@color[0], :char],
357 "color.g" => [@color[1], :char],
358 "color.b" => [@color[2], :char],
359 "color.a" => [@color[3], :char],
363 "image.tween_list" => [nil],
368 "border.no_fill" => [false],
369 "fill.smooth" => [true],
370 "fill.pos_rel_x" => [0.0, :double],
371 "fill.pos_abs_x" => [0],
372 "fill.rel_x" => [1.0, :double],
374 "fill.pos_rel_y" => [0.0, :double],
375 "fill.pos_abs_y" => [0],
376 "fill.rel_y" => [1.0, :double],
380 "color2.r" => [0, :char],
381 "color2.g" => [0, :char],
382 "color2.b" => [0, :char],
383 "color2.a" => [255, :char],
384 "color3.r" => [0, :char],
385 "color3.g" => [0, :char],
386 "color3.b" => [0, :char],
387 "color3.a" => [128, :char],
389 "text.text_class" => [""],
392 "text.fit_x" => [false],
393 "text.fit_y" => [false],
396 "text.align.x" => [0.0, :double],
397 "text.align.y" => [0.0, :double],
398 "text.id_source" => [-1],
399 "text.id_text_source" => [-1]}
404 def initialize(image)
416 im2 = find_image(im.to_str.strip)
417 raise(RedactError, "cannot find image - #{im}") if im2.nil?
419 image = EDJE.image_dir.find { |e| e.filename == im2 }
421 image = ImageDirectoryEntry.new(im, im2)
422 EDJE.image_dir << image
425 super(Tween.new(image))
430 [".", OPTIONS.image_dir].each do |d|
431 f2 = File.join(d, file)
432 return Pathname.new(f2).cleanpath.to_s if File.file?(f2)
440 class ImageDescription < Description
441 attr_reader :image, :auto_rel, :tweens, :border_fill_middle,
442 :fill_smooth, :fill_pos_rel, :fill_pos_abs,
445 def initialize(name = "default", value = 0.0)
450 @border = [0, 0, 0, 0]
451 @border_fill_middle = true
454 @fill_pos_rel = [0.0, 0.0]
455 @fill_pos_abs = [0, 0]
456 @fill_rel = [1.0, 1.0]
462 def border_fill_middle=(var)
463 @border_fill_middle = (var == true)
467 im2 = find_image(im.to_str.strip)
468 raise(RedactError, "cannot find image - #{im}") if im2.nil?
470 return if !@image.nil? && im2 == @image.filename
472 @image = EDJE.image_dir.find { |e| e.filename == im2 }
474 @image = ImageDirectoryEntry.new(im, im2)
475 EDJE.image_dir << @image
478 self.auto_rel = @auto_rel
484 if @auto_rel && !@image.nil?
487 @rel[1].set_rel(0.0, 0.0)
488 @rel[1].set_offset(off[0] + @image.image.width - 1,
489 off[1] + @image.image.height - 1)
493 def set_border(l = 0, r = 0, t = 0, b = 0)
494 @border = [l, r, t, b]
498 @fill_smooth = (v == true)
501 def set_fill_pos_rel(x, y)
502 @fill_pos_rel = [x.to_f, y.to_f]
505 def set_fill_pos_abs(x, y)
506 @fill_pos_abs = [x.to_i, y.to_i]
509 def set_fill_rel(x, y)
510 @fill_rel = [x.to_f, y.to_f]
513 def set_fill_abs(x, y)
514 @fill_abs = [x.to_i, y.to_i]
518 def to_eet_properties
520 {"image.id" => [@image.nil? ? -1 : @image.id],
521 "image.tween_list" => [@tweens],
522 "border.l" => [@border[0]],
523 "border.r" => [@border[1]],
524 "border.t" => [@border[2]],
525 "border.b" => [@border[3]],
526 "border.no_fill" => [!@border_fill_middle],
527 "fill.smooth" => [@fill_smooth],
528 "fill.pos_rel_x" => [@fill_pos_rel[0], :double],
529 "fill.pos_abs_x" => [@fill_pos_abs[0]],
530 "fill.rel_x" => [@fill_rel[0], :double],
531 "fill.abs_x" => [@fill_abs[0]],
532 "fill.pos_rel_y" => [@fill_pos_rel[1], :double],
533 "fill.pos_abs_y" => [@fill_pos_abs[1]],
534 "fill.rel_y" => [@fill_rel[1], :double],
535 "fill.abs_y" => [@fill_abs[1]]})
540 [".", OPTIONS.image_dir].each do |d|
541 f2 = File.join(d, file)
542 return Pathname.new(f2).cleanpath.to_s if File.file?(f2)
549 class TextDescription < Description
550 attr_reader :font, :text, :font_size, :text_class
552 def initialize(name = "default", value = 0.0)
555 @outline_color = [0, 0, 0, 255]
556 @shadow_color = [0, 0, 0, 128]
561 @fit = [false, false]
562 @text_min = [false, false]
563 @text_align = [0.5, 0.5]
565 @text_id_text_source = -1
573 @font_size = v.to_int
577 @text_class = v.to_str.dup
580 def set_fit(x = false, y = false)
584 def set_text_min(x = false, y = false)
588 def set_text_align(x = 0.5, y = 0.5)
594 md = f.match(/.*\.ttf$/)
597 raise(RedactError, "cannot find font - #{f}") if f2.nil?
599 found = EDJE.font_dir.find { |font| font.filename == f2 }
601 EDJE.font_dir << FontDirectoryEntry.new(f, f2)
602 @font = EDJE.font_dir.last.alias
611 def outline_color=(c)
612 @outline_color = parse_hex_color(c)
616 @shadow_color = parse_hex_color(c)
620 def to_eet_properties
622 {"color2.r" => [@outline_color[0], :char],
623 "color2.g" => [@outline_color[1], :char],
624 "color2.b" => [@outline_color[2], :char],
625 "color2.a" => [@outline_color[3], :char],
626 "color3.r" => [@shadow_color[0], :char],
627 "color3.g" => [@shadow_color[1], :char],
628 "color3.b" => [@shadow_color[2], :char],
629 "color3.a" => [@shadow_color[3], :char],
630 "text.text" => [@text],
631 "text.text_class" => [@text_class],
632 "text.font" => [@font],
633 "text.size" => [@font_size],
634 "text.fit_x" => [@fit[0]],
635 "text.fit_y" => [@fit[1]],
636 "text.min_x" => [@text_min[0]],
637 "text.min_y" => [@text_min[1]],
638 "text.align.x" => [@text_align[0], :double],
639 "text.align.y" => [@text_align[1], :double],
640 "text.id_source" => [@text_id_source],
641 "text.id_text_source" => [@text_id_text_source]})
646 [".", OPTIONS.font_dir].each do |d|
647 f2 = File.join(d, file)
648 return Pathname.new(f2).cleanpath.to_s if File.file?(f2)