glimmer-dsl-swt 0.1.0

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.
Files changed (79) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.md +47 -0
  4. data/RUBY_VERSION +1 -0
  5. data/VERSION +1 -0
  6. data/bin/girb +10 -0
  7. data/bin/girb_runner.rb +13 -0
  8. data/bin/glimmer +5 -0
  9. data/icons/scaffold_app.icns +0 -0
  10. data/lib/ext/glimmer.rb +13 -0
  11. data/lib/ext/glimmer/config.rb +18 -0
  12. data/lib/glimmer-dsl-swt.rb +12 -0
  13. data/lib/glimmer/data_binding/list_selection_binding.rb +52 -0
  14. data/lib/glimmer/data_binding/model_binding.rb +248 -0
  15. data/lib/glimmer/data_binding/observable.rb +21 -0
  16. data/lib/glimmer/data_binding/observable_array.rb +107 -0
  17. data/lib/glimmer/data_binding/observable_model.rb +108 -0
  18. data/lib/glimmer/data_binding/observable_widget.rb +17 -0
  19. data/lib/glimmer/data_binding/observer.rb +124 -0
  20. data/lib/glimmer/data_binding/shine.rb +23 -0
  21. data/lib/glimmer/data_binding/table_items_binding.rb +56 -0
  22. data/lib/glimmer/data_binding/tree_items_binding.rb +71 -0
  23. data/lib/glimmer/data_binding/widget_binding.rb +33 -0
  24. data/lib/glimmer/dsl/swt/async_exec_expression.rb +14 -0
  25. data/lib/glimmer/dsl/swt/bind_expression.rb +37 -0
  26. data/lib/glimmer/dsl/swt/color_expression.rb +19 -0
  27. data/lib/glimmer/dsl/swt/column_properties_expression.rb +24 -0
  28. data/lib/glimmer/dsl/swt/combo_selection_data_binding_expression.rb +42 -0
  29. data/lib/glimmer/dsl/swt/custom_widget_expression.rb +39 -0
  30. data/lib/glimmer/dsl/swt/data_binding_expression.rb +34 -0
  31. data/lib/glimmer/dsl/swt/dialog_expression.rb +26 -0
  32. data/lib/glimmer/dsl/swt/display_expression.rb +19 -0
  33. data/lib/glimmer/dsl/swt/dsl.rb +34 -0
  34. data/lib/glimmer/dsl/swt/exec_expression.rb +28 -0
  35. data/lib/glimmer/dsl/swt/layout_data_expression.rb +25 -0
  36. data/lib/glimmer/dsl/swt/layout_expression.rb +27 -0
  37. data/lib/glimmer/dsl/swt/list_selection_data_binding_expression.rb +44 -0
  38. data/lib/glimmer/dsl/swt/menu_bar_expression.rb +33 -0
  39. data/lib/glimmer/dsl/swt/menu_expression.rb +32 -0
  40. data/lib/glimmer/dsl/swt/message_box_expression.rb +29 -0
  41. data/lib/glimmer/dsl/swt/observe_expression.rb +32 -0
  42. data/lib/glimmer/dsl/swt/property_expression.rb +22 -0
  43. data/lib/glimmer/dsl/swt/rgb_expression.rb +12 -0
  44. data/lib/glimmer/dsl/swt/rgba_expression.rb +12 -0
  45. data/lib/glimmer/dsl/swt/shell_expression.rb +25 -0
  46. data/lib/glimmer/dsl/swt/swt_expression.rb +25 -0
  47. data/lib/glimmer/dsl/swt/sync_exec_expression.rb +15 -0
  48. data/lib/glimmer/dsl/swt/tab_item_expression.rb +33 -0
  49. data/lib/glimmer/dsl/swt/table_items_data_binding_expression.rb +31 -0
  50. data/lib/glimmer/dsl/swt/tree_items_data_binding_expression.rb +31 -0
  51. data/lib/glimmer/dsl/swt/tree_properties_expression.rb +26 -0
  52. data/lib/glimmer/dsl/swt/widget_expression.rb +35 -0
  53. data/lib/glimmer/dsl/swt/widget_listener_expression.rb +32 -0
  54. data/lib/glimmer/launcher.rb +196 -0
  55. data/lib/glimmer/package.rb +57 -0
  56. data/lib/glimmer/rake_task.rb +62 -0
  57. data/lib/glimmer/scaffold.rb +582 -0
  58. data/lib/glimmer/swt/color_proxy.rb +53 -0
  59. data/lib/glimmer/swt/display_proxy.rb +88 -0
  60. data/lib/glimmer/swt/font_proxy.rb +72 -0
  61. data/lib/glimmer/swt/layout_data_proxy.rb +84 -0
  62. data/lib/glimmer/swt/layout_proxy.rb +82 -0
  63. data/lib/glimmer/swt/menu_proxy.rb +101 -0
  64. data/lib/glimmer/swt/message_box_proxy.rb +48 -0
  65. data/lib/glimmer/swt/packages.rb +13 -0
  66. data/lib/glimmer/swt/shell_proxy.rb +152 -0
  67. data/lib/glimmer/swt/swt_proxy.rb +106 -0
  68. data/lib/glimmer/swt/tab_item_proxy.rb +65 -0
  69. data/lib/glimmer/swt/table_proxy.rb +150 -0
  70. data/lib/glimmer/swt/tree_proxy.rb +120 -0
  71. data/lib/glimmer/swt/widget_listener_proxy.rb +34 -0
  72. data/lib/glimmer/swt/widget_proxy.rb +489 -0
  73. data/lib/glimmer/ui/custom_shell.rb +45 -0
  74. data/lib/glimmer/ui/custom_widget.rb +244 -0
  75. data/lib/glimmer/util/proc_tracker.rb +16 -0
  76. data/vendor/swt/linux/swt.jar +0 -0
  77. data/vendor/swt/mac/swt.jar +0 -0
  78. data/vendor/swt/windows/swt.jar +0 -0
  79. metadata +307 -0
@@ -0,0 +1,71 @@
1
+ require 'glimmer/data_binding/observable_array'
2
+ require 'glimmer/data_binding/observable_model'
3
+ require 'glimmer/data_binding/observable'
4
+ require 'glimmer/data_binding/observer'
5
+ require 'glimmer/swt/swt_proxy'
6
+
7
+ module Glimmer
8
+ module DataBinding
9
+ class TreeItemsBinding
10
+ include DataBinding::Observable
11
+ include DataBinding::Observer
12
+
13
+ include_package 'org.eclipse.swt'
14
+ include_package 'org.eclipse.swt.widgets'
15
+
16
+ def initialize(parent, model_binding, tree_properties)
17
+ @tree = parent
18
+ @model_binding = model_binding
19
+ @tree_properties = [tree_properties].flatten.first.to_h
20
+ if @tree.respond_to?(:tree_properties=)
21
+ @tree.tree_properties = @tree_properties
22
+ else # assume custom widget
23
+ @tree.body_root.tree_properties = @tree_properties
24
+ end
25
+ call
26
+ model = model_binding.base_model
27
+ observe(model, model_binding.property_name_expression)
28
+ @tree.on_widget_disposed do |dispose_event|
29
+ unregister_all_observables
30
+ end
31
+ end
32
+
33
+ def call(new_value=nil)
34
+ @model_tree_root_node = @model_binding.evaluate_property
35
+ populate_tree(@model_tree_root_node, @tree, @tree_properties)
36
+ end
37
+
38
+ def populate_tree(model_tree_root_node, parent, tree_properties)
39
+ # TODO make it change things by delta instead of removing all
40
+ selected_tree_item_model = parent.swt_widget.getSelection.map(&:getData).first
41
+ old_tree_items = parent.all_tree_items
42
+ old_tree_item_expansion_by_data = old_tree_items.reduce({}) {|hash, ti| hash.merge(ti.getData => ti.getExpanded)}
43
+ old_tree_items.each do |tree_item|
44
+ tree_item.getData('observer_registrations').each do |key, observer_registration|
45
+ observer_registration.unregister
46
+ end
47
+ end
48
+ parent.swt_widget.removeAll
49
+ populate_tree_node(model_tree_root_node, parent.swt_widget, tree_properties)
50
+ parent.all_tree_items.each { |ti| ti.setExpanded(!!old_tree_item_expansion_by_data[ti.getData]) }
51
+ tree_item_to_select = parent.depth_first_search {|ti| ti.getData == selected_tree_item_model}
52
+ parent.swt_widget.setSelection(tree_item_to_select)
53
+ end
54
+
55
+ def populate_tree_node(model_tree_node, parent, tree_properties)
56
+ return if model_tree_node.nil?
57
+ # TODO anticipate default tree properties if none were passed (like literal values text and children)
58
+ tree_item = TreeItem.new(parent, SWT::SWTProxy[:none])
59
+ observer_registrations = @tree_properties.reduce({}) do |hash, key_value_pair|
60
+ hash.merge(key_value_pair.first => observe(model_tree_node, key_value_pair.last))
61
+ end
62
+ tree_item.setData('observer_registrations', observer_registrations)
63
+ tree_item.setData(model_tree_node)
64
+ tree_item.setText((model_tree_node && model_tree_node.send(tree_properties[:text])).to_s)
65
+ [model_tree_node && model_tree_node.send(tree_properties[:children])].flatten.to_a.compact.each do |child|
66
+ populate_tree_node(child, tree_item, tree_properties)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,33 @@
1
+ require 'glimmer'
2
+ require_relative 'observable'
3
+ require_relative 'observer'
4
+
5
+ module Glimmer
6
+ module DataBinding
7
+ class WidgetBinding
8
+ include Glimmer
9
+ include Observable
10
+ include Observer
11
+
12
+ attr_reader :widget, :property
13
+ def initialize(model, property, translator = nil)
14
+ @widget = model
15
+ @property = property
16
+ @translator = translator || proc {|value| value}
17
+
18
+ if @widget.respond_to?(:dispose)
19
+ @widget.on_widget_disposed do |dispose_event|
20
+ unregister_all_observables
21
+ end
22
+ end
23
+ end
24
+ def call(value)
25
+ converted_value = translated_value = @translator.call(value)
26
+ @widget.set_attribute(@property, converted_value) unless evaluate_property == converted_value
27
+ end
28
+ def evaluate_property
29
+ @widget.get_attribute(@property)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/swt/exec_expression'
3
+
4
+ module Glimmer
5
+ module DSL
6
+ module SWT
7
+ # Asynchronously executes code block against the SWT Event Loop
8
+ # to manipulate SWT UI objects on the UI thread safely
9
+ class AsyncExecExpression < StaticExpression
10
+ include ExecExpression
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,37 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/data_binding/model_binding'
3
+
4
+ module Glimmer
5
+ module DSL
6
+ module SWT
7
+ # Responsible for setting up the return value of the bind keyword (command symbol)
8
+ # as a ModelBinding. It is then used by another command handler like
9
+ # DataBindingCommandHandler for text and selection properties on Text and Spinner
10
+ # or TableItemsDataBindingCommandHandler for items in a Table
11
+ class BindExpression < StaticExpression
12
+ def can_interpret?(parent, keyword, *args, &block)
13
+ (
14
+ keyword == 'bind' and
15
+ (
16
+ (
17
+ (args.size == 2) and
18
+ textual?(args[1])
19
+ ) ||
20
+ (
21
+ (args.size == 3) and
22
+ textual?(args[1]) and
23
+ (args[2].is_a?(Hash))
24
+ )
25
+ )
26
+ )
27
+ end
28
+
29
+ def interpret(parent, keyword, *args, &block)
30
+ binding_options = args[2] || {}
31
+ binding_options[:on_read] = binding_options.delete(:on_read) || binding_options.delete('on_read') || block
32
+ DataBinding::ModelBinding.new(args[0], args[1].to_s, binding_options)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/top_level_expression'
3
+ require 'glimmer/swt/color_proxy'
4
+ require 'glimmer/swt/display_proxy'
5
+
6
+ module Glimmer
7
+ module DSL
8
+ module SWT
9
+ class ColorExpression < StaticExpression
10
+ include TopLevelExpression
11
+ include_package 'org.eclipse.swt.widgets'
12
+
13
+ def interpret(parent, keyword, *args, &block)
14
+ Glimmer::SWT::ColorProxy.new(*args)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ require 'glimmer/dsl/static_expression'
2
+
3
+ module Glimmer
4
+ module DSL
5
+ module SWT
6
+ # Responsible for providing a readable keyword (command symbol) to capture
7
+ # and return column properties for use in TreeItemsDataBindingCommandHandler
8
+ class ColumnPropertiesExpression < StaticExpression
9
+ include_package 'org.eclipse.swt.widgets'
10
+
11
+ def can_interpret?(parent, keyword, *args, &block)
12
+ keyword == 'column_properties' and
13
+ block.nil? and
14
+ parent.respond_to?(:swt_widget) and
15
+ parent.swt_widget.is_a?(Table)
16
+ end
17
+
18
+ def interpret(parent, keyword, *args, &block)
19
+ args
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,42 @@
1
+ require 'glimmer/dsl/expression'
2
+ require 'glimmer/data_binding/model_binding'
3
+ require 'glimmer/data_binding/widget_binding'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module SWT
8
+ class ComboSelectionDataBindingExpression < Expression
9
+ include_package 'org.eclipse.swt.widgets'
10
+
11
+ def can_interpret?(parent, keyword, *args, &block)
12
+ keyword == 'selection' and
13
+ block.nil? and
14
+ parent.respond_to?(:swt_widget) and
15
+ parent.swt_widget.is_a?(Combo) and
16
+ args.size == 1 and
17
+ args[0].is_a?(DataBinding::ModelBinding) and
18
+ args[0].evaluate_options_property.is_a?(Array)
19
+ end
20
+
21
+ def interpret(parent, keyword, *args, &block)
22
+ model_binding = args[0]
23
+
24
+ #TODO make this options observer dependent and all similar observers in widget specific data binding handlers
25
+ # TODO consider delegating some of this work
26
+ widget_binding = DataBinding::WidgetBinding.new(parent, 'items')
27
+ widget_binding.call(model_binding.evaluate_options_property)
28
+ model = model_binding.base_model
29
+ widget_binding.observe(model, model_binding.options_property_name)
30
+
31
+ widget_binding = DataBinding::WidgetBinding.new(parent, 'text')
32
+ widget_binding.call(model_binding.evaluate_property)
33
+ widget_binding.observe(model, model_binding.property_name_expression)
34
+
35
+ parent.on_widget_selected do
36
+ model_binding.call(widget_binding.evaluate_property)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,39 @@
1
+ require 'glimmer'
2
+ require 'glimmer/dsl/expression'
3
+ require 'glimmer/dsl/parent_expression'
4
+ require 'glimmer/dsl/top_level_expression'
5
+ require 'glimmer/ui/custom_widget'
6
+ require 'glimmer/ui/custom_shell'
7
+
8
+ module Glimmer
9
+ module DSL
10
+ module SWT
11
+ class CustomWidgetExpression < Expression
12
+ # TODO Make custom widgets automatically generate static expressions
13
+ include ParentExpression
14
+ include TopLevelExpression
15
+
16
+ def can_interpret?(parent, keyword, *args, &block)
17
+ custom_widget_class = UI::CustomWidget.for(keyword)
18
+ custom_widget_class and
19
+ (parent.respond_to?(:swt_widget) or
20
+ custom_widget_class.ancestors.include?(UI::CustomShell))
21
+ end
22
+
23
+ def interpret(parent, keyword, *args, &block)
24
+ options = args.last.is_a?(Hash) ? args.pop : {}
25
+ UI::CustomWidget.for(keyword).new(parent, *args, options, &block)
26
+ end
27
+
28
+ def add_content(parent, &block)
29
+ # TODO consider avoiding source_location
30
+ if block.source_location == parent.content&.__getobj__.source_location
31
+ parent.content.call(parent) unless parent.content.called?
32
+ else
33
+ super
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,34 @@
1
+ require 'glimmer/dsl/expression'
2
+ require 'glimmer/data_binding/model_binding'
3
+ require 'glimmer/data_binding/widget_binding'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module SWT
8
+ # Responsible for wiring two-way data-binding for text and selection properties
9
+ # on Text, Button, and Spinner widgets.
10
+ # Does so by using the output of the bind(model, property) command in the form
11
+ # of a ModelBinding, which is then connected to an anonymous widget observer
12
+ # (aka widget_data_binder as per widget_data_binders array)
13
+ #
14
+ # Depends on BindCommandHandler
15
+ class DataBindingExpression < Expression
16
+ def can_interpret?(parent, keyword, *args, &block)
17
+ args.size == 1 and
18
+ args[0].is_a?(DataBinding::ModelBinding)
19
+ end
20
+
21
+ def interpret(parent, keyword, *args, &block)
22
+ model_binding = args[0]
23
+ widget_binding_parameters = [parent, keyword]
24
+ widget_binding = DataBinding::WidgetBinding.new(*widget_binding_parameters)
25
+ widget_binding.call(model_binding.evaluate_property)
26
+ #TODO make this options observer dependent and all similar observers in widget specific data binding handlers
27
+ widget_binding.observe(model_binding)
28
+ # TODO simplify this logic and put it where it belongs
29
+ parent.add_observer(model_binding, keyword) if parent.respond_to?(:add_observer, [model_binding, keyword])
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,26 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+ require 'glimmer/dsl/top_level_expression'
4
+ require 'glimmer/swt/shell_proxy'
5
+
6
+ module Glimmer
7
+ module DSL
8
+ module SWT
9
+ class DialogExpression < StaticExpression
10
+ include TopLevelExpression
11
+ include ParentExpression
12
+
13
+ def can_interpret?(parent, keyword, *args, &block)
14
+ keyword == 'dialog' and
15
+ (parent.nil? or parent.is_a?(Glimmer::SWT::ShellProxy))
16
+ end
17
+
18
+ def interpret(parent, keyword, *args, &block)
19
+ args = [parent] + args unless parent.nil?
20
+ args += [:dialog_trim, :application_modal]
21
+ Glimmer::SWT::ShellProxy.send(:new, *args)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,19 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+ require 'glimmer/dsl/top_level_expression'
4
+ require 'glimmer/swt/display_proxy'
5
+
6
+ module Glimmer
7
+ module DSL
8
+ module SWT
9
+ class DisplayExpression < StaticExpression
10
+ include TopLevelExpression
11
+ include ParentExpression
12
+
13
+ def interpret(parent, keyword, *args, &block)
14
+ Glimmer::SWT::DisplayProxy.instance(*args)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ require 'glimmer/launcher'
2
+ require Glimmer::Launcher.swt_jar_file
3
+ require 'glimmer/dsl/engine'
4
+ Dir[File.expand_path('../*_expression.rb', __FILE__)].each {|f| require f}
5
+
6
+ # Glimmer DSL expression configuration module
7
+ #
8
+ # When DSL engine interprets an expression, it attempts to handle
9
+ # with expressions listed here in the order specified.
10
+
11
+ # Every expression has a corresponding Expression subclass
12
+ # in glimmer/dsl
13
+
14
+ module Glimmer
15
+ module DSL
16
+ module SWT
17
+ Engine.add_dynamic_expressions(
18
+ SWT,
19
+ %w[
20
+ layout
21
+ widget_listener
22
+ combo_selection_data_binding
23
+ list_selection_data_binding
24
+ tree_items_data_binding
25
+ table_items_data_binding
26
+ data_binding
27
+ property
28
+ widget
29
+ custom_widget
30
+ ]
31
+ )
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ require 'glimmer/dsl/top_level_expression'
2
+ require 'glimmer/swt/display_proxy'
3
+
4
+ module Glimmer
5
+ module DSL
6
+ module SWT
7
+ # Mixin for common code in async_exec and sync_exec expressions
8
+ # Uses name in subclass to auto-derive exec_operation
9
+ module ExecExpression
10
+ include TopLevelExpression
11
+
12
+ def exec_operation
13
+ @exec_operation ||= self.class.name.split(/::/).last.sub(/Expression$/, '').underscore
14
+ end
15
+
16
+ def can_interpret?(parent, keyword, *args, &block)
17
+ keyword == exec_operation and
18
+ block_given? and
19
+ args.empty?
20
+ end
21
+
22
+ def interpret(parent, keyword, *args, &block)
23
+ Glimmer::SWT::DisplayProxy.instance.send(exec_operation, &block)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ require 'glimmer'
2
+ require 'glimmer/dsl/static_expression'
3
+ require 'glimmer/dsl/parent_expression'
4
+ require 'glimmer/swt/layout_data_proxy'
5
+
6
+ # TODO consider turning static keywords like layout_data into methods
7
+
8
+ module Glimmer
9
+ module DSL
10
+ module SWT
11
+ class LayoutDataExpression < StaticExpression
12
+ include ParentExpression
13
+
14
+ def can_interpret?(parent, keyword, *args, &block)
15
+ keyword == 'layout_data' and
16
+ parent.respond_to?(:swt_widget)
17
+ end
18
+
19
+ def interpret(parent, keyword, *args, &block)
20
+ Glimmer::SWT::LayoutDataProxy.new(parent, args)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end