Module: Umbra::EventHandler

Included in:
Form, Widget
Defined in:
lib/umbra/eventhandler.rb

Overview

module containing methods to enable widgets and forms to handle events. Included by form and widget

Defined Under Namespace

Classes: ActionEvent, PropertyChangeEvent, PropertyVetoException

Instance Method Summary collapse

Instance Method Details

#bind_event(event, *xargs, &blk) ⇒ Object

bind_event: bind an event to a block, optional args will also be passed when calling {{{ 2018-04-01 - renamed bind to bind_event



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/umbra/eventhandler.rb', line 22

def bind_event event, *xargs, &blk
  #$log.debug "#{self} called EventHandler BIND #{event}, args:#{xargs} "
  if @_events
    $log.warn "bind: #{self.class} does not support this event: #{event}. #{@_events} " if !event? event
    #raise ArgumentError, "#{self.class} does not support this event: #{event}. #{@_events} " if !event? event
  else
    # it can come here if bind in initial block, since widgets add to @_event after calling super
    # maybe we can change that.
    $log.warn "BIND #{self.class} (#{event})  XXXXX no events defined in @_events. Please do so to avoid bugs and debugging. This will become a fatal error soon."
  end
  @handler ||= {}
  @event_args ||= {}
  @handler[event] ||= []
  @handler[event] << blk
  @event_args[event] ||= []
  @event_args[event] << xargs
end

#event?(eve) ⇒ Boolean

event? : returns boolean depending on whether this widget has registered the given event {{{

Returns:

  • (Boolean)


140
141
142
# File 'lib/umbra/eventhandler.rb', line 140

def event? eve
  @_events.include? eve
end

#fire_handler(event, object) ⇒ Object

fire_handler: Fire all bindings for given event {{{ e.g. fire_handler :ENTER, self The first parameter passed to the calling block is either self, or some action event The second and beyond are any objects you passed when using ‘bind` or `command`. Exceptions are caught here itself, or else they prevent objects from updating, usually the error is in the block sent in by application, not our error. TODO: if an object throws a subclass of VetoException we should not catch it and throw it back for caller to catch and take care of, such as prevent LEAVE or update etc.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/umbra/eventhandler.rb', line 49

def fire_handler event, object
  $log.debug "inside def fire_handler evt:#{event}, o: #{object.class}"
  if !@handler.nil?
    if @_events
      raise ArgumentError, "fire_handler: #{self.class} does not support this event: #{event}. #{@_events} " if !event? event
    else
      $log.debug "fire_handler #{self.class}  XXXXX no events defined in @_events "
    end
    ablk = @handler[event]
    if !ablk.nil?
      aeve = @event_args[event]
      ablk.each_with_index do |blk, ix|
        #$log.debug "#{self} called EventHandler firehander #{@name}, #{event}, obj: #{object},args: #{aeve[ix]}"
        # self prints the entire content of list or table!
        $log.debug "EVENTHANDLER: #{self} called EventHandler firehander #{@name}, #{event}"
        begin
          blk.call object,  *aeve[ix]
        rescue FieldValidationException => fve
          # added 2011-09-26 1.3.0 so a user raised exception on LEAVE
          # keeps cursor in same field.
          raise fve
        rescue PropertyVetoException => pve
          # added 2011-09-26 1.3.0 so a user raised exception on LEAVE
          # keeps cursor in same field.
          raise pve
        rescue => ex
          ## some don't have name
          $log.error "======= Error ERROR in block event #{self}:  #{event}"
          $log.error ex
          $log.error(ex.backtrace.join("\n")) 
          alert ex.to_s
          FFI::NCurses.beep    # doesn't do anything, maybe switched off in preferences
        end
      end
    else
      # there is no block for this key/event
      # we must behave exactly as processkey
      # NOTE this is too risky since then buttons and radio buttons
      # that don't have any command don;t update,so removing 2011-12-2 
      #return :UNHANDLED
      return :NO_BLOCK
    end # if
  else
    # there is no handler
    # I've done this since list traps ENTER but rarely uses it.
    # For buttons default, we'd like to trap ENTER even when focus is elsewhere
    # we must behave exactly as processkey
    # NOTE this is too risky since then buttons and radio buttons
    # that don't have any command don;t update,so removing 2011-12-2 
    #return :UNHANDLED
    # If caller wants, can return UNHANDLED such as list and ENTER.
    return :NO_BLOCK
  end # if
end

#fire_property_change(text, oldvalue, newvalue) ⇒ Object

}}}



104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/umbra/eventhandler.rb', line 104

def fire_property_change text, oldvalue, newvalue
  # canis returns if oldvalue is nil, but if object created with nil and later
  # prop is set then we need a handler fired.
  return if @_object_created.nil? 
  $log.debug " FPC #{self}: #{text} "
  if @pce.nil?
    @pce = PropertyChangeEvent.new(self, text, oldvalue, newvalue)
  else
    @pce.set( self, text, oldvalue, newvalue)
  end
  @repaint_required = true 
  fire_handler :PROPERTY_CHANGE, @pce
end

#register_events(eves) ⇒ Object

register_events: widgets may register their events prior to calling super {{{ This ensures that caller programs don’t use wrong event names.



8
9
10
11
12
13
14
15
16
17
18
# File 'lib/umbra/eventhandler.rb', line 8

def register_events eves
  @_events ||= []
  case eves
  when Array
    @_events.push(*eves)
  when Symbol
    @_events << eves
  else
    raise ArgumentError "register_events: Don't know how to handle #{eves.class}"
  end
end