Neurogami-jimpanzee 1.0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,69 @@
1
+ require "monkeybars/task_processor"
2
+
3
+ module Monkeybars
4
+ class Debug
5
+ extend Monkeybars::TaskProcessor
6
+
7
+ # Reads in ARGV, and enables various Monkeybars specific debugging capabilities
8
+ # TODO: Restore args not used
9
+ def self.enable_on_debugging_args
10
+ puts "inspecting args"
11
+ puts ARGV
12
+ until ARGV.empty?
13
+ arg = ARGV.pop
14
+ case arg
15
+ when '--debug-server'
16
+ port = ARGV.pop
17
+ begin
18
+ port.to_i
19
+ rescue
20
+ port = 4848
21
+ # put the arg back
22
+ ARGV.unshift port
23
+ end
24
+ start_server port
25
+ when '--record-edt'
26
+ puts "recording EDT"
27
+ record_edt
28
+ end
29
+ end
30
+ end
31
+
32
+ def self.record_edt
33
+ listener = lambda do |event|
34
+ puts "found event #{event}"
35
+ end
36
+ Java::java::awt::Toolkit.default_toolkit.addAWTEventListener listener, 0xFFFFFFFFFFFF
37
+ end
38
+ # Use --debug-server to enable
39
+ # allows user to telnet in and send code to be evaled. Results are returned.
40
+ def self.start_server(port=4848)
41
+ Thread.new do
42
+ require 'socket'
43
+ server = TCPServer.new(port)
44
+ begin
45
+ socket = server.accept_nonblock
46
+ rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EINTR
47
+ IO.select([server])
48
+ retry
49
+ end
50
+
51
+ puts "connected!"
52
+ until socket.closed?
53
+ begin
54
+ line = socket.readline
55
+ puts "evaling #{line}"
56
+ result = on_edt { eval line }
57
+ puts "returning result #{result}"
58
+ socket.write "#{result}\n"
59
+ rescue => e
60
+ puts "error, returning error #{e}"
61
+ socket.write "#{e}\n"
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ enable_on_debugging_args
68
+ end
69
+ end
@@ -0,0 +1,89 @@
1
+ require 'monkeybars/inflector'
2
+
3
+ include_class 'javax.swing.SwingUtilities'
4
+
5
+ module Monkeybars
6
+ # This class is primarily used internally for setting up a handler for window
7
+ # close events although any of the WindowAdapter methods can be set. To instantiate
8
+ # a new MonkeybarsWindowAdapter, pass in a hash of method name symbols and method
9
+ # objects. The method names must be the various methods from the
10
+ # java.awt.event.WindowListener interface.
11
+ #
12
+ # For example:
13
+ #
14
+ # def handle_window_closing(event)
15
+ # puts "the window is closing"
16
+ # end
17
+ #
18
+ # handler = MonkeybarsWindowAdapter.new(:windowClosing => method(handle_window_closing))
19
+ class MonkeybarsWindowAdapter #:nodoc:
20
+ def initialize(methods)
21
+ super()
22
+ raise ArgumentError if methods.empty?
23
+ methods.each { |method, proc| raise ArgumentError.new("Only window and internalFrame events can be used to create a MonkeybarsWindowAdapter") unless (/^(window|internalFrame)/ =~ method.to_s) and (proc.respond_to? :to_proc) }
24
+ @methods = methods
25
+ end
26
+
27
+ def method_missing(method, *args, &blk)
28
+ if /^(window|internalFrame)/ =~ method.to_s
29
+ @methods[method].call(*args) if @methods[method]
30
+ else
31
+ super
32
+ end
33
+ end
34
+ end
35
+
36
+
37
+ # This module is used internally by the various XYZHandler classes as the
38
+ # recipent of events. It dispatches the event handling to the controller's
39
+ # handle_event method.
40
+ module BaseHandler
41
+ def method_missing(method, *args, &block)
42
+ @callback.handle_event(@component_name, method.underscore, args[0])
43
+ end
44
+ end
45
+
46
+ module Handlers
47
+ # TODO: add bean types like vetoable change, property change, etc.
48
+ BEAN_TYPES = ["PropertyChange"]
49
+ AWT_TYPES = ["Action","Adjustment","AWTEvent","Component","Container","Focus",
50
+ "HierarchyBounds","Hierarchy","InputMethod","Item","Key","Mouse",
51
+ "MouseMotion","MouseWheel","Text", "WindowFocus","Window","WindowState"]
52
+ SWING_TYPES = ["Ancestor", "Caret", "CellEditor", "Change", "Document",
53
+ "Hyperlink", "InternalFrame", "ListData", "ListSelection",
54
+ "MenuDragMouse", "MenuKey", "Menu", "MouseInput", "PopupMenu",
55
+ "TableColumnModel", "TableModel", "TreeExpansion", "TreeModel",
56
+ "TreeSelection", "TreeWillExpand", "UndoableEdit"]
57
+ ALL_EVENT_NAMES = []
58
+ EVENT_NAMES_BY_TYPE = Hash.new{|h,k| h[k] = []}
59
+ end
60
+ end
61
+
62
+ {"java.awt.event" => Monkeybars::Handlers::AWT_TYPES, "javax.swing.event" => Monkeybars::Handlers::SWING_TYPES, "java.beans" => Monkeybars::Handlers::BEAN_TYPES}.each do |java_package, types|
63
+ types.each do |type|
64
+ eval <<-ENDL
65
+ module Monkeybars
66
+ class #{type}Handler
67
+ def initialize(callback, component_name)
68
+ @callback = callback
69
+ @component_name = component_name
70
+ end
71
+
72
+ def type
73
+ "#{type}"
74
+ end
75
+
76
+ include Monkeybars::BaseHandler
77
+ include #{java_package}.#{type}Listener
78
+ end
79
+ end
80
+ ENDL
81
+
82
+ interface = eval "#{java_package}.#{type}Listener"
83
+ interface.java_class.java_instance_methods.each do |method|
84
+ Monkeybars::Handlers::ALL_EVENT_NAMES << method.name.underscore
85
+ Monkeybars::Handlers::EVENT_NAMES_BY_TYPE[type] << method.name.underscore
86
+ end
87
+ Monkeybars::Handlers::ALL_EVENT_NAMES.uniq!
88
+ end
89
+ end
@@ -0,0 +1,251 @@
1
+ require 'monkeybars/exceptions'
2
+ module Monkeybars
3
+ module EventHandlerRegistrationAndDispatchMixin
4
+ def self.included(target)
5
+ target.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ @@event_handler_procs ||= {}
10
+ def event_handler_procs
11
+ @@event_handler_procs[self] ||= Hash.new {|hash, key| hash[key] = []}
12
+ end
13
+
14
+ @@handlers ||= {}
15
+ def handlers
16
+ @@handlers[self] ||= []
17
+ end
18
+
19
+ # Declares which components you want events to be generated for. add_listener
20
+ # takes a hash of the form :type => type, :components => [components for events]
21
+ # All AWT and Swing listener types are supported. See Monkeybars::Handlers for
22
+ # the full list.
23
+ #
24
+ # The array of components should be strings or symbols with the exact naming of the
25
+ # component in the Java class declared in the view. As an example, if you have a JFrame
26
+ # with a text area named infoTextField that you wanted to receive key events for, perhaps
27
+ # to filter certain key input or to enable an auto-completion feature you could use:
28
+ #
29
+ # add_listener :type => :key, :components => [:infoTextField]
30
+ #
31
+ # To handle the event you would then need to implement a method named
32
+ # <component>_<event> which in this case would be info_text_field_key_pressed,
33
+ # info_text_field_key_released or info_text_field_key_typed.
34
+ #
35
+ # If you have a single component you can omit the array and pass a single string or symbol.
36
+ #
37
+ # add_listener :type => :key, :components => :infoTextField
38
+ #
39
+ # You will run into errors if your component is a nested name, for example
40
+ #
41
+ # add_listener :type => :document, :components => "infoTextField.document"
42
+ #
43
+ # because when the event is generated and a handler is attempted to be located,
44
+ # the name infoTextField.document doesn't map well to a method. To resolve this,
45
+ # the component name can be a hash, the key being the component name and the value
46
+ # being the desired callback name.
47
+ #
48
+ # add_listener :type => :document, :components => {"infoTextField.document" => "info_text_field"}
49
+ #
50
+ # This will cause the info_text_field_action_performed method to be called when
51
+ # the action performed event is generated by infoTextField.document.
52
+ #
53
+ # If you want to add a listener to the view itself (JFrame, JDialog, etc.)
54
+ # then you can use :java_window as the component
55
+ #
56
+ # add_listener :type => :window, :components => [:java_window]
57
+ #
58
+ # If it is not possible to declare a method, or it is desirable to do so dynamically
59
+ # (even from outside the class), you can use the define_handler method.
60
+ #
61
+ # If you wish to override the default event handling behavior, override handle_event
62
+ def add_listener(details)
63
+ handlers << details
64
+ end
65
+
66
+ # define_handler takes a component/event name and a block to be called when that
67
+ # event is generated for that component. This can be used in place of a method
68
+ # declaration for that component/event pair.
69
+ #
70
+ # So, if you have declared:
71
+ #
72
+ # add_listener :type => :action, :components => [:ok_button]
73
+ #
74
+ # you could implement the handler using:
75
+ #
76
+ # define_handler(:ok_button_action_performed) do |event|
77
+ # # handle the event here
78
+ # end
79
+ #
80
+ # Note that handlers defined using this method will create implicit listener
81
+ # registrations the same as a declared method would.
82
+ #
83
+ # define_handler also accepts multiple event names
84
+ #
85
+ # define_handler(:ok_button_action_performed, :cancel_button_action_performed) do
86
+ # # handle event(s) here
87
+ # end
88
+ def define_handler(*actions, &block)
89
+ actions.each {|action| event_handler_procs[action.to_sym] << block}
90
+ end
91
+ end
92
+
93
+ # This method should be called from the initialize method of the class using
94
+ # this mixin to set up the needed instance variables and both declared
95
+ # and implicit handlers
96
+ def setup_implicit_and_explicit_event_handlers # :nodoc:
97
+ @__event_handler_view_target = if self.class.ancestors.member?(Monkeybars::Controller)
98
+ @__view
99
+ else
100
+ self
101
+ end
102
+ @__registered_handlers = Hash.new{|h,k| h[k] = []}
103
+ @__event_handler_procs = Hash.new{|h,k| h[k] = []}
104
+
105
+ unless self.class.handlers.empty?
106
+ if @__event_handler_view_target.nil?
107
+ raise "A view must be declared in order to add event listeners"
108
+ end
109
+
110
+ self.class.handlers.each do |handler|
111
+ handler[:components].each do |component|
112
+ if component.kind_of? Array
113
+ component = component.first
114
+ end
115
+ begin
116
+ resolved_component = @__event_handler_view_target.instance_eval(component.to_s, __FILE__, __LINE__)
117
+ rescue NoMethodError => e
118
+ raise InvalidHandlerError, "Could not find component: #{component} on view #{@__event_handler_view_target}\nOriginal exception: #{e.message}"
119
+ end
120
+
121
+ add_handler_for handler[:type], handler[:components], resolved_component
122
+ end
123
+ end
124
+ end
125
+
126
+ monkeybars_base_class = self.class.ancestors.find {|klass| /^Monkeybars::(Controller|View)$/ =~ klass.name }
127
+ (methods.grep(/_/) - (EventHandlerRegistrationAndDispatchMixin.instance_methods + monkeybars_base_class.instance_methods)).each {|method| add_implicit_handler_for_method(method) }
128
+
129
+ self.class.event_handler_procs.each {|method, proc| add_implicit_handler_for_method(method)}
130
+ end
131
+
132
+ # Instance-level version of Monkeybars::Controller.define_handler. It follows the same
133
+ # syntax as the class-level version but applies the callback block as a listener to events
134
+ # generated by this instance of the controller class' view. This callback is
135
+ # useful when the application has nested controllers and event handling needs to be different
136
+ # for each instance of a controller class.
137
+ #
138
+ # define_handler can accept either a single event or a list of events to apply the block to:
139
+ #
140
+ # define_handler :ok_button_action_performed { puts "action performed on 'ok button'" }
141
+ #
142
+ # define_handler :ok_button_action_performed, :cancel_button_action_performed { puts "action performed on a button" }
143
+ #
144
+ # If you are defining a handler that requires aliasing, define handler can also be passed a hash of method => component mappings
145
+ # mixed in with the methods to apply the handler to.
146
+ #
147
+ # define_handler :text_field_insert_update => "text_field.document" { puts "you typed something" }
148
+ #
149
+ # define_handler :text_field_insert_update => "text_field.document", :text_field_remove_update => "text_field.document" { puts "you typed or deleted something" }
150
+ #
151
+ # These mappings can also be mixed in with regular methods. It is suggested that you put
152
+ # all of your hash items at the end of the argument list so they are wrapped up into an
153
+ # implicit Hash object although this is not strictly necessary.
154
+ #
155
+ # define_handler :ok_button_action_performed, :text_field_insert_update => "text_field.document" { puts "you did ... something" }
156
+ #
157
+ def define_handler(*actions, &block)
158
+ # define_handler :foo_action_performed => :foo_document_action_performed, { handle event here }
159
+ actions.each do |action|
160
+ if action.kind_of? Hash
161
+ # handle a hash with multiple mappings, e.g.
162
+ # define_handler :text_field_insert_update => "text_field.document", :text_field2_insert_update => "text_field2.document { ... handler code here ... }
163
+ action.each do |method, component|
164
+ @__event_handler_procs[method.to_sym] << block
165
+ add_implicit_handler_for_method(method, component)
166
+ end
167
+ else
168
+ @__event_handler_procs[action.to_sym] << block
169
+ add_implicit_handler_for_method(action)
170
+ end
171
+ end
172
+ end
173
+
174
+ # Specific handlers get precedence over general handlers, that is button_mouse_released
175
+ # gets called before mouse_released.
176
+ def handle_event(component_name, event_name, event) #:nodoc:
177
+ return if event.nil?
178
+
179
+ callbacks = get_callbacks("#{component_name}_#{event_name}".to_sym)
180
+ if callbacks.empty?
181
+ callbacks = get_callbacks(event_name.to_sym)
182
+ end
183
+
184
+ callbacks.each{ |proc| 0 == proc.arity ? proc.call : proc.call(event) }
185
+ end
186
+
187
+ private
188
+ def get_callbacks(method)
189
+ callbacks = []
190
+ begin
191
+ callbacks << method(method)
192
+ rescue NameError; end
193
+ callbacks + self.class.event_handler_procs[method] + @__event_handler_procs[method]
194
+ end
195
+
196
+ def add_implicit_handler_for_method(method, component_to_alias = nil)
197
+ component_match = nil
198
+
199
+ Monkeybars::Handlers::ALL_EVENT_NAMES.each do |event|
200
+ component_match = Regexp.new("(.*)_(#{event})").match(method.to_s)
201
+ break unless component_match.nil?
202
+ end
203
+
204
+ return if component_match.nil?
205
+ component_name, event_name = component_match[1], component_match[2]
206
+
207
+ begin
208
+ if component_to_alias.nil?
209
+ component = @__event_handler_view_target.instance_eval(component_name)
210
+ else
211
+ component = @__event_handler_view_target.instance_eval(component_to_alias)
212
+ end
213
+ rescue NameError => e
214
+ rescue Monkeybars::UndefinedComponentError => e
215
+ # swallow, handler style methods for controls that don't exist is allowed
216
+ else
217
+ component.methods.each do |method|
218
+ listener_match = /add(.*)Listener/.match(method)
219
+ next if listener_match.nil?
220
+ if Monkeybars::Handlers::EVENT_NAMES_BY_TYPE[listener_match[1]].member? event_name
221
+ if component_to_alias.nil?
222
+ add_handler_for listener_match[1], component_name, component
223
+ else
224
+ add_handler_for listener_match[1], {component_to_alias => component_name}, component
225
+ end
226
+ end
227
+ end
228
+ end
229
+ end
230
+
231
+ def add_handler_for(handler_type, components, java_component)
232
+ components = ["global"] if components.nil?
233
+ components = [components] unless components.kind_of? Array
234
+ components.each do |component|
235
+ # handle aliases :components => {"text_area.document" => "text_area"}
236
+ if component.kind_of? Hash
237
+ component_name = component.values[0]
238
+ component_field = component.keys[0]
239
+ else
240
+ component_name = component
241
+ component_field = component
242
+ end
243
+ unless @__registered_handlers[java_component].member? handler_type.underscore
244
+ handler = "Monkeybars::#{handler_type.camelize}Handler".constantize.new(self, component_name.to_s)
245
+ @__event_handler_view_target.add_handler(handler, component_field)
246
+ @__registered_handlers[java_component] << handler_type.underscore
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,10 @@
1
+ module Monkeybars
2
+ class UndefinedComponentError < RuntimeError; end
3
+ class InvalidSignalHandlerError < RuntimeError; end
4
+ class UndefinedSignalError < RuntimeError; end
5
+ class InvalidCloseAction < RuntimeError; end
6
+ class InvalidMappingError < RuntimeError; end
7
+ class TranslationError < RuntimeError; end
8
+ class InvalidNestingError < RuntimeError; end
9
+ class InvalidHandlerError < RuntimeError; end
10
+ end
@@ -0,0 +1,34 @@
1
+ # Interface to setting up a handler for any uncaught exceptions in the application.
2
+ # The block that is passed into GlobalErrorHandler.on_error will be called when
3
+ # an uncaught exception occurs.
4
+ #
5
+ # You must be *VERY* careful when implementing your handler. All uncaught exceptions
6
+ # will be routed to this block so any error that occur inside the block will not
7
+ # generate exceptions.
8
+ class GlobalErrorHandler
9
+ include Java::java::lang::Thread::UncaughtExceptionHandler
10
+
11
+ # Creation point for the GlobalErrorHandler. To use, pass in a block that takes
12
+ # 2 parameters, the exception and the thread that the exception occured on.
13
+ #
14
+ # The exception passed into this block is a *Java* Throwable, not a Ruby exception.
15
+ # http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Throwable.html
16
+ #
17
+ # GlobalErrorHandler.on_error {|exception, thread| puts "Error #{exception} occured on thread #{thread}" }
18
+ #
19
+ # or you may want to dispatch to an error handler method.
20
+ #
21
+ # GlobalErrorHandler.on_error {|exception, thread| my_error_handler_method(exception, thread) }
22
+ def self.on_error(&callback)
23
+ java.lang.Thread.default_uncaught_exception_handler = self.new(&callback)
24
+ end
25
+
26
+ def uncaughtException(thread, exception)
27
+ @callback.call(exception, thread)
28
+ end
29
+
30
+ private
31
+ def initialize(&callback)
32
+ @callback = callback
33
+ end
34
+ end