Neurogami-jimpanzee 1.0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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