glimmer-dsl-swt 4.18.2.0 → 4.18.2.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,6 +22,7 @@
22
22
  require 'glimmer'
23
23
  require 'glimmer/dsl/expression'
24
24
  require 'glimmer/dsl/parent_expression'
25
+ require 'glimmer/swt/custom/shape'
25
26
 
26
27
  module Glimmer
27
28
  module DSL
@@ -29,7 +30,7 @@ module Glimmer
29
30
  class WidgetExpression < Expression
30
31
  include ParentExpression
31
32
 
32
- EXCLUDED_KEYWORDS = %w[shell display tab_item]
33
+ EXCLUDED_KEYWORDS = %w[shell display tab_item] + Glimmer::SWT::Custom::Shape.keywords - ['text']
33
34
 
34
35
  def can_interpret?(parent, keyword, *args, &block)
35
36
  result = !EXCLUDED_KEYWORDS.include?(keyword) &&
@@ -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
@@ -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
@@ -28,9 +28,20 @@ module Glimmer
28
28
  #
29
29
  # Invoking `#swt_color` returns the SWT Color object wrapped by this proxy
30
30
  #
31
- # Follows the Proxy Design Pattern
31
+ # Follows the Proxy Design Pattern and Flyweight Design Pattern (caching memoization)
32
32
  class ColorProxy
33
33
  include_package 'org.eclipse.swt.graphics'
34
+
35
+ class << self
36
+ def flyweight(*args)
37
+ flyweight_color_proxies[args] ||= new(*args)
38
+ end
39
+
40
+ # Flyweight Design Pattern memoization cache. Can be cleared if memory is needed.
41
+ def flyweight_color_proxies
42
+ @flyweight_color_proxies ||= {}
43
+ end
44
+ end
34
45
 
35
46
  # Initializes a proxy for an SWT Color object
36
47
  #
@@ -49,6 +60,7 @@ module Glimmer
49
60
  #
50
61
  def initialize(*args)
51
62
  @args = args
63
+ ensure_arg_values_within_valid_bounds
52
64
  end
53
65
 
54
66
  def swt_color
@@ -64,7 +76,7 @@ module Glimmer
64
76
  end
65
77
  when 3..4
66
78
  red, green, blue, alpha = @args
67
- @swt_color = Color.new(DisplayProxy.instance.swt_display, *[red, green, blue, alpha].compact)
79
+ @swt_color = Color.new(*[red, green, blue, alpha].compact)
68
80
  end
69
81
  end
70
82
  @swt_color
@@ -79,7 +91,17 @@ module Glimmer
79
91
 
80
92
  def respond_to?(method, *args, &block)
81
93
  super || swt_color.respond_to?(method, *args, &block)
82
- end
94
+ end
95
+
96
+ private
97
+
98
+ def ensure_arg_values_within_valid_bounds
99
+ if @args.to_a.size >= 3
100
+ @args = @args.map do |value|
101
+ [[value, 255].min, 0].max
102
+ end
103
+ end
104
+ end
83
105
  end
84
106
  end
85
107
  end
@@ -34,6 +34,14 @@ module Glimmer
34
34
  shapes.delete(shape)
35
35
  end
36
36
  end
37
+
38
+ def resetup_shape_paint_listeners
39
+ # TODO consider performance optimizations relating to order of shape rendering (affecting only further shapes not previous ones)
40
+ shapes.each do |shape|
41
+ shape.paint_listener_proxy&.unregister
42
+ shape.setup_paint_listener
43
+ end
44
+ end
37
45
  end
38
46
 
39
47
  end
@@ -32,6 +32,7 @@ module Glimmer
32
32
  # swt_widget returns the parent (e.g. a `canvas` WidgetProxy), equivalent to `parent.swt_widget`
33
33
  # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
34
34
  class Shape
35
+ include Packages
35
36
  include Properties
36
37
  # TODO support textExtent sized shapes nested within text/string
37
38
  # TODO support a Pattern DSL for methods that take Pattern arguments
@@ -42,7 +43,17 @@ module Glimmer
42
43
  end
43
44
 
44
45
  def gc_instance_methods
45
- org.eclipse.swt.graphics.GC.instance_methods.map(&:to_s)
46
+ @gc_instance_methods ||= org.eclipse.swt.graphics.GC.instance_methods.map(&:to_s)
47
+ end
48
+
49
+ def keywords
50
+ @keywords ||= gc_instance_methods.select do |method_name|
51
+ !method_name.end_with?('=') && (method_name.start_with?('draw_') || method_name.start_with?('fill_'))
52
+ end.reject do |method_name|
53
+ gc_instance_methods.include?("#{method_name}=") || gc_instance_methods.include?("set_#{method_name}")
54
+ end.map do |method_name|
55
+ method_name.gsub(/(draw|fill|gradient|round)_/, '')
56
+ end.uniq.compact.to_a
46
57
  end
47
58
 
48
59
  def arg_options(args, extract: false)
@@ -52,11 +63,19 @@ module Glimmer
52
63
  end
53
64
 
54
65
  def method_name(keyword, args)
55
- keyword = keyword.to_s
56
- gradient = 'gradient_' if arg_options(args)[:gradient]
57
- round = 'round_' if arg_options(args)[:round]
58
- gc_instance_method_name_prefix = !['polyline', 'point', 'image', 'focus'].include?(keyword) && (arg_options(args)[:fill] || arg_options(args)[:gradient]) ? 'fill_' : 'draw_'
59
- "#{gc_instance_method_name_prefix}#{gradient}#{round}#{keyword}"
66
+ method_arg_options = arg_options(args)
67
+ unless flyweight_method_names.keys.include?([keyword, method_arg_options])
68
+ keyword = keyword.to_s
69
+ gradient = 'gradient_' if method_arg_options[:gradient]
70
+ round = 'round_' if method_arg_options[:round]
71
+ gc_instance_method_name_prefix = !['polyline', 'point', 'image', 'focus'].include?(keyword) && (method_arg_options[:fill] || method_arg_options[:gradient]) ? 'fill_' : 'draw_'
72
+ flyweight_method_names[[keyword, method_arg_options]] = "#{gc_instance_method_name_prefix}#{gradient}#{round}#{keyword}"
73
+ end
74
+ flyweight_method_names[[keyword, method_arg_options]]
75
+ end
76
+
77
+ def flyweight_method_names
78
+ @flyweight_method_names ||= {}
60
79
  end
61
80
  end
62
81
 
@@ -91,27 +110,11 @@ module Glimmer
91
110
  end
92
111
 
93
112
  def post_add_content
94
- event_handler = lambda do |event|
95
- @properties['background'] = [@parent.background] if fill? && !@properties.keys.map(&:to_s).include?('background')
96
- @properties['foreground'] = [@parent.foreground] if draw? && !@properties.keys.map(&:to_s).include?('foreground')
97
- @properties.each do |property, args|
98
- method_name = attribute_setter(property)
99
- apply_property_arg_conversions(method_name, args)
100
- event.gc.send(method_name, *args)
101
- end
102
- apply_shape_arg_conversions(@method_name, @args)
103
- apply_shape_arg_defaults(@method_name, @args)
104
- tolerate_shape_extra_args(@method_name, @args)
105
- event.gc.send(@method_name, *@args)
106
- end
107
- if parent.respond_to?(:swt_display)
108
- @paint_listener_proxy = @parent.on_swt_paint(&event_handler)
109
- else
110
- @paint_listener_proxy = @parent.on_paint_control(&event_handler)
111
- end
113
+ setup_paint_listener
114
+ @content_added = true
112
115
  end
113
116
 
114
- def apply_property_arg_conversions(method_name, args)
117
+ def apply_property_arg_conversions(method_name, property, args)
115
118
  the_java_method = org.eclipse.swt.graphics.GC.java_class.declared_instance_methods.detect {|m| m.name == method_name}
116
119
  if (args.first.is_a?(Symbol) || args.first.is_a?(String))
117
120
  if the_java_method.parameter_types.first == Color.java_class
@@ -142,6 +145,7 @@ module Glimmer
142
145
  args[0] = org.eclipse.swt.graphics.Pattern.new(*new_args)
143
146
  args[1..-1] = []
144
147
  end
148
+ @properties[property] = args
145
149
  end
146
150
 
147
151
  def apply_shape_arg_conversions(method_name, args)
@@ -159,6 +163,12 @@ module Glimmer
159
163
  elsif (method_name.include?('text') || method_name.include?('string')) && !@properties.keys.map(&:to_s).include?('background') && args.size == 3
160
164
  args << true
161
165
  end
166
+ if method_name.include?('image') && args.first.is_a?(String)
167
+ args[0] = ImageProxy.new(args[0])
168
+ end
169
+ if method_name.include?('image') && args.first.is_a?(ImageProxy)
170
+ args[0] = args[0].swt_image
171
+ end
162
172
  end
163
173
 
164
174
  # Tolerates shape extra args added by user by mistake
@@ -178,11 +188,38 @@ module Glimmer
178
188
 
179
189
  def set_attribute(attribute_name, *args)
180
190
  @properties[attribute_name] = args
191
+ if @content_added
192
+ @parent.resetup_shape_paint_listeners
193
+ @parent.redraw
194
+ end
181
195
  end
182
196
 
183
197
  def get_attribute(attribute_name)
184
198
  @properties.symbolize_keys[attribute_name.to_s.to_sym]
185
199
  end
200
+
201
+ def setup_paint_listener
202
+ if parent.respond_to?(:swt_display)
203
+ @paint_listener_proxy = @parent.on_swt_paint(&method(:paint))
204
+ else
205
+ @paint_listener_proxy = @parent.on_paint_control(&method(:paint))
206
+ end
207
+ end
208
+
209
+ def paint(paint_event)
210
+ @properties['background'] = [@parent.background] if fill? && !@properties.keys.map(&:to_s).include?('background')
211
+ @properties['foreground'] = [@parent.foreground] if draw? && !@properties.keys.map(&:to_s).include?('foreground')
212
+ @properties['font'] = [@parent.font] if draw? && !@properties.keys.map(&:to_s).include?('font')
213
+ @properties.each do |property, args|
214
+ method_name = attribute_setter(property)
215
+ apply_property_arg_conversions(method_name, property, args)
216
+ paint_event.gc.send(method_name, *args)
217
+ end
218
+ apply_shape_arg_conversions(@method_name, @args)
219
+ apply_shape_arg_defaults(@method_name, @args)
220
+ tolerate_shape_extra_args(@method_name, @args)
221
+ paint_event.gc.send(@method_name, *@args)
222
+ end
186
223
 
187
224
  end
188
225
 
@@ -45,7 +45,7 @@ module Glimmer
45
45
  class << self
46
46
  # Returns singleton instance
47
47
  def instance(*args)
48
- if @instance.nil? || @instance.swt_display.isDisposed
48
+ if @instance.nil? || @instance.swt_display.nil? || @instance.swt_display.isDisposed
49
49
  @instance = new(*args)
50
50
  end
51
51
  @instance
@@ -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
@@ -46,6 +46,7 @@ module Glimmer
46
46
  @swt_widget = swt_widget
47
47
  else
48
48
  if args.first.is_a?(ShellProxy)
49
+ @parent_proxy = args[0]
49
50
  args[0] = args[0].swt_widget
50
51
  end
51
52
  style_args = args.select {|arg| arg.is_a?(Symbol) || arg.is_a?(String)}
@@ -78,7 +79,7 @@ module Glimmer
78
79
  end
79
80
 
80
81
  # Centers shell within monitor it is in
81
- def center
82
+ def center_within_display
82
83
  primary_monitor = @display.getPrimaryMonitor()
83
84
  monitor_bounds = primary_monitor.getBounds()
84
85
  shell_bounds = @swt_widget.getBounds()
@@ -101,13 +102,13 @@ module Glimmer
101
102
  else
102
103
  @opened_before = true
103
104
  @swt_widget.pack
104
- center
105
+ center_within_display
105
106
  @swt_widget.open
106
107
  end
107
108
  end
108
109
 
109
110
  def nested?
110
- !parent.nil?
111
+ !swt_widget&.parent.nil?
111
112
  end
112
113
 
113
114
  def hide
@@ -74,12 +74,10 @@ module Glimmer
74
74
 
75
75
  DEFAULT_INITIALIZERS = {
76
76
  composite: lambda do |composite|
77
- if composite.get_layout.nil?
78
- layout = GridLayout.new
79
- layout.marginWidth = 15
80
- layout.marginHeight = 15
81
- composite.layout = layout
82
- end
77
+ composite.layout = GridLayout.new if composite.get_layout.nil?
78
+ end,
79
+ canvas: lambda do |canvas|
80
+ canvas.layout = nil unless canvas.get_layout.nil?
83
81
  end,
84
82
  scrolled_composite: lambda do |scrolled_composite|
85
83
  scrolled_composite.expand_horizontal = true
@@ -160,7 +158,7 @@ module Glimmer
160
158
  underscored_widget_name = self.class.underscored_widget_name(@swt_widget)
161
159
  parent_proxy_class = self.class.widget_proxy_class(self.class.underscored_widget_name(@swt_widget.parent))
162
160
  parent = swt_widget.parent
163
- @parent_proxy = parent.get_data('proxy') || parent_proxy_class.new(swt_widget: parent)
161
+ @parent_proxy = parent&.get_data('proxy') || parent_proxy_class.new(swt_widget: parent)
164
162
  end
165
163
  if @swt_widget&.get_data('proxy').nil?
166
164
  @swt_widget.set_data('proxy', self)
@@ -499,26 +497,37 @@ module Glimmer
499
497
 
500
498
  # This supports widgets in and out of basic SWT
501
499
  def self.swt_widget_class_for(underscored_widget_name)
502
- underscored_widget_name = KEYWORD_ALIASES[underscored_widget_name] if KEYWORD_ALIASES[underscored_widget_name]
503
- swt_widget_name = underscored_widget_name.camelcase(:upper)
504
- swt_widget_class = eval(swt_widget_name)
505
- # TODO fix issue with not detecting DateTime because it's conflicting with the Ruby DateTime
506
- unless swt_widget_class.ancestors.include?(org.eclipse.swt.widgets.Widget)
507
- swt_widget_class = swt_widget_class_manual_entries[underscored_widget_name]
508
- if swt_widget_class.nil?
509
- Glimmer::Config.logger.debug {"Class #{swt_widget_class} matching #{underscored_widget_name} is not a subclass of org.eclipse.swt.widgets.Widget"}
510
- return nil
500
+ # TODO clear memoization for a keyword if a custom widget was defined with that keyword
501
+ unless flyweight_swt_widget_classes.keys.include?(underscored_widget_name)
502
+ begin
503
+ underscored_widget_name = KEYWORD_ALIASES[underscored_widget_name] if KEYWORD_ALIASES[underscored_widget_name]
504
+ swt_widget_name = underscored_widget_name.camelcase(:upper)
505
+ swt_widget_class = eval(swt_widget_name)
506
+ # TODO fix issue with not detecting DateTime because it's conflicting with the Ruby DateTime
507
+ unless swt_widget_class.ancestors.include?(org.eclipse.swt.widgets.Widget)
508
+ swt_widget_class = swt_widget_class_manual_entries[underscored_widget_name]
509
+ if swt_widget_class.nil?
510
+ Glimmer::Config.logger.debug {"Class #{swt_widget_class} matching #{underscored_widget_name} is not a subclass of org.eclipse.swt.widgets.Widget"}
511
+ return nil
512
+ end
513
+ end
514
+ flyweight_swt_widget_classes[underscored_widget_name] = swt_widget_class
515
+ rescue SyntaxError, NameError => e
516
+ Glimmer::Config.logger.debug {e.full_message}
517
+ # Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
518
+ nil
519
+ rescue => e
520
+ Glimmer::Config.logger.debug {e.full_message}
521
+ # Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
522
+ nil
511
523
  end
512
524
  end
513
- swt_widget_class
514
- rescue SyntaxError, NameError => e
515
- Glimmer::Config.logger.debug {e.full_message}
516
- # Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
517
- nil
518
- rescue => e
519
- Glimmer::Config.logger.debug {e.full_message}
520
- # Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
521
- nil
525
+ flyweight_swt_widget_classes[underscored_widget_name]
526
+ end
527
+
528
+ # Flyweight Design Pattern memoization cache. Can be cleared if memory is needed.
529
+ def self.flyweight_swt_widget_classes
530
+ @flyweight_swt_widget_classes ||= {}
522
531
  end
523
532
 
524
533
  def async_exec(&block)