glimmer-dsl-swt 4.17.2.2 → 4.17.4.1

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.
@@ -0,0 +1,95 @@
1
+ require 'glimmer/ui/custom_widget'
2
+
3
+ module Glimmer
4
+ module SWT
5
+ module Custom
6
+ # CodeText is a customization of StyledText with support for Ruby Syntax Highlighting
7
+ class CodeText
8
+ include Glimmer::UI::CustomWidget
9
+
10
+ SYNTAX_COLOR_MAP = {
11
+ Builtin: [215,58,73],
12
+ Class: [3,47,98],
13
+ Constant: [0,92,197],
14
+ Double: [0,92,197],
15
+ Escape: [:red],
16
+ Function: [:blue],
17
+ Instance: [227,98,9],
18
+ Integer: [:blue],
19
+ Interpol: [:blue],
20
+ Keyword: [:blue],
21
+ Name: [111,66,193], #purple
22
+ Operator: [:red],
23
+ Pseudo: [:dark_red],
24
+ Punctuation: [:blue],
25
+ Single: [106,115,125], # Also, Comments
26
+ Symbol: [:dark_green],
27
+ Text: [75, 75, 75],
28
+ }
29
+
30
+ # TODO support `option :language`
31
+ # TODO support auto language detection
32
+
33
+ def text=(value)
34
+ swt_widget&.text = value
35
+ end
36
+
37
+ def text
38
+ swt_widget&.text
39
+ end
40
+
41
+ def syntax_highlighting
42
+ return [] if text.to_s.strip.empty?
43
+ code = text
44
+ return @syntax_highlighting if @last_code == code
45
+ @last_code = code
46
+ lexer = Rouge::Lexer.find_fancy('ruby', code)
47
+ lex = lexer.lex(code).to_a
48
+ code_size = 0
49
+ lex_hashes = lex.map do |pair|
50
+ {token_type: pair.first, token_text: pair.last}
51
+ end.each do |hash|
52
+ hash[:token_index] = code_size
53
+ code_size += hash[:token_text].size
54
+ end
55
+ code_lines = code.split("\n")
56
+ line_index = 0
57
+ @syntax_highlighting = code_lines_map = code_lines.reduce({}) do |hash, line|
58
+ line_hashes = []
59
+ line_hashes << lex_hashes.shift while lex_hashes.any? && lex_hashes.first[:token_index].between?(line_index, line_index + line.size)
60
+ hash.merge(line_index => line_hashes).tap do
61
+ line_index += line.size + 1
62
+ end
63
+ end
64
+ end
65
+
66
+ before_body {
67
+ @swt_style = swt_style == 0 ? [:border, :multi, :v_scroll, :h_scroll] : swt_style
68
+ }
69
+
70
+ body {
71
+ styled_text(swt_style) {
72
+ font name: 'Consolas', height: 15
73
+ foreground rgb(75, 75, 75)
74
+ left_margin 5
75
+ top_margin 5
76
+ right_margin 5
77
+ bottom_margin 5
78
+
79
+ on_line_get_style { |line_style_event|
80
+ styles = []
81
+ syntax_highlighting[line_style_event.lineOffset].to_a.each do |token_hash|
82
+ start_index = token_hash[:token_index]
83
+ size = token_hash[:token_text].size
84
+ token_color = SYNTAX_COLOR_MAP[token_hash[:token_type].name] || [:black]
85
+ token_color = color(*token_color).swt_color
86
+ styles << StyleRange.new(start_index, size, token_color, nil)
87
+ end
88
+ line_style_event.styles = styles.to_java(StyleRange) unless styles.empty?
89
+ }
90
+ }
91
+ }
92
+ end
93
+ end
94
+ end
95
+ end
@@ -27,10 +27,20 @@ module Glimmer
27
27
  #
28
28
  # Follows the Proxy Design Pattern
29
29
  class ImageProxy
30
+ class << self
31
+ def create(*args)
32
+ if args.size == 1 && args.first.is_a?(ImageProxy)
33
+ args.first
34
+ else
35
+ new(*args)
36
+ end
37
+ end
38
+ end
39
+
30
40
  include_package 'org.eclipse.swt.graphics'
31
41
 
32
42
  attr_reader :file_path, :jar_file_path, :image_data, :swt_image
33
-
43
+
34
44
  # Initializes a proxy for an SWT Image object
35
45
  #
36
46
  # Takes the same args as the SWT Image class
@@ -38,28 +48,41 @@ module Glimmer
38
48
  # and returns an image object.
39
49
  def initialize(*args)
40
50
  @args = args
41
- @file_path = @args.first if @args.first.is_a?(String) && @args.size == 1
42
- if @file_path
43
- if @file_path.start_with?('uri:classloader')
44
- @jar_file_path = @file_path
45
- @file_path = @jar_file_path.sub(/^uri\:classloader\:/, '').sub('//', '/') # the latter sub is needed for Mac
46
- object = java.lang.Object.new
47
- file_input_stream = object.java_class.resource_as_stream(file_path)
48
- buffered_file_input_stream = java.io.BufferedInputStream.new(file_input_stream)
49
- end
50
- @image_data = ImageData.new(buffered_file_input_stream || @file_path)
51
+ options = @args.last.is_a?(Hash) ? @args.delete_at(-1) : {}
52
+ options[:swt_image] = @args.first if @args.size == 1 && @args.first.is_a?(Image)
53
+ @file_path = @args.first if @args.size == 1 && @args.first.is_a?(String)
54
+ @args = @args.first if @args.size == 1 && @args.first.is_a?(Array)
55
+ if options&.keys&.include?(:swt_image)
56
+ @swt_image = options[:swt_image]
57
+ @image_data = @swt_image.image_data
58
+ elsif @file_path
59
+ @image_data = ImageData.new(input_stream || @file_path)
51
60
  @swt_image = Image.new(DisplayProxy.instance.swt_display, @image_data)
52
61
  else
53
62
  @swt_image = Image.new(*@args)
54
63
  @image_data = @swt_image.image_data
55
64
  end
56
65
  end
66
+
67
+ def input_stream
68
+ if @file_path.start_with?('uri:classloader')
69
+ @jar_file_path = @file_path
70
+ file_path = @jar_file_path.sub(/^uri\:classloader\:/, '').sub('//', '/') # the latter sub is needed for Mac
71
+ object = java.lang.Object.new
72
+ file_input_stream = object.java_class.resource_as_stream(file_path)
73
+ else
74
+ file_input_stream = java.io.FileInputStream.new(@file_path)
75
+ end
76
+ java.io.BufferedInputStream.new(file_input_stream) if file_input_stream
77
+ end
57
78
 
58
79
  def scale_to(width, height)
59
80
  scaled_image_data = image_data.scaledTo(width, height)
60
81
  device = swt_image.device
61
82
  swt_image.dispose
62
83
  @swt_image = Image.new(device, scaled_image_data)
84
+ @image_data = @swt_image.image_data
85
+ self
63
86
  end
64
87
 
65
88
  def method_missing(method, *args, &block)
@@ -26,7 +26,7 @@ require 'glimmer/swt/shell_proxy'
26
26
 
27
27
  module Glimmer
28
28
  module SWT
29
- # Proxy for org.eclipse.swt.widgets.Shell
29
+ # Proxy for org.eclipse.swt.widgets.MessageBox
30
30
  #
31
31
  # Follows the Proxy Design Pattern
32
32
  class MessageBoxProxy
@@ -0,0 +1,53 @@
1
+ # Copyright (c) 2007-2020 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/swt/widget_proxy'
23
+
24
+ module Glimmer
25
+ module SWT
26
+ # Proxy for org.eclipse.swt.custom.SashForm
27
+ #
28
+ # Follows the Proxy Design Pattern
29
+ class SashFormProxy < WidgetProxy
30
+ def post_add_content
31
+ swt_widget.setWeights(@weights) unless @weights.nil?
32
+ end
33
+
34
+ def set_attribute(attribute_name, *args)
35
+ if attribute_name.to_s == "weights"
36
+ @weights = args
37
+ @weights = @weights.first if @weights.first.is_a?(Array)
38
+ else
39
+ super(attribute_name, *args)
40
+ end
41
+ end
42
+
43
+ def get_attribute(attribute_name)
44
+ if attribute_name.to_s == "weights"
45
+ swt_widget.getWeights.to_a
46
+ else
47
+ super(attribute_name)
48
+ end
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -128,7 +128,7 @@ module Glimmer
128
128
  def deconstruct(integer)
129
129
  constant_source_class.constants.reduce([]) do |found, c|
130
130
  constant_value = constant_source_class.const_get(c) rescue -1
131
- is_found = constant_value.is_a?(Integer) && (integer & constant_value) == integer
131
+ is_found = constant_value.is_a?(Integer) && (integer & constant_value) == constant_value
132
132
  is_found ? found += [c] : found
133
133
  end
134
134
  end
@@ -136,6 +136,7 @@ module Glimmer
136
136
  # Reverse engineer a style integer into a symbol
137
137
  # Useful for debugging
138
138
  def reverse_lookup(integer)
139
+ # TODO support looking up compound style mixes
139
140
  constant_source_class.constants.reduce([]) do |found, c|
140
141
  constant_value = constant_source_class.const_get(c) rescue -1
141
142
  is_found = constant_value.is_a?(Integer) && integer == constant_value
@@ -23,6 +23,7 @@ require 'glimmer/swt/widget_listener_proxy'
23
23
  require 'glimmer/swt/color_proxy'
24
24
  require 'glimmer/swt/font_proxy'
25
25
  require 'glimmer/swt/swt_proxy'
26
+ require 'glimmer/swt/display_proxy'
26
27
  require 'glimmer/swt/dnd_proxy'
27
28
  require 'glimmer/swt/image_proxy'
28
29
 
@@ -54,7 +55,7 @@ module Glimmer
54
55
  "radio" => [:radio],
55
56
  "scrolled_composite" => [:border, :h_scroll, :v_scroll],
56
57
  "spinner" => [:border],
57
- "styled_text" => [:border],
58
+ "styled_text" => [:border, :multi, :v_scroll, :h_scroll],
58
59
  "table" => [:virtual, :border, :full_selection],
59
60
  "text" => [:border],
60
61
  "toggle" => [:toggle],
@@ -204,7 +205,7 @@ module Glimmer
204
205
  widget_custom_attribute = widget_custom_attribute_mapping[attribute_name.to_s]
205
206
  if widget_custom_attribute
206
207
  widget_custom_attribute[:setter][:invoker].call(@swt_widget, args)
207
- elsif @swt_widget.respond_to?(attribute_setter(attribute_name), args)
208
+ elsif @swt_widget.respond_to?(attribute_setter(attribute_name))
208
209
  apply_property_type_converters(attribute_name, args)
209
210
  @swt_widget.send(attribute_setter(attribute_name), *args) unless @swt_widget.send(attribute_getter(attribute_name)) == args.first
210
211
  else
@@ -328,6 +329,57 @@ module Glimmer
328
329
  observer.call(@swt_widget.getText)
329
330
  }
330
331
  end,
332
+ :caret_position => lambda do |observer|
333
+ on_swt_keydown { |event|
334
+ observer.call(@swt_widget.getCaretPosition)
335
+ }
336
+ on_swt_keyup { |event|
337
+ observer.call(@swt_widget.getCaretPosition)
338
+ }
339
+ on_swt_mousedown { |event|
340
+ observer.call(@swt_widget.getCaretPosition)
341
+ }
342
+ on_swt_mouseup { |event|
343
+ observer.call(@swt_widget.getCaretPosition)
344
+ }
345
+ end,
346
+ :selection => lambda do |observer|
347
+ on_swt_keydown { |event|
348
+ observer.call(@swt_widget.getSelection)
349
+ }
350
+ on_swt_keyup { |event|
351
+ observer.call(@swt_widget.getSelection)
352
+ }
353
+ on_swt_mousedown { |event|
354
+ observer.call(@swt_widget.getSelection)
355
+ }
356
+ on_swt_mouseup { |event|
357
+ observer.call(@swt_widget.getSelection)
358
+ }
359
+ end,
360
+ :selection_count => lambda do |observer|
361
+ on_swt_keydown { |event|
362
+ observer.call(@swt_widget.getSelectionCount)
363
+ }
364
+ on_swt_keyup { |event|
365
+ observer.call(@swt_widget.getSelectionCount)
366
+ }
367
+ on_swt_mousedown { |event|
368
+ observer.call(@swt_widget.getSelectionCount)
369
+ }
370
+ on_swt_mouseup { |event|
371
+ observer.call(@swt_widget.getSelectionCount)
372
+ }
373
+ end,
374
+ :top_index => lambda do |observer|
375
+ @last_top_index = @swt_widget.getTopIndex
376
+ on_paint_control { |event|
377
+ if @swt_widget.getTopIndex != @last_top_index
378
+ @last_top_index = @swt_widget.getTopIndex
379
+ observer.call(@last_top_index)
380
+ end
381
+ }
382
+ end,
331
383
  },
332
384
  Java::OrgEclipseSwtWidgets::Button => {
333
385
  :selection => lambda do |observer|
@@ -619,7 +671,11 @@ module Glimmer
619
671
  },
620
672
  'selection_count' => {
621
673
  getter: {name: 'getSelectionCount'},
622
- setter: {name: 'setSelection', invoker: lambda { |widget, args| @swt_widget.setSelection(@swt_widget.getCaretPosition, @swt_widget.getCaretPosition + args.first) if args.first }},
674
+ setter: {name: 'setSelection', invoker: lambda { |widget, args|
675
+ # TODO consider the idea of aliasing getCaretPosition in StyledText
676
+ caret_position = @swt_widget.getCaretPosition rescue @swt_widget.getCaretOffset
677
+ @swt_widget.setSelection(caret_position, caret_position + args.first) if args.first
678
+ }},
623
679
  },
624
680
  }
625
681
  end
@@ -683,21 +739,45 @@ module Glimmer
683
739
  },
684
740
  :background => color_converter,
685
741
  :background_image => lambda do |value|
686
- image_proxy = nil
687
- if value.is_a?(String)
688
- image_proxy = ImageProxy.new(value)
689
- elsif value.is_a?(Array)
690
- image_proxy = ImageProxy.new(*value)
691
- end
692
- if image_proxy
742
+ image_proxy = ImageProxy.create(value)
743
+
744
+ if image_proxy&.file_path&.end_with?('.gif')
745
+ image = image_proxy.swt_image
746
+ width = image.get_bounds.width.to_i
747
+ height = image.get_bounds.height.to_i
748
+ image_number = 0
749
+ loader = ImageLoader.new
750
+ loader.load(image_proxy.input_stream)
751
+ image.dispose
752
+ image = org.eclipse.swt.graphics.Image.new(DisplayProxy.instance.swt_display,loader.data[0].scaledTo(width, height))
753
+ gc = org.eclipse.swt.graphics.GC.new(image)
754
+ on_paint_control { |event|
755
+ image_number = (image_number == loader.data.length - 1) ? 0 : image_number + 1
756
+ next_frame_data = loader.data[image_number]
757
+ image = org.eclipse.swt.graphics.Image.new(DisplayProxy.instance.swt_display, next_frame_data.scaledTo(width, height))
758
+ event.gc.drawImage(image, 0, 0, width, height, 0, 0, width, height)
759
+ image.dispose
760
+ }
761
+ Thread.new {
762
+ last_image_number = -1
763
+ while last_image_number != image_number
764
+ last_image_number = image_number
765
+ sync_exec {
766
+ redraw
767
+ }
768
+ delayTime = loader.data[image_number].delayTime.to_f / 100.0
769
+ sleep(delayTime)
770
+ end
771
+ };
772
+ image_proxy = nil
773
+ else
693
774
  on_swt_Resize do |resize_event|
694
775
  image_proxy.scale_to(@swt_widget.getSize.x, @swt_widget.getSize.y)
695
- @swt_widget.setBackgroundImage(image_proxy.swt_image)
696
- end
697
- image_proxy.swt_image
698
- else
699
- value
700
- end
776
+ @swt_widget.setBackgroundImage(image_proxy.swt_image)
777
+ end
778
+ end
779
+
780
+ image_proxy&.swt_image
701
781
  end,
702
782
  :cursor => lambda do |value|
703
783
  cursor_proxy = nil
@@ -718,34 +798,18 @@ module Glimmer
718
798
  end
719
799
  end,
720
800
  :image => lambda do |value|
721
- if value.is_a?(String)
722
- ImageProxy.new(value).swt_image
723
- elsif value.is_a?(Array)
724
- ImageProxy.new(*value).swt_image
725
- else
726
- value
727
- end
801
+ ImageProxy.create(value).swt_image
728
802
  end,
729
803
  :images => lambda do |array|
730
804
  array.to_a.map do |value|
731
- if value.is_a?(String)
732
- ImageProxy.new(value).swt_image
733
- elsif value.is_a?(Array)
734
- ImageProxy.new(*value).swt_image
735
- else
736
- value
737
- end
805
+ ImageProxy.create(value).swt_image
738
806
  end.to_java(Image)
739
807
  end,
740
808
  :items => lambda do |value|
741
809
  value.to_java :string
742
810
  end,
743
811
  :text => lambda do |value|
744
- if swt_widget.is_a?(Browser)
745
- value.to_s
746
- else
747
- value.to_s
748
- end
812
+ value.to_s
749
813
  end,
750
814
  :transfer => lambda do |value|
751
815
  value = value.first if value.is_a?(Array) && value.size == 1 && value.first.is_a?(Array)
@@ -0,0 +1,166 @@
1
+ class Sample
2
+ attr_accessor :sample_directory, :file, :selected
3
+
4
+ def initialize(file, sample_directory: )
5
+ self.file = file
6
+ self.sample_directory = sample_directory
7
+ end
8
+
9
+ def name
10
+ if @name.nil?
11
+ @name = File.basename(file, '.rb').split('_').map(&:capitalize).join(' ')
12
+ if @name.start_with?('Hello')
13
+ name_parts = @name.split
14
+ name_parts[0] = name_parts.first + ','
15
+ name_parts[-1] = name_parts.last + '!'
16
+ @name = name_parts.join(' ')
17
+ end
18
+ end
19
+ @name
20
+ end
21
+
22
+ def content
23
+ @content ||= File.read(file)
24
+ end
25
+
26
+ def launch
27
+ load file
28
+ end
29
+ end
30
+
31
+ class SampleDirectory
32
+ class << self
33
+ attr_accessor :selected_sample
34
+
35
+ def sample_directories
36
+ if @sample_directories.nil?
37
+ @sample_directories = Dir.glob(File.join(File.expand_path('..', __FILE__), '*')).
38
+ select { |file| File.directory?(file) }.
39
+ map { |file| SampleDirectory.new(file) }
40
+ glimmer_gems = Gem.find_latest_files("glimmer-*-*")
41
+ sample_directories = glimmer_gems.map do |lib|
42
+ File.dirname(File.dirname(lib))
43
+ end.select do |gem|
44
+ Dir.exist?(File.join(gem, 'samples'))
45
+ end.map do |gem|
46
+ Dir.glob(File.join(gem, 'samples', '*')).select {|file_or_dir| Dir.exist?(file_or_dir)}
47
+ end.flatten.uniq.reverse
48
+ if Dir.exist?('samples')
49
+ Dir.glob(File.join('samples', '*')).to_a.reverse.each do |dir|
50
+ sample_directories << dir if Dir.exist?(dir)
51
+ end
52
+ end
53
+ sample_directories = sample_directories.uniq {|dir| File.basename(dir)}
54
+ @sample_directories = sample_directories.map { |file| SampleDirectory.new(file) }
55
+ end
56
+ @sample_directories
57
+ end
58
+
59
+ def all_samples
60
+ @all_samples ||= sample_directories.map(&:samples).reduce(:+)
61
+ end
62
+ end
63
+
64
+ include Glimmer # used for observe syntax
65
+
66
+ attr_accessor :file
67
+
68
+ def initialize(file)
69
+ self.file = file
70
+ end
71
+
72
+ def name
73
+ File.basename(file).split('_').map(&:capitalize).join(' ')
74
+ end
75
+
76
+ def samples
77
+ if @samples.nil?
78
+ @samples = Dir.glob(File.join(file, '*')).
79
+ select { |file| File.file?(file) }.
80
+ map { |sample_file| Sample.new(sample_file, sample_directory: self) }.
81
+ sort_by(&:name)
82
+
83
+ @samples.each do |sample|
84
+ observe(sample, :selected) do |new_selected_value|
85
+ if new_selected_value
86
+ self.class.all_samples.reject {|a_sample| a_sample.name == sample.name}.each do |other_sample|
87
+ other_sample.selected = false
88
+ end
89
+ self.class.selected_sample = sample
90
+ end
91
+ end
92
+ end
93
+ end
94
+ @samples
95
+ end
96
+ end
97
+
98
+ class MetaSampleApplication
99
+ include Glimmer
100
+
101
+ def launch
102
+ shell {
103
+ text 'Glimmer Meta-Sample (The Sample of Samples)'
104
+
105
+ on_swt_show {
106
+ SampleDirectory.selected_sample = SampleDirectory.all_samples.first
107
+ }
108
+
109
+ sash_form {
110
+ composite {
111
+ grid_layout 1, false
112
+
113
+ scrolled_composite {
114
+ layout_data(:fill, :fill, true, true)
115
+
116
+ composite {
117
+ SampleDirectory.sample_directories.each { |sample_directory|
118
+ group {
119
+ layout_data(:fill, :fill, true, true)
120
+ grid_layout 2, false
121
+ text sample_directory.name
122
+ font height: 30
123
+
124
+ sample_directory.samples.each { |sample|
125
+ label_radio = radio {
126
+ selection bind(sample, :selected)
127
+ }
128
+ label {
129
+ text sample.name
130
+ font height: 30
131
+
132
+ on_mouse_up {
133
+ sample.selected = true
134
+ }
135
+ }
136
+ }
137
+ }
138
+ }
139
+ }
140
+ }
141
+
142
+ button {
143
+ layout_data(:center, :center, false, false) {
144
+ height_hint 150
145
+ }
146
+ text 'Launch Sample'
147
+ font height: 45
148
+ on_widget_selected {
149
+ SampleDirectory.selected_sample.launch
150
+ }
151
+ }
152
+ }
153
+
154
+ code_text {
155
+ text bind(SampleDirectory, 'selected_sample.content')
156
+ editable false
157
+ caret nil
158
+ }
159
+
160
+ weights 1, 2
161
+ }
162
+ }.open
163
+ end
164
+ end
165
+
166
+ MetaSampleApplication.new.launch