glimmer 0.4.8 → 0.4.9

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.
data/bin/girb_runner.rb CHANGED
@@ -1 +1,3 @@
1
+ require 'puts_debuggerer'
2
+
1
3
  include Glimmer
data/lib/glimmer.rb CHANGED
@@ -8,6 +8,7 @@ require "facets"
8
8
  require "super_module"
9
9
  require "logger"
10
10
  require "java"
11
+ require "nested_inherited_jruby_include_package"
11
12
  require_relative "glimmer/parent"
12
13
  require_relative "glimmer/swt_packages" #TODO move into SWT namespace
13
14
  require_relative "glimmer/swt/custom_widget"
@@ -1,8 +1,13 @@
1
1
  module Glimmer
2
+ # rename to keyword handler
3
+
2
4
  module CommandHandler
3
5
  def can_handle?(parent, command_symbol, *args, &block)
4
6
  raise "must be implemented by a class"
5
7
  end
8
+
9
+ # TODO rename do_handle to just handle
10
+
6
11
  def do_handle(parent, command_symbol, *args, &block)
7
12
  raise "must be implemented by a class"
8
13
  end
@@ -14,10 +14,11 @@ module Glimmer
14
14
  return @next_chain_link.handle(parent, command_symbol, *args, &block)
15
15
  else
16
16
  # TODO see if we need a better response here (e.g. dev mode error raising vs production mode silent failure)
17
- # Glimmer.logger.error "Command: #{command_symbol} cannot be handled!"
18
- Glimmer.logger.debug "Command: #{command_symbol} cannot be handled!"
19
- # raise "Command: #{command_symbol} cannot be handled!"
20
- nil
17
+ message = "Glimmer keyword #{command_symbol} with args #{args} cannot be handled"
18
+ message += " inside parent #{parent.inspect}" if parent
19
+ message += "! Check the validity of the code."
20
+ # Glimmer.logger.error message
21
+ raise message
21
22
  end
22
23
  end
23
24
  end
@@ -1,4 +1,5 @@
1
1
  require_relative "command_handler_chain_factory"
2
+ require_relative "swt/command_handlers/observe_command_handler"
2
3
  require_relative "swt/command_handlers/color_command_handler"
3
4
  require_relative "swt/command_handlers/display_command_handler"
4
5
  require_relative "swt/command_handlers/shell_command_handler"
@@ -22,6 +23,7 @@ require_relative "swt/command_handlers/custom_widget_command_handler"
22
23
  module Glimmer
23
24
  # edit to add more command handlers and extend Glimmer
24
25
  CommandHandlerChainFactory.def_dsl(:swt,
26
+ SWT::CommandHandlers::ObserveCommandHandler.new,
25
27
  SWT::CommandHandlers::DisplayCommandHandler.new,
26
28
  SWT::CommandHandlers::ShellCommandHandler.new,
27
29
  SWT::CommandHandlers::LayoutDataCommandHandler.new,
@@ -1,5 +1,6 @@
1
1
  require File.dirname(__FILE__) + "/../../command_handler"
2
2
  require File.dirname(__FILE__) + "/../custom_widget"
3
+ require File.dirname(__FILE__) + "/../custom_shell"
3
4
  require File.dirname(__FILE__) + "/../g_widget"
4
5
 
5
6
  module Glimmer
@@ -9,8 +10,9 @@ module Glimmer
9
10
  include CommandHandler
10
11
 
11
12
  def can_handle?(parent, command_symbol, *args, &block)
12
- (parent.is_a?(GWidget) || parent.is_a?(CustomWidget)) and
13
- CustomWidget.for(command_symbol)
13
+ custom_widget_class = CustomWidget.for(command_symbol)
14
+ custom_widget_class and
15
+ (parent.is_a?(GWidget) || parent.is_a?(CustomWidget) || custom_widget_class.ancestors.include?(CustomShell))
14
16
  end
15
17
 
16
18
  def do_handle(parent, command_symbol, *args, &block)
@@ -16,7 +16,6 @@ module Glimmer
16
16
  #
17
17
  # Depends on BindCommandHandler
18
18
  class DataBindingCommandHandler
19
- extend Glimmer
20
19
  include CommandHandler
21
20
 
22
21
  include_package 'org.eclipse.swt.widgets'
@@ -0,0 +1,35 @@
1
+ require File.dirname(__FILE__) + "/../../command_handler"
2
+
3
+ module Glimmer
4
+ module SWT
5
+ module CommandHandlers
6
+ class ObserveCommandHandler
7
+ REGEX_NESTED_OR_INDEXED_PROPERTY = /([^\[]+)(\[[^\]]+\])?/
8
+ include CommandHandler
9
+
10
+ def can_handle?(parent, command_symbol, *args, &block)
11
+ command_symbol.to_s == "observe" and
12
+ (
13
+ (
14
+ (args.size == 2) and
15
+ (
16
+ args[1].is_a?(Symbol) or
17
+ args[1].is_a?(String)
18
+ )
19
+ )
20
+ ) and
21
+ !block.nil?
22
+ end
23
+
24
+ def do_handle(parent, command_symbol, *args, &block)
25
+ observer = Observer.proc(&block)
26
+ if args[1].to_s.match(REGEX_NESTED_OR_INDEXED_PROPERTY)
27
+ observer.observe(ModelBinding.new(args[0], args[1]))
28
+ else
29
+ observer.observe(args[0], args[1])
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -8,10 +8,10 @@ module Glimmer
8
8
 
9
9
  def can_handle?(parent, command_symbol, *args, &block)
10
10
  parent.respond_to?(:set_attribute) and
11
- parent.respond_to?(:has_attribute?) and
12
- args.size > 0 and
13
- block == nil and
14
- parent.has_attribute?(command_symbol, *args)
11
+ parent.respond_to?(:has_attribute?) and
12
+ args.size > 0 and
13
+ block == nil and
14
+ parent.has_attribute?(command_symbol, *args)
15
15
  end
16
16
 
17
17
  def do_handle(parent, command_symbol, *args, &block)
@@ -5,6 +5,8 @@ require File.dirname(__FILE__) + "/../custom_widget"
5
5
  module Glimmer
6
6
  module SWT
7
7
  module CommandHandlers
8
+ # TODO rename to observation command handler (or keyword handler)
9
+
8
10
  class WidgetListenerCommandHandler
9
11
  include CommandHandler
10
12
 
@@ -14,18 +16,19 @@ module Glimmer
14
16
  widget_parentage = (parent.is_a?(GWidget) || parent.is_a?(CustomWidget))
15
17
  Glimmer.logger.debug "parent is a widget: #{widget_parentage}"
16
18
  return unless widget_parentage
17
- Glimmer.logger.debug "on listener?: " + (command_symbol.to_s[0,3] == "on_").to_s
18
- return unless command_symbol.to_s[0,3] == "on_"
19
- Glimmer.logger.debug "command symbol is longer than 3: " + (command_symbol.to_s.length > 3).to_s
20
- return unless command_symbol.to_s.length > 3
21
- Glimmer.logger.debug "args are 0?: " + (args.size == 0).to_s
22
- return unless args.size == 0
23
- Glimmer.logger.debug "can add listener? " + (parent.can_add_listener?(command_symbol.to_s[3, command_symbol.to_s.length])).to_s
24
- parent.can_add_listener?(command_symbol.to_s[3, command_symbol.to_s.length])
19
+ Glimmer.logger.debug "keyword starts with on_: #{command_symbol.to_s.start_with?('on_')}"
20
+ return unless command_symbol.to_s.start_with?('on_')
21
+ Glimmer.logger.debug "args are empty?: #{args.empty?}"
22
+ return unless args.empty?
23
+ Glimmer.logger.debug "block exists?: #{!block.nil?}"
24
+ return unless !block.nil?
25
+ result = parent.can_handle_observation_request?(command_symbol.to_s)
26
+ Glimmer.logger.debug "can add listener? #{result}"
27
+ result
25
28
  end
26
29
 
27
30
  def do_handle(parent, command_symbol, *args, &block)
28
- parent.add_listener(command_symbol.to_s[3, command_symbol.to_s.length], &block)
31
+ parent.handle_observation_request(command_symbol.to_s, &block)
29
32
  ListenerParent.new #TODO refactor and move to models
30
33
  end
31
34
 
@@ -0,0 +1,45 @@
1
+ require 'super_module'
2
+
3
+ module Glimmer
4
+ module SWT
5
+ module CustomShell
6
+ include SuperModule
7
+ include Glimmer::SWT::CustomWidget
8
+
9
+ def initialize(parent, *swt_constants, options, &content)
10
+ super
11
+ raise 'Invalid custom shell body root! Must be a shell or another custom shell.' unless body_root.is_a?(GShell) || body_root.is_a?(CustomShell)
12
+ end
13
+
14
+ # Classes may override
15
+ def open
16
+ body_root.open
17
+ end
18
+
19
+ # DO NOT OVERRIDE. JUST AN ALIAS FOR `#open`. OVERRIDE `#open` INSTEAD.
20
+ def show
21
+ open
22
+ end
23
+
24
+ def close
25
+ body_root.close
26
+ end
27
+
28
+ def hide
29
+ body_root.hide
30
+ end
31
+
32
+ def visible?
33
+ body_root.visible?
34
+ end
35
+
36
+ def center
37
+ body_root.center
38
+ end
39
+
40
+ def start_event_loop
41
+ body_root.start_event_loop
42
+ end
43
+ end
44
+ end
45
+ end
@@ -58,6 +58,16 @@ module Glimmer
58
58
  end_eval
59
59
  end
60
60
  end
61
+
62
+ def before_body(&block)
63
+ @before_body_blocks ||= []
64
+ @before_body_blocks << block
65
+ end
66
+
67
+ def after_body(&block)
68
+ @after_body_blocks ||= []
69
+ @after_body_blocks << block
70
+ end
61
71
  end
62
72
 
63
73
  attr_reader :body_root, :widget, :parent, :swt_style, :options, :content
@@ -68,7 +78,9 @@ module Glimmer
68
78
  options ||= {}
69
79
  @options = self.class.options.merge(options)
70
80
  @content = ProcTracker.new(content) if content
81
+ execute_hooks('before_body')
71
82
  @body_root = body
83
+ execute_hooks('after_body')
72
84
  @widget = @body_root.widget
73
85
  end
74
86
 
@@ -76,16 +88,26 @@ module Glimmer
76
88
  raise 'Not implemented!'
77
89
  end
78
90
 
79
- # TODO consider using delegators
80
-
81
- def can_add_listener?(underscored_listener_name)
82
- @body_root.can_add_listener?(underscored_listener_name)
91
+ def can_handle_observation_request?(observation_request)
92
+ result = false
93
+ if observation_request.start_with?('on_updated_')
94
+ property = observation_request.sub(/^on_updated_/, '')
95
+ result = can_add_observer?(property)
96
+ end
97
+ result || body_root&.can_handle_observation_request?(observation_request)
83
98
  end
84
99
 
85
- # TODO clean up difference between add_listener and add_observer
100
+ def handle_observation_request(observation_request, &block)
101
+ if observation_request.start_with?('on_updated_')
102
+ property = observation_request.sub(/^on_updated_/, '')
103
+ add_observer(Observer::Proc.new(&block), property) if can_add_observer?(property)
104
+ else
105
+ body_root.handle_observation_request(observation_request, &block)
106
+ end
107
+ end
86
108
 
87
- def add_listener(underscored_listener_name, &block)
88
- @body_root.add_listener(underscored_listener_name, &block)
109
+ def can_add_observer?(attribute_name)
110
+ respond_to?(attribute_name) || @body_root.can_add_observer?(attribute_name)
89
111
  end
90
112
 
91
113
  def add_observer(observer, attribute_name)
@@ -121,11 +143,53 @@ module Glimmer
121
143
  "#{attribute_name}="
122
144
  end
123
145
 
146
+ # TODO see if it is worth it to eliminate duplication of method_missing
147
+ # from GWidget using a module
148
+
149
+ def method_missing(method, *args, &block)
150
+ method_name = method.to_s
151
+ if can_handle_observation_request?(method_name)
152
+ handle_observation_request(method_name, &block)
153
+ else
154
+ super
155
+ end
156
+ end
157
+
124
158
  def process_block(block)
125
159
  if block.source_location == @content&.__getobj__.source_location
126
- @content.call unless @content.called?
160
+ @content.call(self) unless @content.called?
127
161
  else
128
- block.call
162
+ block.call(self)
163
+ end
164
+ end
165
+
166
+ def has_style?(style)
167
+ (swt_style & GSWT[style]) == GSWT[style]
168
+ end
169
+
170
+ # TODO see if it is worth it to eliminate duplication of async_exec/sync_exec
171
+ # delegation to GDisplay, via a module
172
+
173
+ def async_exec(&block)
174
+ GDisplay.instance.async_exec(&block)
175
+ end
176
+
177
+ def sync_exec(&block)
178
+ GDisplay.instance.sync_exec(&block)
179
+ end
180
+
181
+ def add_content(&block)
182
+ body_root.add_content(&block)
183
+ end
184
+
185
+ private
186
+
187
+ def execute_hooks(hook_name)
188
+ self.class.instance_variable_get("@#{hook_name}_blocks")&.each_with_index do |hook_block, i|
189
+ hook_block_number = i + 1
190
+ self.class.define_method("__#{hook_name}#{hook_block_number}", hook_block)
191
+ send("__#{hook_name}#{hook_block_number}")
192
+ self.class.send(:undef_method, "__#{hook_name}#{hook_block_number}")
129
193
  end
130
194
  end
131
195
  end
@@ -23,6 +23,14 @@ module Glimmer
23
23
  def dispose
24
24
  @display.dispose
25
25
  end
26
+
27
+ def async_exec(&block)
28
+ @display.asyncExec(GRunnable.new(&block))
29
+ end
30
+
31
+ def sync_exec(&block)
32
+ @display.syncExec(GRunnable.new(&block))
33
+ end
26
34
  end
27
35
  end
28
36
  end
@@ -7,8 +7,6 @@ module Glimmer
7
7
  FONT_STYLES = [:normal, :bold, :italic]
8
8
  include_package 'org.eclipse.swt.graphics'
9
9
 
10
- extend Glimmer
11
-
12
10
  attr_reader :g_widget
13
11
  attr_accessor :display
14
12
 
@@ -17,11 +15,9 @@ module Glimmer
17
15
  @instances ||= {}
18
16
  unless @instances[g_widget]
19
17
  @instances[g_widget] = new(g_widget)
20
- add_contents(g_widget) {
21
- on_widget_disposed { |dispose_event|
22
- @instances.delete(g_widget)
23
- }
24
- }
18
+ g_widget.on_widget_disposed do |dispose_event|
19
+ @instances.delete(g_widget)
20
+ end
25
21
  end
26
22
  @instances[g_widget]
27
23
  end
@@ -46,7 +46,7 @@ module Glimmer
46
46
  end
47
47
 
48
48
  def process_block(block)
49
- block.call(@layout)
49
+ block.call(self)
50
50
  end
51
51
 
52
52
  def has_attribute?(attribute_name, *args)
@@ -24,7 +24,7 @@ module Glimmer
24
24
  end
25
25
 
26
26
  def process_block(block)
27
- block.call(@layout)
27
+ block.call(self)
28
28
  end
29
29
 
30
30
  def swt_layout_data_class
@@ -10,7 +10,8 @@ module Glimmer
10
10
  include_package 'org.eclipse.swt.layout'
11
11
  include_package 'org.eclipse.swt.widgets'
12
12
 
13
- attr_reader :display
13
+ attr_reader :display, :opened_before
14
+ alias opened_before? opened_before
14
15
 
15
16
  # Instantiates shell with same arguments expected by SWT Shell
16
17
  def initialize(*args)
@@ -37,10 +38,44 @@ module Glimmer
37
38
 
38
39
  # Opens shell and starts SWT's UI thread event loop
39
40
  def open
40
- @widget.pack
41
- center
42
- @widget.open
43
- start_event_loop
41
+ if @opened_before
42
+ @widget.setVisible(true)
43
+ # notify_observers('visible')
44
+ else
45
+ @opened_before = true
46
+ @widget.pack
47
+ center
48
+ @widget.open
49
+ # NOTE: the following line runs after scheduled sync exec events,
50
+ # but ensures visible status is only updated upon true visibility
51
+ # async_exec do
52
+ # notify_observers('visible')
53
+ # end
54
+ start_event_loop
55
+ end
56
+ end
57
+ alias show open
58
+
59
+ def hide
60
+ @widget.setVisible(false)
61
+ # notify_observers('visible')
62
+ end
63
+
64
+ def close
65
+ @widget.close
66
+ # notify_observers('visible')
67
+ end
68
+
69
+ # TODO implement and notify_observers('visible') based on open and hide
70
+
71
+ def visible?
72
+ @widget.isDisposed ? false : @widget.isVisible
73
+ end
74
+
75
+ # TODO evaluate if this is needed
76
+
77
+ def visible=(visibility)
78
+ visibility ? show : hide
44
79
  end
45
80
 
46
81
  def start_event_loop
@@ -49,6 +84,23 @@ module Glimmer
49
84
  end
50
85
  @display.dispose
51
86
  end
87
+
88
+ def add_observer(observer, property_name)
89
+ case property_name.to_s
90
+ when 'visible?'
91
+ @widget.addListener(GSWT[:show]) do |event|
92
+ observer.call(visible?)
93
+ end
94
+ @widget.addListener(GSWT[:hide]) do |event|
95
+ observer.call(visible?)
96
+ end
97
+ @widget.addListener(GSWT[:close]) do |event|
98
+ observer.call(visible?)
99
+ end
100
+ else
101
+ super
102
+ end
103
+ end
52
104
  end
53
105
  end
54
106
  end