X-Git-Url: http://git.code-monkey.de/?p=embrace.git;a=blobdiff_plain;f=bin%2Fembrace;h=79d57c892ae374d3498066c19d2e5072e936c11e;hp=66915743cf3aa4a654f03a07c82896cbe4097735;hb=c0b425d6a1cd0e286d58eca4c1ed415315bd48d2;hpb=82f2544b1ba0d064c5e9b77795c0a34efe37a37e diff --git a/bin/embrace b/bin/embrace index 6691574..79d57c8 100755 --- a/bin/embrace +++ b/bin/embrace @@ -27,29 +27,9 @@ require "embrace/imap" PKG_NAME = "embrace" DATADIR = "/usr/local/share/#{PKG_NAME}/" -class Evas::EvasObject - def move_relative(obj, x, y) - # FIXME investigate whether there's an easier way - move(*obj.geometry[0..1].zip([x, y]).map { |(a, b)| a + b }) - end - - def center(obj) - a = geometry - b = obj.geometry - - move_relative(obj, (b[2] / 2) - (a[2] / 2), - (b[3] / 2) - (a[3] / 2)) - end - - def alpha=(alpha) - set_color(*(get_color[0..-2] << alpha)) - end -end - module Embrace VERSION = "0.0.1" ICON_FILE = DATADIR + "l33t_MAI_envelope.png" - MAX_ICONS = 11 class ZeroToOneAnimator < Ecore::Animator def initialize(duration) @@ -81,11 +61,22 @@ module Embrace # an animator that runs for the specified number of seconds, # and yields values between 0 and 255 class AlphaAnimator < ZeroToOneAnimator - def initialize(duration, *objects) + def initialize(duration, object) super(duration) do |v| - objects.each { |o| o.alpha = (255 * v).to_i } + a = compute_alpha(v) + object.set_color(a, a, a, a) end end + + def compute_alpha(v) + (255 * v).to_i + end + end + + class InverseAlphaAnimator < AlphaAnimator + def compute_alpha(v) + super((1.0 - v).abs) + end end class MoveAnimator < ZeroToOneAnimator @@ -105,11 +96,23 @@ module Embrace end class MailboxIcon < Evas::Smart + class FadeOutFinishedEvent < Ecore::Event + attr_reader :icon + + def initialize(icon) + super() + + @icon = icon + end + end + attr_accessor :slot def initialize(evas, label) super(evas) + self.name = label + @slot = nil @alpha_anim = nil @@ -117,40 +120,53 @@ module Embrace @label = Evas::Text.new(evas) @objects = [@img, @label] + @objects.each { |o| add_member(o) } - @img.set_color(255, 255, 255, 0) - @label.set_color(255, 255, 255, 0) - @label.set_color(255, 0, 0, 0) + set_color(0, 0, 0, 0) @img.set_file(ICON_FILE) @img.set_fill(0, 0, *@img.get_size) - @label.text = label + @label.text = name @label.set_font("VeraBd", 10) + a = @label.geometry + b = *@img.get_size + + @label_offset_x = (b[0] / 2) - (a[2] / 2) + @label_offset_y = (b[1] / 2) - (a[3] / 2) + resize(*@img.get_size) end - def label - @label.text + def fade_in + show + + @alpha_anim ||= AlphaAnimator.new(2, self) + @alpha_anim.on_finished { @alpha_anim = nil } + end + + def fade_out + @alpha_anim ||= InverseAlphaAnimator.new(2, self) + @alpha_anim.on_finished do + @alpha_anim = nil + FadeOutFinishedEvent.raise(self) + end end # smart callbacks - def on_show + def smart_show @objects.each { |o| o.show } - - @alpha_anim ||= AlphaAnimator.new(2, @img, @label) - @alpha_anim.on_finished { @alpha_anim = nil } end - def on_hide + def smart_hide @objects.each { |o| o.hide } @alpha_anim && @alpha_anim.delete @alpha_anim = nil end - def on_delete + def smart_delete @objects.each { |o| o.delete } @objects.clear @@ -159,37 +175,22 @@ module Embrace @img = @label = @alpha_anim = nil end - def on_move(x, y) - @objects.each { |o| o.move(x, y) } + def smart_move(x, y) + @img.move(x, y) - @label.center(self) + # center the label on the image + @label.move(x + @label_offset_x, + y + @label_offset_y) end - def on_resize(w, h) + def smart_resize(w, h) @img.resize(w, h) end - end - - class FixedSizeArray < Array - def initialize(siz) - super - end - def each - super { |item| yield item unless item.nil? } + def smart_color_set(r, g, b, a) + @img.set_color(r, g, b, a) + @label.set_color(r, 0, 0, a) end - - def delete_at(i) - self[i] = nil - end - - undef :push - undef :<< - undef :unshift - - undef :pop - undef :shift - undef :delete end class Container < Evas::Smart @@ -197,33 +198,46 @@ module Embrace class ContainerFullError < ContainerError; end class ContainerLockedError < ContainerError; end - include Enumerable - def initialize(evas) super @bg = Evas::Rectangle.new(evas) - @bg.set_color(0, 0, 0, 255) + @bg.set_color(0, 0, 0, 8) + + add_member(@bg) - @icons = FixedSizeArray.new(MAX_ICONS) - @about_to_add = [] + @icons = [] @animators = [] - @lock_count = 0 + @about_to_add = 0 + @add_lock_count = 0 + + @handlers = [ + Ecore::EventHandler.new(MailboxIcon::FadeOutFinishedEvent, + &method(:on_icon_fade_out_finished)) + ] + end + + def can_add? + !slots_left.zero? && @add_lock_count.zero? end - def each - @icons.each { |i| yield i unless i.nil? } + def can_delete? + @about_to_add.zero? && @add_lock_count.zero? end def <<(i) Kernel.raise(ContainerFullError) if slots_left.zero? - Kernel.raise(ContainerLockedError) if @lock_count > 0 + Kernel.raise(ContainerLockedError) unless @add_lock_count.zero? + + geo = geometry + + i.move(geo[0], + geo[1] + geo[3] % Main.instance.icon_height) - i.move_relative(self, 0, 0) i.slot = next_slot i.clip = self - i.show + i.fade_in # check whether we need to need to move this icon if slots_left == 1 @@ -233,7 +247,7 @@ module Embrace movement = Main.instance.icon_height * (slots_left - 1) - @about_to_add << i + @about_to_add += 1 move_time = 0.25 * slots_left @animators << MoveAnimator.new(move_time, movement, i) @@ -242,15 +256,11 @@ module Embrace @animators.delete(ani) @icons[i.slot] = i - # FIXME check whether we can always shift the array instead - #puts "really added #{i.label} now (slot #{i.slot})" - @about_to_add.delete(i) + @about_to_add -= 1 end end def delete(icon) - # icons that are placed above the one that's deleted need - # to be moved i = @icons.index(icon) return (block_given? ? yield : nil) if i.nil? @@ -258,54 +268,67 @@ module Embrace end def delete_at(i) - @icons[i].delete + Kernel.raise(ContainerLockedError) unless @about_to_add.zero? + Kernel.raise(ContainerLockedError) unless @add_lock_count.zero? + + @add_lock_count += 1 + @icons[i].fade_out + end + + def on_icon_fade_out_finished(ev) + i = @icons.index(ev.icon) + ev.icon.delete @icons.delete_at(i) - ar = @icons[i..-1].reject { |i| i.nil? } - return if ar.nil? + # icons that are placed above the one that's deleted need + # to be moved. check whether are there any first + if i == @icons.length + @add_lock_count -= 1 + return + end - @lock_count += 1 + ar = @icons[i..-1] @animators << MoveAnimator.new(2, Main.instance.icon_height, *ar) @animators.last.on_finished do |ani| @animators.delete(ani) - @lock_count -= 1 + @add_lock_count -= 1 end end - def length - @icons.nitems - end - # smart callbacks - def on_show + def smart_show @bg.show end - def on_hide + def smart_hide @bg.hide end - def on_delete + def smart_delete @bg.delete @bg = nil end - def on_move(x, y) + def smart_move(x, y) @bg.move(x, y) end - def on_resize(w, h) + def smart_resize(w, h) @bg.resize(w, h) end private + def max_icons + geometry.pop / Main.instance.icon_height + end + def slots_left - MAX_ICONS - @icons.nitems - @about_to_add.length + max_icons - @icons.nitems - @about_to_add end def next_slot - @icons.nitems + @about_to_add.length + @icons.nitems + @about_to_add end end @@ -317,19 +340,28 @@ module Embrace def initialize super + self.has_alpha = true self.title = "Embrace" self.borderless = true @icon_dim = IO.read(ICON_FILE, 8, 16).unpack("NN") - self.on_resize { @container.resize(*geometry[2, 3]) } + on_resize { @container.resize(*geometry[2, 3]) } @container = Container.new(evas) @container.move(0, 0) @container.layer = -1 @container.show - size = [@icon_dim.first, icon_height * MAX_ICONS] + size = [@icon_dim.first] + + arg = ARGV.shift + if arg.nil? + size << icon_height * 11 + else + size << arg.to_i + end + resize(*size) set_size_min(*size) set_size_max(*size) @@ -360,10 +392,6 @@ module Embrace end private - def add_icon(name) - @container << MailboxIcon.new(evas, name) - end - def on_timer return unless @server.nil? @@ -380,24 +408,12 @@ module Embrace lbl = md.captures.first end - found = @container.find { |i| i.label == lbl } - - begin - if ev.count.zero? - unless found.nil? - #puts "removing icon #{lbl}" - @container.delete(found) - else - #puts "count == 0, but icon not found (#{lbl})" - end - elsif found.nil? - #puts "adding icon #{lbl}" - add_icon(lbl) - else - #puts "count > 0, but already there (#{lbl})" - end - rescue Exception => e - puts e.message + found = evas.find_object(lbl) + + if ev.count.zero? && !found.nil? && @container.can_delete? + @container.delete(found) + elsif !ev.count.zero? && found.nil? && @container.can_add? + @container << MailboxIcon.new(evas, lbl) end false