123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- module Zori
- # A widget may have sub-widgets
- module Widget
- include Graphic
- include State
-
- # Position of the widget.
- attr_reader :x
- attr_reader :y
- attr_reader :z
- # Dimensions of the widget.
- attr_reader :w
- attr_reader :h
-
- # Style of the widget
- attr_reader :style
-
- # Capabilities of the widget
- attr_reader :can
-
- # State of the widget
- attr_reader :state
- # Parent of a widget
- attr_accessor :parent
-
- def initialize(params={}, &block)
- super(params, &block)
- @action = block
- @components = []
- @x = params[:x] || 0
- @y = params[:y] || 0
- @w = params[:w] || 640
- @h = params[:h] || 480
- self.init_graph
- @z = params[:z] || 0
- @style = Zori::Style.default.dup
- # deep copy the default style
- @can = Zori::Capability.new
- @state = :active
- @parent = nil
- # Widget is active
- # @action = action
- end
- # Helper dimension, equal to x + w
- def left
- @x + @w
- end
- # Helper dimension, equal to y + h
- def bottom
- @y + @h
- end
- # Called when an event comes in from the Eruta engine.
- # Tries every component of this widget in order and stops if a truthy
- # value is returned. Finally calls handle_event on self in case
- # no component handles the event.
- def on_event(*data)
- return false if disabled? || hidden?
- if @components
- @components.each do | component |
- res = component.on_event(*data)
- return res if res
- end
- end
- res = handle_event(*data)
- end
-
- # The widget's own event handler will try to call a method named on_eventname
- def handle_event(*args)
- type = args.shift
- return false unless type
- method = "on_#{type}".to_sym
- # Try direct handler call.
- if self.respond_to?(method)
- return self.send(method, *args)
- else
- return nil
- end
- end
- # Adds a component to this widget
- # Will try to send a on_component event with
- def <<(component)
- component.parent = self
- @components << component
- self.on_event(:component, component)
- end
-
- # Checks if the coordinates are inside the main rectange of the widget.
- def inside?(x, y)
- return (x >= @x) && (x <= (@x + w)) && (y >= @y) && (y <= (@y + h))
- end
-
-
- # Makes the widget fit all direct children with the given margins
- def fit_children(margin_x = 20, margin_y = 20)
- min_x, min_y, = 640, 480 # XXX get this from somewhere...
- max_y, max_x = 0, 0
- @components.each do | child |
- min_x = child.x if child.x < min_x
- min_y = child.y if child.y < min_y
- max_x = child.left if child.left > max_x
- max_y = child.bottom if child.bottom > max_y
- end
- @x = min_x - margin_x
- @y = min_y - margin_y
- @w = max_x - min_x + margin_x * 2
- @h = max_y - min_y + margin_y * 2
- on_resize
- end
-
- # Adds a menu to this widget as a child widget
- def make_menu(x, y, w, h, heading, &block)
- menu = Zori::Menu.new(:x => x, :y => y, :w => w, :h => h, :heading => heading, &block)
- self << menu
- return menu
- end
-
- # Adds a button to this widget as a child widget
- def make_button(x, y, w, h, heading, &block)
- button = Zori::Button.new(:x => x, :y => y, :w => w, :h => h, :heading => heading, &block)
- self << button
- return button
- end
- # Adds a longtext to this widget as a child widget
- def make_longtext(x, y, w, h, text, &block)
- lt = Zori::LongText.new(:x => x, :y => y, :w => w, :h => h, :text => text,
- &block)
- self << lt
- return lt
- end
- # Triggers the widget and call its action block
- def trigger
- return @action.call if @action
- return nil
- end
-
- end
- end
|