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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +50 -0
- data/README.md +398 -523
- data/VERSION +1 -1
- data/glimmer-dsl-swt.gemspec +9 -6
- data/lib/ext/glimmer/config.rb +1 -0
- data/lib/glimmer-dsl-swt.rb +1 -0
- data/lib/glimmer/data_binding/table_items_binding.rb +1 -0
- data/lib/glimmer/dsl/swt/custom_widget_expression.rb +1 -0
- data/lib/glimmer/dsl/swt/widget_expression.rb +1 -0
- data/lib/glimmer/rake_task.rb +38 -21
- data/lib/glimmer/rake_task/package.rb +21 -10
- data/lib/glimmer/rake_task/scaffold.rb +146 -42
- data/lib/glimmer/swt/custom/code_text.rb +95 -0
- data/lib/glimmer/swt/image_proxy.rb +34 -11
- data/lib/glimmer/swt/message_box_proxy.rb +1 -1
- data/lib/glimmer/swt/sash_form_proxy.rb +53 -0
- data/lib/glimmer/swt/style_constantizable.rb +2 -1
- data/lib/glimmer/swt/widget_proxy.rb +99 -35
- data/samples/elaborate/meta_sample.rb +166 -0
- data/samples/hello/hello_sash_form.rb +137 -0
- metadata +11 -8
- data/lib/glimmer/rake_task/sample.rb +0 -115
@@ -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
|
-
|
42
|
-
if @
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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)
|
@@ -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) ==
|
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)
|
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|
|
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 =
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
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
|
-
|
698
|
-
|
699
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|