glimmer-dsl-swt 4.18.1.1 → 4.18.2.4

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.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2007-2021 Andy Maleh
2
- #
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -30,7 +30,8 @@ module Glimmer
30
30
  args.size > 0 and
31
31
  parent.respond_to?(:set_attribute) and
32
32
  parent.respond_to?(:has_attribute?) and
33
- parent.has_attribute?(keyword, *args)
33
+ parent.has_attribute?(keyword, *args) and
34
+ !(parent.respond_to?(:swt_widget) && parent.swt_widget.class == org.eclipse.swt.widgets.Canvas && keyword == 'image')
34
35
  end
35
36
 
36
37
  def interpret(parent, keyword, *args, &block)
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2007-2021 Andy Maleh
2
- #
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -27,7 +27,7 @@ module Glimmer
27
27
  module Package
28
28
  class << self
29
29
  attr_accessor :javapackager_extra_args
30
- alias jpackage_extra_args :javapackager_extra_args
30
+ alias jpackage_extra_args javapackager_extra_args
31
31
 
32
32
  def clean
33
33
  require 'fileutils'
@@ -48,7 +48,7 @@ module Glimmer
48
48
  FileUtils.mkdir_p('vendor/jars')
49
49
  command = "lock_jars --vendor-dir vendor/jars"
50
50
  puts command
51
- system command
51
+ system command
52
52
  end
53
53
 
54
54
  def config
@@ -78,18 +78,18 @@ module Glimmer
78
78
  else
79
79
  puts 'Warbler executable "warble" is missing!'
80
80
  end
81
- end
81
+ end
82
82
  end
83
83
 
84
84
  def jar
85
85
  FileUtils.mkdir_p('dist')
86
86
  puts "Generating JAR with Warbler..."
87
87
  system "jruby -S gem install warbler -v2.0.5 --no-document" unless warbler_exists?
88
- system('warble')
88
+ system('warble')
89
89
  end
90
90
 
91
91
  def native(native_type=nil, native_extra_args)
92
- puts "Generating native executable with javapackager/jpackage..."
92
+ puts "Generating native executable with javapackager/jpackage..."
93
93
  java_version = `java -version`
94
94
  puts "WARNING! Glimmer Packaging Pre-Requisite Java Version 1.8.0_241 Is Not Found!" unless java_version.include?('1.8.0_241')
95
95
  require 'facets/string/titlecase'
@@ -125,7 +125,7 @@ module Glimmer
125
125
  command += " #{ENV['JAVAPACKAGER_EXTRA_ARGS']} " if ENV['JAVAPACKAGER_EXTRA_ARGS']
126
126
  command += " #{native_extra_args} " if native_extra_args
127
127
  puts command
128
- system command
128
+ system command
129
129
  end
130
130
 
131
131
  private
@@ -42,6 +42,7 @@ module Glimmer
42
42
  *.gem
43
43
  *.rbc
44
44
  /.config
45
+ /.mvn/
45
46
  /coverage/
46
47
  /InstalledFiles
47
48
  /pkg/
@@ -97,9 +98,9 @@ module Glimmer
97
98
  .gladiator
98
99
 
99
100
  # Glimmer
100
- dist
101
- packages
102
- vendor/jars
101
+ /dist/
102
+ /packages/
103
+ /vendor/jars/
103
104
  MULTI_LINE_STRING
104
105
 
105
106
  GEMFILE = <<~MULTI_LINE_STRING
@@ -28,42 +28,126 @@ module Glimmer
28
28
  class Animation
29
29
  include Properties # TODO rename to Properties
30
30
 
31
+ class << self
32
+ def schedule_frame_animation(animation, &frame_animation_block)
33
+ frame_animation_queue(animation).prepend(frame_animation_block)
34
+ swt_display.async_exec do
35
+ frame_animation_queue(next_animation)&.pop&.call
36
+ end
37
+ end
38
+
39
+ def next_animation
40
+ animation = nil
41
+ while frame_animation_queues.values.reduce(:+)&.any? && (animation.nil? || frame_animation_queue(animation).last.nil?)
42
+ animation = frame_animation_queues.keys[next_animation_index]
43
+ frame_animation_queues.delete(animation) if frame_animation_queues.values.reduce(:+)&.any? && !animation.nil? && frame_animation_queue(animation).empty?
44
+ end
45
+ animation
46
+ end
47
+
48
+ def next_animation_index
49
+ next_schedule_index % frame_animation_queues.keys.size
50
+ end
51
+
52
+ def next_schedule_index
53
+ unless defined? @@next_schedule_index
54
+ @@next_schedule_index = 0
55
+ else
56
+ @@next_schedule_index += 1
57
+ end
58
+ end
59
+
60
+ def frame_animation_queues
61
+ unless defined? @@frame_animation_queues
62
+ @@frame_animation_queues = {}
63
+ end
64
+ @@frame_animation_queues
65
+ end
66
+
67
+ def frame_animation_queue(animation)
68
+ frame_animation_queues[animation] ||= []
69
+ end
70
+
71
+ def swt_display
72
+ unless defined? @@swt_display
73
+ @@swt_display = DisplayProxy.instance.swt_display
74
+ end
75
+ @@swt_display
76
+ end
77
+ end
78
+
31
79
  attr_reader :parent, :options, :frame_index, :cycle
32
80
  alias current_frame_index frame_index
33
- attr_accessor :frame_block, :every, :cycle_count, :frame_count, :started
81
+ attr_accessor :frame_block, :every, :cycle_count, :frame_count, :started, :duration_limit
82
+ alias started? started
34
83
  # TODO consider supporting an async: false option
35
84
 
36
85
  def initialize(parent)
37
86
  @parent = parent
38
87
  @started = true
39
88
  @frame_index = 0
89
+ @cycle_count_index = 0
90
+ @start_number = 0 # denotes the number of starts (increments on every start)
91
+ self.class.swt_display # ensures initializing variable to set from GUI thread
40
92
  end
41
93
 
42
94
  def post_add_content
43
95
  @parent.on_widget_disposed { stop }
44
- start if @started
96
+ start if started?
45
97
  end
46
98
 
99
+ # Starts an animation that is indefinite or has never been started before (i.e. having `started: false` option).
100
+ # Otherwise, resumes a stopped animation that has not been completed.
47
101
  def start
48
- swt_display = DisplayProxy.instance.swt_display
102
+ return if @start_number > 0 && started?
103
+ @start_number += 1
104
+ @started = true
105
+ @start_time = Time.now
106
+ @original_start_time = @start_time if @duration.nil?
107
+ # TODO track when finished in a variable for finite animations (whether by frame count, cycle count, or duration limit)
49
108
  Thread.new do
109
+ start_number = @start_number
50
110
  if cycle_count.is_a?(Integer) && cycle.is_a?(Array)
51
111
  (cycle_count * cycle.length).times do
52
- break unless draw_frame(swt_display)
112
+ break unless draw_frame(start_number)
53
113
  end
54
114
  else
55
115
  loop do
56
116
  # this code has to be duplicated to break from a loop (break keyword only works when literally in a loop block)
57
- break unless draw_frame(swt_display)
117
+ break unless draw_frame(start_number)
58
118
  end
59
119
  end
60
- @started = false
61
120
  end
62
121
  end
63
122
 
64
123
  def stop
124
+ return if stopped?
65
125
  @started = false
126
+ @duration = (Time.now - @start_time) + @duration.to_f if duration_limited? && !@start_time.nil?
127
+ end
128
+
129
+ # Restarts an animation (whether indefinite or not and whether stopped or not)
130
+ def restart
131
+ @original_start_time = @start_time = nil
132
+ @duration = nil
133
+ @frame_index = 0
134
+ @cycle_count_index = 0
135
+ stop
136
+ start
137
+ end
138
+
139
+ def stopped?
140
+ !started?
141
+ end
142
+
143
+ def finite?
144
+ frame_count_limited? || cycle_limited? || duration_limited?
145
+ end
146
+
147
+ def infinite?
148
+ !finite?
66
149
  end
150
+ alias indefinite? infinite?
67
151
 
68
152
  def has_attribute?(attribute_name, *args)
69
153
  respond_to?(ruby_attribute_setter(attribute_name)) && respond_to?(ruby_attribute_getter(attribute_name))
@@ -89,21 +173,60 @@ module Glimmer
89
173
  end
90
174
  end
91
175
 
176
+ def cycle_enabled?
177
+ @cycle.is_a?(Array)
178
+ end
179
+
180
+ def cycle_limited?
181
+ cycle_enabled? && @cycle_count.is_a?(Integer)
182
+ end
183
+
184
+ def duration_limited?
185
+ @duration_limit.is_a?(Integer)
186
+ end
187
+
188
+ def frame_count_limited?
189
+ @frame_count.is_a?(Integer)
190
+ end
191
+
192
+ def surpassed_duration_limit?
193
+ duration_limited? && ((Time.now - @start_time) > (@duration_limit - @duration.to_f))
194
+ end
195
+
196
+ def within_duration_limit?
197
+ !surpassed_duration_limit?
198
+ end
199
+
92
200
  private
93
201
 
94
202
  # Returns true on success of painting a frame and false otherwise
95
- def draw_frame(swt_display)
96
- return false if !@started || (@frame_count.is_a?(Integer) && @frame_index == @frame_count)
203
+ def draw_frame(start_number)
204
+ return false if stopped? ||
205
+ start_number != @start_number ||
206
+ (frame_count_limited? && @frame_index == @frame_count) ||
207
+ (cycle_limited? && @cycle_count_index == @cycle_count) ||
208
+ surpassed_duration_limit?
97
209
  block_args = [@frame_index]
98
- block_args << @cycle[@frame_index % @cycle.length] if @cycle.is_a?(Array)
99
- swt_display.async_exec do
100
- @parent.clear_shapes
101
- @parent.content {
102
- frame_block.call(*block_args)
103
- }
104
- @parent.redraw
210
+ block_args << @cycle[@frame_index % @cycle.length] if cycle_enabled?
211
+ current_frame_index = @frame_index
212
+ current_cycle_count_index = @cycle_count_index
213
+ self.class.schedule_frame_animation(self) do
214
+ if started? && start_number == @start_number && within_duration_limit?
215
+ @parent.clear_shapes
216
+ @parent.content {
217
+ frame_block.call(*block_args)
218
+ }
219
+ @parent.redraw
220
+ else
221
+ if stopped? && @frame_index > current_frame_index
222
+ @started = false
223
+ @frame_index = current_frame_index
224
+ @cycle_count_index = current_cycle_count_index
225
+ end
226
+ end
105
227
  end
106
228
  @frame_index += 1
229
+ @cycle_count_index += 1 if cycle_limited? && (@frame_index % @cycle&.length&.to_i) == 0
107
230
  sleep(every) if every.is_a?(Numeric)
108
231
  true
109
232
  rescue => e
@@ -61,11 +61,12 @@ module Glimmer
61
61
 
62
62
  before_body {
63
63
  @swt_style = swt_style == 0 ? [:border, :multi, :v_scroll, :h_scroll] : swt_style
64
+ @font_name = display.get_font_list(nil, true).map(&:name).include?('Consolas') ? 'Consolas' : 'Courier'
64
65
  }
65
66
 
66
67
  body {
67
68
  styled_text(swt_style) {
68
- font name: 'Consolas', height: 15
69
+ font name: @font_name, height: 15
69
70
  foreground rgb(75, 75, 75)
70
71
  left_margin 5
71
72
  top_margin 5
@@ -20,6 +20,10 @@
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
22
  require 'glimmer/swt/properties'
23
+ require 'glimmer/swt/swt_proxy'
24
+ require 'glimmer/swt/display_proxy'
25
+ require 'glimmer/swt/color_proxy'
26
+ require 'glimmer/swt/font_proxy'
23
27
 
24
28
  module Glimmer
25
29
  module SWT
@@ -28,8 +32,9 @@ module Glimmer
28
32
  # swt_widget returns the parent (e.g. a `canvas` WidgetProxy), equivalent to `parent.swt_widget`
29
33
  # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
30
34
  class Shape
35
+ include Packages
31
36
  include Properties
32
- # TODO support textExtent as an option
37
+ # TODO support textExtent sized shapes nested within text/string
33
38
  # TODO support a Pattern DSL for methods that take Pattern arguments
34
39
 
35
40
  class << self
@@ -48,8 +53,11 @@ module Glimmer
48
53
  end
49
54
 
50
55
  def method_name(keyword, args)
51
- gc_instance_method_name_prefix = arg_options(args)[:fill] ? 'fill_' : 'draw_'
52
- "#{gc_instance_method_name_prefix}#{keyword}"
56
+ keyword = keyword.to_s
57
+ gradient = 'gradient_' if arg_options(args)[:gradient]
58
+ round = 'round_' if arg_options(args)[:round]
59
+ gc_instance_method_name_prefix = !['polyline', 'point', 'image', 'focus'].include?(keyword) && (arg_options(args)[:fill] || arg_options(args)[:gradient]) ? 'fill_' : 'draw_'
60
+ "#{gc_instance_method_name_prefix}#{gradient}#{round}#{keyword}"
53
61
  end
54
62
  end
55
63
 
@@ -67,18 +75,26 @@ module Glimmer
67
75
  post_add_content if property_block.nil?
68
76
  end
69
77
 
78
+ def draw?
79
+ !fill?
80
+ end
81
+
70
82
  def fill?
71
- !draw?
83
+ @options[:fill]
72
84
  end
73
85
 
74
- def draw?
75
- !@options[:fill]
86
+ def gradient?
87
+ @options[:gradient]
88
+ end
89
+
90
+ def round?
91
+ @options[:round]
76
92
  end
77
93
 
78
94
  def post_add_content
79
95
  event_handler = lambda do |event|
80
- @properties['background'] = [DisplayProxy.instance.get_system_color(SWTProxy(:color_widget_background))] if fill? && !@properties.keys.map(&:to_s).include?('background')
81
- @properties['foreground'] = [ColorProxy.new(0, 0, 0)] if draw? && !@properties.keys.map(&:to_s).include?('foreground')
96
+ @properties['background'] = [@parent.background] if fill? && !@properties.keys.map(&:to_s).include?('background')
97
+ @properties['foreground'] = [@parent.foreground] if draw? && !@properties.keys.map(&:to_s).include?('foreground')
82
98
  @properties.each do |property, args|
83
99
  method_name = attribute_setter(property)
84
100
  apply_property_arg_conversions(method_name, args)
@@ -86,6 +102,7 @@ module Glimmer
86
102
  end
87
103
  apply_shape_arg_conversions(@method_name, @args)
88
104
  apply_shape_arg_defaults(@method_name, @args)
105
+ tolerate_shape_extra_args(@method_name, @args)
89
106
  event.gc.send(@method_name, *@args)
90
107
  end
91
108
  if parent.respond_to?(:swt_display)
@@ -102,7 +119,7 @@ module Glimmer
102
119
  args[0] = ColorProxy.new(args[0])
103
120
  end
104
121
  if the_java_method.parameter_types.first == Java::int.java_class
105
- args[0] = SWTProxy[args[0]]
122
+ args[0] = SWTProxy.constant(args[0])
106
123
  end
107
124
  end
108
125
  if args.first.is_a?(ColorProxy)
@@ -114,6 +131,18 @@ module Glimmer
114
131
  if args.first.is_a?(FontProxy)
115
132
  args[0] = args[0].swt_font
116
133
  end
134
+ if ['setBackgroundPattern', 'setForegroundPattern'].include?(method_name.to_s)
135
+ args.each_with_index do |arg, i|
136
+ if arg.is_a?(Symbol) || arg.is_a?(String)
137
+ args[i] = ColorProxy.new(arg).swt_color
138
+ elsif arg.is_a?(ColorProxy)
139
+ args[i] = arg.swt_color
140
+ end
141
+ end
142
+ new_args = [DisplayProxy.instance.swt_display] + args
143
+ args[0] = org.eclipse.swt.graphics.Pattern.new(*new_args)
144
+ args[1..-1] = []
145
+ end
117
146
  end
118
147
 
119
148
  def apply_shape_arg_conversions(method_name, args)
@@ -126,18 +155,35 @@ module Glimmer
126
155
  def apply_shape_arg_defaults(method_name, args)
127
156
  if method_name.include?('round_rectangle') && args.size.between?(4, 5)
128
157
  (6 - args.size).times {args << 60}
129
- elsif method_name.include?('gradient_rectangle') && args.size == 4
158
+ elsif method_name.include?('rectangle') && gradient? && args.size == 4
159
+ args << true
160
+ elsif (method_name.include?('text') || method_name.include?('string')) && !@properties.keys.map(&:to_s).include?('background') && args.size == 3
130
161
  args << true
131
162
  end
163
+ if method_name.include?('image') && args.first.is_a?(String)
164
+ args[0] = ImageProxy.new(args[0])
165
+ end
166
+ if method_name.include?('image') && args.first.is_a?(ImageProxy)
167
+ args[0] = args[0].swt_image
168
+ end
169
+ end
170
+
171
+ # Tolerates shape extra args added by user by mistake
172
+ # (e.g. happens when switching from round rectangle to a standard one without removing all extra args)
173
+ def tolerate_shape_extra_args(method_name, args)
174
+ the_java_method_arg_count = org.eclipse.swt.graphics.GC.java_class.declared_instance_methods.select do |m|
175
+ m.name == method_name.camelcase(:lower)
176
+ end.map(&:parameter_types).map(&:size).max
177
+ if args.size > the_java_method_arg_count
178
+ args[the_java_method_arg_count..-1] = []
179
+ end
132
180
  end
133
181
 
134
182
  def has_attribute?(attribute_name, *args)
135
- # TODO test that attribute getter responds too
136
183
  self.class.gc_instance_methods.include?(attribute_setter(attribute_name))
137
184
  end
138
185
 
139
186
  def set_attribute(attribute_name, *args)
140
- # TODO special treatment for color symbols
141
187
  @properties[attribute_name] = args
142
188
  end
143
189