glimmer-dsl-swing 0.0.1 → 0.0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ecbd6a72ae4955c7f90995ef135f1aac59fc4b3294377fa4b7957b1b22069715
4
- data.tar.gz: a58db866e29fd2d2f6620314918b629a94095cbe717ce7ca6c998d30a6d4348d
3
+ metadata.gz: d91f9d5241c9f9414d4f4c343568a71f19657560b72713a4fbfe4711af0e120f
4
+ data.tar.gz: 25079ddbf4e8b83a899b4857e88aa9dacfbde3f67147c7708047113654e42df7
5
5
  SHA512:
6
- metadata.gz: 1c675e8abe364913657308555622a3969d7eed06b0e95894946686fa01e9493bf56e2a016bb5c135edcb1e6ac2a11fea91809c248724257f2d2ab4db59607d0a
7
- data.tar.gz: a7c4ccc5cac6eececddf64760737c9765f9ef7c9b40efa6a6a77eb326b2257a425d222297087cb3a93a9589b215d9edbe8ddff27452ac0fcc14582aab228b6b8
6
+ metadata.gz: 23641076d917e3223517cfabfd82c72973360b4bff14032567e67e6352b4dd40e6e628d920833786401a8b0d65b3959d6303e6721cd2fd95254ff365e8bc64ee
7
+ data.tar.gz: f1b4f292413767713e88bf115e0b16cb4df5644f72cfb79c80f5043dbc4bfe639e6e3fb5ec79ec515b3e526e094c4be9aed3a48ed2a3ba7d402978517643770c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.0.2
4
+
5
+ - General Java 2D shape support by nesting under any component
6
+ - Support setting `jframe` `minimum_size width, height` without building `Dimension` object manually
7
+ - Hello, Shapes! sample
8
+ - Improve Hello, Button! sample
9
+
3
10
  ## 0.0.1
4
11
 
5
12
  - Initial version of Glimmer DSL for Swing
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Swing 0.0.1
1
+ # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Swing 0.0.2
2
2
  ## JRuby Swing Desktop Development GUI Library
3
3
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-swing.svg)](http://badge.fury.io/rb/glimmer-dsl-swing)
4
4
  [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -64,7 +64,7 @@ gem install glimmer-dsl-swing
64
64
 
65
65
  Add the following to `Gemfile`:
66
66
  ```
67
- gem 'glimmer-dsl-swing', '~> 0.0.1'
67
+ gem 'glimmer-dsl-swing', '~> 0.0.2'
68
68
  ```
69
69
 
70
70
  And, then run:
@@ -86,6 +86,153 @@ jframe('Hello, World!') {
86
86
  }.show
87
87
  ```
88
88
 
89
+ ## Glimmer GUI DSL
90
+
91
+ The Glimmer GUI DSL enables development of desktop graphical user interfaces in a manner similar to HTML, but in one language, Ruby, thus avoiding the multi-language separation dissonance encountered on the web, especially given that Ruby looping/conditional constructs do not need scriptlets to be added around View code. This makes desktop development extremely productive.
92
+
93
+ 1 - Keywords
94
+
95
+ You may declare any swing/awt component with its keyword, which is the underscored version of the class name. For example, `jframe` is the keyword for `javax.swing.JFrame` (`j_frame` is acceptable too)
96
+
97
+ Examples:
98
+
99
+ ```ruby
100
+ jframe
101
+ jbutton
102
+ jlabel
103
+ ```
104
+
105
+ 2 - Arguments
106
+
107
+ You may pass any arguments that a [swing](https://docs.oracle.com/javase/8/docs/api/javax/swing/package-summary.html)/[awt](https://docs.oracle.com/javase/8/docs/api/java/awt/package-summary.html) component constructor accepts to its Glimmer keyword.
108
+
109
+ Example `JFrame`, `JLabel`, and `JButton` have a constructor signature that accepts a string representing title or text:
110
+
111
+ ```ruby
112
+ jframe('Hello, World!')
113
+ jbutton('Push Me')
114
+ jlabel('Name')
115
+ ```
116
+
117
+ The recommended style is to always wrap arguments with parentheses for component keywords.
118
+
119
+ 3 - Content Block
120
+
121
+ You may pass a content block to any [swing](https://docs.oracle.com/javase/8/docs/api/javax/swing/package-summary.html)/[awt](https://docs.oracle.com/javase/8/docs/api/java/awt/package-summary.html) component keyword, which contains properties and/or nested components.
122
+
123
+ Example:
124
+
125
+ ```ruby
126
+ jframe('Hello, World!') {
127
+ minimum_size 320, 240
128
+
129
+ jlabel('Hello, World!')
130
+ }
131
+ ```
132
+
133
+ The recommended style for the content block is to always be curly braces to denote as View nesting code different from the logic in looping/conditional constructs that utilize `do;end` instead.
134
+
135
+ Property arguments never have parentheses.
136
+
137
+ 4 - Listeners
138
+
139
+ You may declare listeners with their event method name on the [swing](https://docs.oracle.com/javase/8/docs/api/javax/swing/package-summary.html)/[awt](https://docs.oracle.com/javase/8/docs/api/java/awt/package-summary.html) listener class (these are the classes in the signatures of `AddXYZListener` methods on [swing](https://docs.oracle.com/javase/8/docs/api/javax/swing/package-summary.html)/[awt](https://docs.oracle.com/javase/8/docs/api/java/awt/package-summary.html) component classes).
140
+
141
+ For example, `JButton` has an `AddXYZListener` method called `AddActionListener`, which accepts an `ActionListener` class. That class has one event method: `actionPerformed`. In Glimmer, you simply underscore that and prefix with `on_`:
142
+
143
+ ```ruby
144
+ jframe('Hello, Button!') {
145
+ jbutton('Click') {
146
+ on_action_performed do
147
+ puts 'Clicked!'
148
+ end
149
+ }
150
+ }
151
+ ```
152
+
153
+ The recommended style for listeners is always a `do; end` block.
154
+
155
+ 5 - Component Proxy & Methods
156
+
157
+ When utilizing the Glimmer GUI DSL, you get back proxy objects that wrap [swing](https://docs.oracle.com/javase/8/docs/api/javax/swing/package-summary.html)/[awt](https://docs.oracle.com/javase/8/docs/api/java/awt/package-summary.html) components. To access the original component wrapped by the proxy object, you may call the `#original` method.
158
+
159
+ Furthermore, you may invoke any method available on the component on the proxy object, like the `#show` method on `JFrame`.
160
+
161
+ ```ruby
162
+ frame1 = jframe('Hello, World!') {
163
+ # ...
164
+ }
165
+ frame1.show
166
+ ```
167
+
168
+ ### Shape DSL
169
+
170
+ [Glimmer DSL for Swing](https://rubygems.org/gems/glimmer-dsl-swing) might be the only Ruby Swing DSL out there that supports an additional Shape DSL.
171
+
172
+ This enables declarative painting of arbitrary shapes using Java 2D, which is similar to how SVG works on the web.
173
+
174
+ Simply utilize underscored shape names from the `java.awt.geom` [package classes](https://docs.oracle.com/javase/8/docs/api/java/awt/geom/package-summary.html) minus the `2D` suffix, following the same general rules of the [Glimmer GUI DSL](#glimmer-gui-dsl).
175
+
176
+ For example, `Arc2D` becomes simply `arc`.
177
+
178
+ Additionally, you can set `draw_color` or `fill_color` property as an rgb/rgba hash (e.g. `r: 255, g: 0, b: 0`)
179
+
180
+ Example:
181
+
182
+ ```ruby
183
+ require 'glimmer-dsl-swing'
184
+
185
+ include Glimmer
186
+
187
+ jframe('Hello, Shapes!') {
188
+ minimum_size 400, 400
189
+
190
+ arc(40, 40, 90, 90, 30, 230, 0) {
191
+ fill_color r: 255, g: 0, b: 0
192
+ draw_color r: 0, g: 255, b: 255
193
+ }
194
+
195
+ arc(40, 140, 90, 90, 30, 230, 1) {
196
+ fill_color r: 255, g: 0, b: 0
197
+ draw_color r: 0, g: 255, b: 255
198
+ }
199
+
200
+ arc(40, 240, 90, 90, 30, 230, 2) {
201
+ fill_color r: 255, g: 0, b: 0
202
+ draw_color r: 0, g: 255, b: 255
203
+ }
204
+
205
+ ellipse(140, 40, 180, 90) {
206
+ fill_color r: 0, g: 255, b: 255
207
+ draw_color r: 255, g: 0, b: 0
208
+ }
209
+
210
+ rectangle(140, 140, 180, 90) {
211
+ fill_color r: 0, g: 255, b: 255
212
+ draw_color r: 255, g: 0, b: 0
213
+ }
214
+
215
+ round_rectangle(140, 240, 180, 90, 60, 40) {
216
+ fill_color r: 0, g: 255, b: 255
217
+ draw_color r: 255, g: 0, b: 0
218
+ }
219
+
220
+ line(180, 60, 280, 110) {
221
+ draw_color r: 0, g: 0, b: 0
222
+ }
223
+
224
+ quad_curve(170, 60, 180, 90, 220, 100) {
225
+ draw_color r: 0, g: 0, b: 0
226
+ }
227
+
228
+ cubic_curve(190, 60, 240, 40, 220, 80, 260, 70) {
229
+ draw_color r: 0, g: 0, b: 0
230
+ }
231
+ }.show
232
+ ```
233
+
234
+ ![screenshots/glimmer-dsl-swing-mac-hello-shapes.png](screenshots/glimmer-dsl-swing-mac-hello-shapes.png)
235
+
89
236
  ## Girb (Glimmer IRB)
90
237
 
91
238
  You can run the `girb` command (`bin/girb` if you cloned the project locally):
@@ -102,6 +249,18 @@ This gives you `irb` with the `glimmer-dsl-gtk` gem loaded and the `Glimmer` mod
102
249
 
103
250
  #### Hello, World!
104
251
 
252
+ Run with gem installed:
253
+
254
+ ```
255
+ jruby -r glimmer-dsl-swing -e "require 'samples/hello/hello_world'"
256
+ ```
257
+
258
+ Or run from locally cloned project directory:
259
+
260
+ ```
261
+ jruby -r ./lib/glimmer-dsl-swing samples/hello/hello_world.rb
262
+ ```
263
+
105
264
  ![screenshots/glimmer-dsl-swing-mac-hello-world.png](screenshots/glimmer-dsl-swing-mac-hello-world.png)
106
265
 
107
266
  ```ruby
@@ -116,6 +275,18 @@ jframe('Hello, World!') {
116
275
 
117
276
  #### Hello, Button!
118
277
 
278
+ Run with gem installed:
279
+
280
+ ```
281
+ jruby -r glimmer-dsl-swing -e "require 'samples/hello/hello_button'"
282
+ ```
283
+
284
+ Or run from locally cloned project directory:
285
+
286
+ ```
287
+ jruby -r ./lib/glimmer-dsl-swing samples/hello/hello_button.rb
288
+ ```
289
+
119
290
  ![screenshots/glimmer-dsl-swing-mac-hello-button.png](screenshots/glimmer-dsl-swing-mac-hello-button.png)
120
291
 
121
292
  ```ruby
@@ -125,11 +296,79 @@ include Glimmer
125
296
 
126
297
  jframe('Hello, Button!') {
127
298
  @button = jbutton('Click To Increment: 0') {
128
- on_action_performed {
299
+ on_action_performed do
129
300
  button_text_match = @button.text.match(/(.*)(\d+)$/)
130
301
  count = button_text_match[2].to_i + 1
131
302
  @button.text = "#{button_text_match[1]}#{count}"
132
- }
303
+ end
304
+ }
305
+ }.show
306
+ ```
307
+
308
+ #### Hello, Shapes!
309
+
310
+ Run with gem installed:
311
+
312
+ ```
313
+ jruby -r glimmer-dsl-swing -e "require 'samples/hello/hello_shapes'"
314
+ ```
315
+
316
+ Or run from locally cloned project directory:
317
+
318
+ ```
319
+ jruby -r ./lib/glimmer-dsl-swing samples/hello/hello_shapes.rb
320
+ ```
321
+
322
+ ![screenshots/glimmer-dsl-swing-mac-hello-shapes.png](screenshots/glimmer-dsl-swing-mac-hello-shapes.png)
323
+
324
+ ```ruby
325
+ require 'glimmer-dsl-swing'
326
+
327
+ include Glimmer
328
+
329
+ jframe('Hello, Shapes!') {
330
+ minimum_size 400, 400
331
+
332
+ arc(40, 40, 90, 90, 30, 230, 0) {
333
+ fill_color r: 255, g: 0, b: 0
334
+ draw_color r: 0, g: 255, b: 255
335
+ }
336
+
337
+ arc(40, 140, 90, 90, 30, 230, 1) {
338
+ fill_color r: 255, g: 0, b: 0
339
+ draw_color r: 0, g: 255, b: 255
340
+ }
341
+
342
+ arc(40, 240, 90, 90, 30, 230, 2) {
343
+ fill_color r: 255, g: 0, b: 0
344
+ draw_color r: 0, g: 255, b: 255
345
+ }
346
+
347
+ ellipse(140, 40, 180, 90) {
348
+ fill_color r: 0, g: 255, b: 255
349
+ draw_color r: 255, g: 0, b: 0
350
+ }
351
+
352
+ rectangle(140, 140, 180, 90) {
353
+ fill_color r: 0, g: 255, b: 255
354
+ draw_color r: 255, g: 0, b: 0
355
+ }
356
+
357
+ round_rectangle(140, 240, 180, 90, 60, 40) {
358
+ fill_color r: 0, g: 255, b: 255
359
+ draw_color r: 255, g: 0, b: 0
360
+ }
361
+
362
+ line(180, 60, 280, 110) {
363
+ draw_color r: 0, g: 0, b: 0
364
+ }
365
+
366
+ quad_curve(170, 60, 180, 90, 220, 100) {
367
+ draw_color r: 0, g: 0, b: 0
368
+ }
369
+
370
+ cubic_curve(190, 60, 240, 40, 220, 80, 260, 70) {
371
+ draw_color r: 0, g: 0, b: 0
133
372
  }
134
373
  }.show
135
374
  ```
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
data/bin/girb CHANGED
File without changes
Binary file
@@ -29,12 +29,12 @@ module Glimmer
29
29
  include ParentExpression
30
30
 
31
31
  def can_interpret?(parent, keyword, *args, &block)
32
- keyword = "j_#{keyword[1..-1]}" if keyword.match(/j[a-z]/)
32
+ keyword = "j_#{keyword[1..-1]}" if keyword.match(/j[a-z]/) # TODO move this logic to ComponentProxy
33
33
  Glimmer::Swing::ComponentProxy.exist?(keyword)
34
34
  end
35
35
 
36
36
  def interpret(parent, keyword, *args, &block)
37
- keyword = "j_#{keyword[1..-1]}" if keyword.match(/j[a-z]/)
37
+ keyword = "j_#{keyword[1..-1]}" if keyword.match(/j[a-z]/) # TODO move this logic to ComponentProxy
38
38
  Glimmer::Swing::ComponentProxy.create(parent, keyword, *args, &block)
39
39
  end
40
40
 
@@ -39,6 +39,7 @@ module Glimmer
39
39
  listener
40
40
  property
41
41
  component
42
+ shape
42
43
  ]
43
44
  )
44
45
  end
@@ -27,13 +27,16 @@ module Glimmer
27
27
  module Swing
28
28
  class PropertyExpression < Expression
29
29
  def can_interpret?(parent, keyword, *args, &block)
30
- parent.is_a?(Glimmer::Swing::ComponentProxy) and
30
+ (
31
+ parent.is_a?(Glimmer::Swing::ComponentProxy) or
32
+ parent.is_a?(Glimmer::Swing::ShapeProxy)
33
+ ) and
31
34
  block.nil? and
32
35
  parent.respond_to?(keyword, *args)
33
36
  end
34
37
 
35
38
  def interpret(parent, keyword, *args, &block)
36
- parent.send(keyword, *args)
39
+ parent.send("#{keyword}=", *args)
37
40
  end
38
41
  end
39
42
  end
@@ -0,0 +1,48 @@
1
+ # Copyright (c) 2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer/dsl/expression'
23
+ require 'glimmer/dsl/parent_expression'
24
+
25
+ module Glimmer
26
+ module DSL
27
+ module Swing
28
+ class ShapeExpression < Expression
29
+ include ParentExpression
30
+
31
+ def can_interpret?(parent, keyword, *args, &block)
32
+ Glimmer::Swing::ShapeProxy.exist?(keyword)
33
+ end
34
+
35
+ def interpret(parent, keyword, *args, &block)
36
+ Glimmer::Swing::ShapeProxy.create(parent, keyword, *args, &block)
37
+ end
38
+
39
+ def add_content(parent, keyword, *args, &block)
40
+ super
41
+ parent.post_add_content
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ require 'glimmer/swing/shape_proxy'
@@ -31,11 +31,21 @@ module Glimmer
31
31
  DEFAULT_WIDTH = 190
32
32
  DEFAULT_HEIGHT = 150
33
33
 
34
+ def set_minimum_size(*args)
35
+ @minimum_size_set = true
36
+ if args.size == 1 && args.first.is_a?(Java::JavaAwt::Dimension)
37
+ super
38
+ else
39
+ super(Java::JavaAwt::Dimension.new(*args))
40
+ end
41
+ end
42
+ alias minimum_size= set_minimum_size
43
+
34
44
  def post_add_content
35
45
  unless @initial_content_added
36
46
  @initial_content_added = true
37
- the_width = width == 0 ? DEFAULT_WIDTH : width
38
- the_height = height == 0 ? DEFAULT_HEIGHT : height
47
+ the_width = @minimum_size_set ? minimum_size.width : DEFAULT_WIDTH
48
+ the_height = @minimum_size_set ? minimum_size.height : DEFAULT_HEIGHT
39
49
  set_minimum_size(Java::JavaAwt::Dimension.new(the_width, the_height))
40
50
  set_default_close_operation(Java::JavaxSwing::JFrame::EXIT_ON_CLOSE)
41
51
  end
@@ -32,7 +32,7 @@ module Glimmer
32
32
 
33
33
  class << self
34
34
  def exist?(keyword)
35
- !!component_proxy_class(keyword)
35
+ !!component_class(keyword)
36
36
  end
37
37
 
38
38
  def create(parent, keyword, *args, &block)
@@ -70,10 +70,10 @@ module Glimmer
70
70
  end
71
71
 
72
72
  def component_class(keyword)
73
- unless flyweight_component_class.keys.include?(keyword)
73
+ unless flyweight_component_class[keyword]
74
74
  begin
75
- pd component_class_name = component_class_symbol(keyword).to_s
76
- pd component_class = eval(component_class_name)
75
+ component_class_name = component_class_symbol(keyword).to_s
76
+ component_class = eval(component_class_name)
77
77
  unless component_class.ancestors.include?(Java::JavaAwt::Component)
78
78
  component_class = component_class_manual_entries[keyword]
79
79
  if component_class.nil?
@@ -81,6 +81,25 @@ module Glimmer
81
81
  return nil
82
82
  end
83
83
  end
84
+ component_class = Class.new(component_class) {
85
+ attr_accessor :shape_proxies
86
+
87
+ def paint(g2)
88
+ super(g2)
89
+ shape_proxies.each do |shape_proxy|
90
+ original_color = g2.get_color
91
+ if shape_proxy.fill_color
92
+ g2.color = Color.new(shape_proxy.fill_color[:r], shape_proxy.fill_color[:g], shape_proxy.fill_color[:b], shape_proxy.fill_color[:a] || 255)
93
+ g2.fill(shape_proxy)
94
+ end
95
+ if shape_proxy.draw_color
96
+ g2.color = Color.new(shape_proxy.draw_color[:r], shape_proxy.draw_color[:g], shape_proxy.draw_color[:b], shape_proxy.draw_color[:a] || 255)
97
+ g2.draw(shape_proxy)
98
+ end
99
+ g2.color = original_color
100
+ end
101
+ end
102
+ }
84
103
  flyweight_component_class[keyword] = component_class
85
104
  rescue SyntaxError, NameError => e
86
105
  Glimmer::Config.logger.debug {e.full_message}
@@ -106,7 +125,7 @@ module Glimmer
106
125
  @keyword = keyword
107
126
  @args = args
108
127
  @block = block
109
- build_widget
128
+ build
110
129
  post_add_content if @block.nil?
111
130
  end
112
131
 
@@ -117,7 +136,15 @@ module Glimmer
117
136
 
118
137
  # Subclasses may override to perform post initialization work on an added child (normally must also call super)
119
138
  def post_initialize_child(child)
120
- add(child)
139
+ if child.is_a?(ComponentProxy)
140
+ add(child)
141
+ elsif child.is_a?(ShapeProxy)
142
+ shape_proxies << child
143
+ end
144
+ end
145
+
146
+ def shape_proxies
147
+ @shape_proxies ||= []
121
148
  end
122
149
 
123
150
  def respond_to?(method_name, *args, &block)
@@ -130,7 +157,9 @@ module Glimmer
130
157
  end
131
158
 
132
159
  def method_missing(method_name, *args, &block)
133
- if @original.respond_to?("set_#{method_name}", true) && !args.empty?
160
+ if respond_to?("#{method_name}=", true) && !args.empty?
161
+ send("#{method_name}=", *args)
162
+ elsif @original.respond_to?("set_#{method_name}", true) && !args.empty?
134
163
  send_to_original("set_#{method_name}", *args, &block)
135
164
  elsif @original.respond_to?(method_name, true)
136
165
  send_to_original(method_name, *args, &block)
@@ -224,10 +253,9 @@ module Glimmer
224
253
 
225
254
  private
226
255
 
227
- def build_widget
228
- pd keyword
229
- pd ComponentProxy.component_class(keyword)
256
+ def build
230
257
  @original = ComponentProxy.component_class(keyword).new(*normalize_args(args))
258
+ @original.shape_proxies = shape_proxies
231
259
  end
232
260
 
233
261
  def normalize_args(args)
@@ -240,3 +268,4 @@ module Glimmer
240
268
  end
241
269
 
242
270
  Dir[File.expand_path("./#{File.basename(__FILE__, '.rb')}/*.rb", __dir__)].each {|f| require f}
271
+ require 'glimmer/swing/shape_proxy'
@@ -0,0 +1,167 @@
1
+ # Copyright (c) 2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer/swing/packages'
23
+
24
+ module Glimmer
25
+ module Swing
26
+ # Proxy for Java2D shape objects
27
+ #
28
+ # Follows the Proxy Design Pattern
29
+ class ShapeProxy
30
+ include Packages
31
+
32
+ class << self
33
+ def exist?(keyword)
34
+ !!shape_class(keyword)
35
+ end
36
+
37
+ def create(parent, keyword, *args, &block)
38
+ shape_proxy_class(keyword).new(parent, keyword, *args, &block)
39
+ end
40
+
41
+ def shape_proxy_class(keyword)
42
+ begin
43
+ class_name = shape_proxy_class_symbol(keyword)
44
+ Glimmer::Swing::ShapeProxy.const_get(class_name)
45
+ rescue => e
46
+ Glimmer::Config.logger.debug e.full_message
47
+ Glimmer::Swing::ShapeProxy
48
+ end
49
+ end
50
+
51
+ def shape_proxy_class_symbol(keyword)
52
+ "#{keyword.camelcase(:upper)}Proxy".to_sym
53
+ end
54
+
55
+ def shape_class_symbol(keyword)
56
+ keyword.camelcase(:upper).to_sym
57
+ end
58
+
59
+ def keyword(shape_proxy_class)
60
+ shape_proxy_class.to_s.underscore.sub(/_proxy$/, '')
61
+ end
62
+
63
+ def shape_class_manual_entries
64
+ # add mappings for any classes (minus the namespace) that conflict with standard Ruby classes
65
+ {
66
+ # example:
67
+ # 'date_time' => Java::OrgEclipseSwtWidgets::DateTime
68
+ }
69
+ end
70
+
71
+ def shape_class(keyword)
72
+ unless flyweight_shape_class.keys.include?(keyword)
73
+ begin
74
+ shape_class_name = shape_class_symbol(keyword).to_s
75
+ shape_class = eval("#{shape_class_name}2D::Double") rescue eval(shape_class_name)
76
+ unless shape_class.ancestors.include?(Java::JavaAwt::Shape)
77
+ shape_class = shape_class_manual_entries[keyword]
78
+ if shape_class.nil?
79
+ Glimmer::Config.logger.debug {"Class #{shape_class} matching #{keyword} is not a subclass of java.awt.Component"}
80
+ return nil
81
+ end
82
+ end
83
+ flyweight_shape_class[keyword] = shape_class
84
+ rescue SyntaxError, NameError => e
85
+ Glimmer::Config.logger.debug {e.full_message}
86
+ nil
87
+ rescue => e
88
+ Glimmer::Config.logger.debug {e.full_message}
89
+ nil
90
+ end
91
+ end
92
+ flyweight_shape_class[keyword]
93
+ end
94
+
95
+ # Flyweight Design Pattern memoization cache. Can be cleared if memory is needed.
96
+ def flyweight_shape_class
97
+ @flyweight_shape_class ||= {}
98
+ end
99
+ end
100
+
101
+ attr_reader :parent_proxy, :original, :args, :keyword, :block
102
+ attr_accessor :draw_color, :fill_color
103
+
104
+ def initialize(parent, keyword, *args, &block)
105
+ @parent_proxy = parent
106
+ @keyword = keyword
107
+ @args = args
108
+ @block = block
109
+ build
110
+ post_add_content if @block.nil?
111
+ end
112
+
113
+ # Subclasses may override to perform post add_content work (normally must call super)
114
+ def post_add_content
115
+ @parent_proxy&.post_initialize_child(self)
116
+ end
117
+
118
+ # Subclasses may override to perform post initialization work on an added child (normally must also call super)
119
+ def post_initialize_child(child)
120
+ if child.is_a?(ShapeProxy)
121
+ add(child)
122
+ end
123
+ end
124
+
125
+ def respond_to?(method_name, *args, &block)
126
+ respond_to_original?(method_name, *args, &block) ||
127
+ super(method_name, true)
128
+ end
129
+
130
+ def respond_to_original?(method_name, *args, &block)
131
+ @original.respond_to?(method_name, true) || @original.respond_to?("set_#{method_name}", true)
132
+ end
133
+
134
+ def method_missing(method_name, *args, &block)
135
+ if @original.respond_to?("set_#{method_name}", true) && !args.empty?
136
+ send_to_original("set_#{method_name}", *args, &block)
137
+ elsif @original.respond_to?(method_name, true)
138
+ send_to_original(method_name, *args, &block)
139
+ else
140
+ super
141
+ end
142
+ end
143
+
144
+ def send_to_original(method_name, *args, &block)
145
+ @original.send(method_name, *normalize_args(args), &block)
146
+ end
147
+
148
+ def content(&block)
149
+ Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Swing::ShapeExpression.new, @keyword, &block)
150
+ end
151
+
152
+ private
153
+
154
+ def build
155
+ @original = ShapeProxy.shape_class(keyword).new(*normalize_args(args))
156
+ end
157
+
158
+ def normalize_args(args)
159
+ args.map do |arg|
160
+ arg.is_a?(ShapeProxy) ? arg.original : arg
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ Dir[File.expand_path("./#{File.basename(__FILE__, '.rb')}/*.rb", __dir__)].each {|f| require f}
@@ -36,8 +36,6 @@ require 'facets/string/camelcase'
36
36
  require 'facets/hash/stringify_keys'
37
37
 
38
38
  # Internal requires
39
- # require 'ext/glimmer/config'
40
- # require 'ext/glimmer'
41
39
  require 'glimmer/swing'
42
40
  require 'glimmer/swing/ext/glimmer'
43
41
  require 'glimmer/swing/ext/glimmer/config'
@@ -4,10 +4,10 @@ include Glimmer
4
4
 
5
5
  jframe('Hello, Button!') {
6
6
  @button = jbutton('Click To Increment: 0') {
7
- on_action_performed {
8
- button_text_match = @button.text.match(/(.*)(\d+)$/)
7
+ on_action_performed do
8
+ button_text_match = @button.text.match(/([^0-9]+)(\d+)$/)
9
9
  count = button_text_match[2].to_i + 1
10
10
  @button.text = "#{button_text_match[1]}#{count}"
11
- }
11
+ end
12
12
  }
13
13
  }.show
@@ -0,0 +1,49 @@
1
+ require 'glimmer-dsl-swing'
2
+
3
+ include Glimmer
4
+
5
+ jframe('Hello, Shapes!') {
6
+ minimum_size 400, 400
7
+
8
+ arc(40, 40, 90, 90, 30, 230, 0) {
9
+ fill_color r: 255, g: 0, b: 0
10
+ draw_color r: 0, g: 255, b: 255
11
+ }
12
+
13
+ arc(40, 140, 90, 90, 30, 230, 1) {
14
+ fill_color r: 255, g: 0, b: 0
15
+ draw_color r: 0, g: 255, b: 255
16
+ }
17
+
18
+ arc(40, 240, 90, 90, 30, 230, 2) {
19
+ fill_color r: 255, g: 0, b: 0
20
+ draw_color r: 0, g: 255, b: 255
21
+ }
22
+
23
+ ellipse(140, 40, 180, 90) {
24
+ fill_color r: 0, g: 255, b: 255
25
+ draw_color r: 255, g: 0, b: 0
26
+ }
27
+
28
+ rectangle(140, 140, 180, 90) {
29
+ fill_color r: 0, g: 255, b: 255
30
+ draw_color r: 255, g: 0, b: 0
31
+ }
32
+
33
+ round_rectangle(140, 240, 180, 90, 60, 40) {
34
+ fill_color r: 0, g: 255, b: 255
35
+ draw_color r: 255, g: 0, b: 0
36
+ }
37
+
38
+ line(180, 60, 280, 110) {
39
+ draw_color r: 0, g: 0, b: 0
40
+ }
41
+
42
+ quad_curve(170, 60, 180, 90, 220, 100) {
43
+ draw_color r: 0, g: 0, b: 0
44
+ }
45
+
46
+ cubic_curve(190, 60, 240, 40, 220, 80, 260, 70) {
47
+ draw_color r: 0, g: 0, b: 0
48
+ }
49
+ }.show
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-swing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
@@ -202,6 +202,7 @@ executables:
202
202
  - girb
203
203
  extensions: []
204
204
  extra_rdoc_files:
205
+ - CHANGELOG.md
205
206
  - LICENSE.txt
206
207
  - README.md
207
208
  files:
@@ -217,6 +218,7 @@ files:
217
218
  - lib/glimmer/dsl/swing/dsl.rb
218
219
  - lib/glimmer/dsl/swing/listener_expression.rb
219
220
  - lib/glimmer/dsl/swing/property_expression.rb
221
+ - lib/glimmer/dsl/swing/shape_expression.rb
220
222
  - lib/glimmer/swing.rb
221
223
  - lib/glimmer/swing/component_listener_proxy.rb
222
224
  - lib/glimmer/swing/component_proxy.rb
@@ -224,7 +226,9 @@ files:
224
226
  - lib/glimmer/swing/ext/glimmer.rb
225
227
  - lib/glimmer/swing/ext/glimmer/config.rb
226
228
  - lib/glimmer/swing/packages.rb
229
+ - lib/glimmer/swing/shape_proxy.rb
227
230
  - samples/hello/hello_button.rb
231
+ - samples/hello/hello_shapes.rb
228
232
  - samples/hello/hello_world.rb
229
233
  homepage: http://github.com/AndyObtiva/glimmer-dsl-swing
230
234
  licenses:
@@ -246,7 +250,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
246
250
  - !ruby/object:Gem::Version
247
251
  version: '0'
248
252
  requirements: []
249
- rubygems_version: 3.1.6
253
+ rubygems_version: 3.2.29
250
254
  signing_key:
251
255
  specification_version: 4
252
256
  summary: Glimmer DSL for Swing