glimmer-dsl-opal 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +95 -20
  3. data/VERSION +1 -1
  4. data/lib/glimmer-dsl-opal.rb +10 -8
  5. data/lib/glimmer/data_binding/element_binding.rb +35 -0
  6. data/lib/glimmer/data_binding/observable_element.rb +14 -0
  7. data/lib/glimmer/dsl/opal/bind_expression.rb +37 -0
  8. data/lib/glimmer/dsl/opal/button_expression.rb +17 -0
  9. data/lib/glimmer/dsl/opal/combo_expression.rb +17 -0
  10. data/lib/glimmer/dsl/opal/combo_selection_data_binding_expression.rb +40 -0
  11. data/lib/glimmer/dsl/opal/composite_expression.rb +17 -0
  12. data/lib/glimmer/dsl/opal/data_binding_expression.rb +34 -0
  13. data/lib/glimmer/dsl/opal/dsl.rb +9 -0
  14. data/lib/glimmer/dsl/opal/label_expression.rb +2 -2
  15. data/lib/glimmer/dsl/opal/property_expression.rb +1 -1
  16. data/lib/glimmer/dsl/opal/shell_expression.rb +2 -2
  17. data/lib/glimmer/dsl/opal/widget_listener_expression.rb +18 -0
  18. data/lib/glimmer/opal/div_proxy.rb +14 -0
  19. data/lib/glimmer/opal/{shell.rb → document_proxy.rb} +19 -5
  20. data/lib/glimmer/opal/element_proxy.rb +52 -0
  21. data/lib/glimmer/opal/event_listener_proxy.rb +18 -0
  22. data/lib/glimmer/opal/input_proxy.rb +30 -0
  23. data/lib/glimmer/opal/label_proxy.rb +24 -0
  24. data/lib/glimmer/opal/select_proxy.rb +58 -0
  25. data/lib/samples/elaborate/contact_manager.rb +95 -0
  26. data/lib/samples/elaborate/contact_manager/contact.rb +11 -0
  27. data/lib/samples/elaborate/contact_manager/contact_manager_presenter.rb +36 -0
  28. data/lib/samples/elaborate/contact_manager/contact_repository.rb +244 -0
  29. data/lib/samples/elaborate/launch +6 -0
  30. data/lib/samples/elaborate/login.rb +88 -0
  31. data/lib/samples/elaborate/tic_tac_toe.rb +53 -0
  32. data/lib/samples/elaborate/tic_tac_toe/board.rb +124 -0
  33. data/lib/samples/elaborate/tic_tac_toe/cell.rb +27 -0
  34. data/lib/samples/hello/hello_browser.rb +8 -0
  35. data/lib/samples/hello/hello_combo.rb +34 -0
  36. data/lib/samples/hello/hello_computed.rb +69 -0
  37. data/lib/samples/hello/hello_computed/contact.rb +21 -0
  38. data/lib/samples/hello/hello_list_multi_selection.rb +44 -0
  39. data/lib/samples/hello/hello_list_single_selection.rb +34 -0
  40. data/lib/samples/hello/hello_tab.rb +24 -0
  41. data/lib/samples/hello/hello_world.rb +8 -0
  42. data/lib/samples/hello/launch +10 -0
  43. data/lib/samples/launch +4 -0
  44. metadata +39 -6
  45. data/lib/glimmer/opal/label.rb +0 -31
@@ -1,6 +1,6 @@
1
1
  require 'glimmer/dsl/static_expression'
2
2
  require 'glimmer/dsl/parent_expression'
3
- require 'glimmer/opal/label'
3
+ require 'glimmer/opal/label_proxy'
4
4
 
5
5
  module Glimmer
6
6
  module DSL
@@ -9,7 +9,7 @@ module Glimmer
9
9
  include ParentExpression
10
10
 
11
11
  def interpret(parent, keyword, *args, &block)
12
- Glimmer::Opal::Label.new(parent, args)
12
+ Glimmer::Opal::LabelProxy.new(parent, args)
13
13
  end
14
14
  end
15
15
  end
@@ -7,7 +7,7 @@ module Glimmer
7
7
  include TopLevelExpression
8
8
 
9
9
  def can_interpret?(parent, keyword, *args, &block)
10
- keyword.to_s == 'text'
10
+ parent and keyword and block.nil?
11
11
  end
12
12
 
13
13
  def interpret(parent, keyword, *args, &block)
@@ -1,7 +1,7 @@
1
1
  require 'glimmer/dsl/static_expression'
2
2
  require 'glimmer/dsl/top_level_expression'
3
3
  require 'glimmer/dsl/parent_expression'
4
- require 'glimmer/opal/shell'
4
+ require 'glimmer/opal/document_proxy'
5
5
 
6
6
  module Glimmer
7
7
  module DSL
@@ -11,7 +11,7 @@ module Glimmer
11
11
  include ParentExpression
12
12
 
13
13
  def interpret(parent, keyword, *args, &block)
14
- Glimmer::Opal::Shell.new(args)
14
+ Glimmer::Opal::DocumentProxy.new(args)
15
15
  end
16
16
  end
17
17
  end
@@ -0,0 +1,18 @@
1
+ require 'glimmer/dsl/expression'
2
+
3
+ module Glimmer
4
+ module DSL
5
+ module Opal
6
+ class WidgetListenerExpression < Expression
7
+
8
+ def can_interpret?(parent, keyword, *args, &block)
9
+ keyword.start_with?('on_') and args.empty? and block_given?
10
+ end
11
+
12
+ def interpret(parent, keyword, *args, &block)
13
+ parent.handle_observation_request(keyword, &block)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ require 'glimmer/opal/element_proxy'
2
+
3
+ module Glimmer
4
+ module Opal
5
+ class DivProxy < ElementProxy
6
+ def dom
7
+ div_id = id
8
+ @dom ||= DOM {
9
+ div(id: div_id, class: 'grid_layout')
10
+ }
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,10 +1,15 @@
1
+ require 'glimmer/opal/element_proxy'
2
+
1
3
  module Glimmer
2
4
  module Opal
3
- class Shell
5
+ class DocumentProxy < ElementProxy
6
+ # TODO consider renaming to ShellProxy to match SWT API
7
+
4
8
  def initialize(args)
5
9
  @args = args
6
10
  @children = []
7
11
  $document.ready do
12
+ $document.head.replace(head_dom)
8
13
  $document.body.replace(dom)
9
14
  end
10
15
  end
@@ -17,10 +22,19 @@ module Glimmer
17
22
  $document.title = value
18
23
  end
19
24
 
20
- def add_child(child)
21
- return if @children.include?(child)
22
- @children << child
23
- dom << child.dom
25
+ def head_dom
26
+ @head_dom ||= DOM {
27
+ head {
28
+ <<~CSS
29
+ <style>
30
+ div.grid_layout > * {
31
+ display: block;
32
+ margin-bottom: 10px;
33
+ }
34
+ </style>
35
+ CSS
36
+ }
37
+ }
24
38
  end
25
39
 
26
40
  def dom
@@ -0,0 +1,52 @@
1
+ module Glimmer
2
+ module Opal
3
+ class ElementProxy
4
+ attr_reader :parent, :args
5
+
6
+ def initialize(parent, args)
7
+ @parent = parent
8
+ @args = args
9
+ @children = []
10
+ @parent.add_child(self)
11
+ end
12
+
13
+ def add_child(child)
14
+ return if @children.include?(child)
15
+ @children << child
16
+ dom << child.dom
17
+ end
18
+
19
+ def redraw
20
+ old_dom = @dom
21
+ @dom = nil
22
+ old_dom.replace dom
23
+ end
24
+
25
+ # Subclasses must override with their own mappings
26
+ def observation_request_to_event_mapping
27
+ {}
28
+ end
29
+
30
+ def name
31
+ self.class.name.split('::').last.underscore.sub(/_proxy$/, '')
32
+ end
33
+
34
+ def id
35
+ "#{name}-#{hash}"
36
+ end
37
+
38
+ # Subclasses can override with their own selector
39
+ def selector
40
+ "#{name}##{id}"
41
+ end
42
+
43
+ def handle_observation_request(keyword, &event_listener)
44
+ event = observation_request_to_event_mapping[keyword][:event]
45
+ event_handler = observation_request_to_event_mapping[keyword][:event_handler]
46
+ event_listener = event_handler&.call(event_listener) || event_listener
47
+ delegate = $document.on(event, selector, &event_listener)
48
+ EventListenerProxy.new(element_proxy: self, event: event, selector: selector, delegate: delegate)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,18 @@
1
+ module Glimmer
2
+ module Opal
3
+ class EventListenerProxy
4
+ attr_reader :element_proxy, :event, :selector, :delegate
5
+
6
+ def initialize(element_proxy:, event:, selector:, delegate:)
7
+ @element_proxy = element_proxy
8
+ @event = event
9
+ @selector = selector
10
+ @delegate = delegate
11
+ end
12
+
13
+ def unregister
14
+ $document.off(@delegate)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ require 'glimmer/opal/element_proxy'
2
+
3
+ module Glimmer
4
+ module Opal
5
+ class InputProxy < ElementProxy
6
+ attr_reader :text
7
+
8
+ def text=(value)
9
+ @text = value
10
+ redraw
11
+ end
12
+
13
+ def observation_request_to_event_mapping
14
+ {
15
+ 'on_widget_selected' => {
16
+ event: 'click'
17
+ }
18
+ }
19
+ end
20
+
21
+ def dom
22
+ input_text = @text
23
+ input_id = id
24
+ @dom ||= DOM {
25
+ input id: input_id, type: 'button', value: input_text
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,24 @@
1
+ require 'glimmer/opal/element_proxy'
2
+
3
+ module Glimmer
4
+ module Opal
5
+ class LabelProxy < ElementProxy
6
+ attr_reader :text
7
+
8
+ def text=(value)
9
+ @text = value
10
+ redraw
11
+ end
12
+
13
+ def dom
14
+ label_text = @text
15
+ label_id = id
16
+ @dom ||= DOM {
17
+ label(id: label_id) {
18
+ label_text
19
+ }
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,58 @@
1
+ require 'glimmer/data_binding/observable_element'
2
+ require 'glimmer/opal/event_listener_proxy'
3
+ require 'glimmer/opal/element_proxy'
4
+
5
+ module Glimmer
6
+ module Opal
7
+ class SelectProxy < ElementProxy
8
+ include Glimmer::DataBinding::ObservableElement
9
+ attr_reader :text, :items
10
+
11
+ def initialize(parent, args)
12
+ super(parent, args)
13
+ @items = []
14
+ end
15
+
16
+ def text=(value)
17
+ @text = value
18
+ redraw
19
+ end
20
+
21
+ def items=(the_items)
22
+ @items = the_items
23
+ redraw
24
+ end
25
+
26
+ def observation_request_to_event_mapping
27
+ {
28
+ 'on_widget_selected' => {
29
+ event: 'change',
30
+ event_handler: -> (event_listener) {
31
+ -> (event) {
32
+ @text = event.target.value
33
+ event_listener.call(event)
34
+ }
35
+ }
36
+ }
37
+ }
38
+ end
39
+
40
+ def dom
41
+ select_text = @text
42
+ items = @items
43
+ select_id = id
44
+ @dom ||= DOM {
45
+ select(id: select_id) {
46
+ items.to_a.each do |item|
47
+ option_hash = {value: item}
48
+ option_hash[:selected] = 'selected' if select_text == item
49
+ option(option_hash) {
50
+ item
51
+ }
52
+ end
53
+ }
54
+ }
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,95 @@
1
+ require_relative "contact_manager/contact_manager_presenter"
2
+
3
+ class ContactManager
4
+ include Glimmer
5
+
6
+ def initialize
7
+ @contact_manager_presenter = ContactManagerPresenter.new
8
+ @contact_manager_presenter.list
9
+ end
10
+
11
+ def launch
12
+ shell {
13
+ text "Contact Manager"
14
+ composite {
15
+ composite {
16
+ grid_layout 2, false
17
+ label {text "First &Name: "}
18
+ text {
19
+ text bind(@contact_manager_presenter, :first_name)
20
+ on_key_pressed {|key_event|
21
+ @contact_manager_presenter.find if key_event.keyCode == Glimmer::SWT::SWTProxy[:cr]
22
+ }
23
+ }
24
+ label {text "&Last Name: "}
25
+ text {
26
+ text bind(@contact_manager_presenter, :last_name)
27
+ on_key_pressed {|key_event|
28
+ @contact_manager_presenter.find if key_event.keyCode == Glimmer::SWT::SWTProxy[:cr]
29
+ }
30
+ }
31
+ label {text "&Email: "}
32
+ text {
33
+ text bind(@contact_manager_presenter, :email)
34
+ on_key_pressed {|key_event|
35
+ @contact_manager_presenter.find if key_event.keyCode == Glimmer::SWT::SWTProxy[:cr]
36
+ }
37
+ }
38
+ composite {
39
+ grid_layout 2, false
40
+ button {
41
+ text "&Find"
42
+ on_widget_selected {
43
+ @contact_manager_presenter.find
44
+ }
45
+ }
46
+ button {
47
+ text "&List All"
48
+ on_widget_selected {
49
+ @contact_manager_presenter.list
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ table(:multi) { |table_proxy|
56
+ layout_data {
57
+ horizontal_alignment :fill
58
+ vertical_alignment :fill
59
+ grab_excess_horizontal_space true
60
+ grab_excess_vertical_space true
61
+ height_hint 200
62
+ }
63
+ table_column {
64
+ text "First Name"
65
+ width 80
66
+ on_widget_selected {
67
+ @contact_manager_presenter.toggle_sort(:first_name)
68
+ }
69
+ }
70
+ table_column {
71
+ text "Last Name"
72
+ width 80
73
+ on_widget_selected {
74
+ @contact_manager_presenter.toggle_sort(:last_name)
75
+ }
76
+ }
77
+ table_column {
78
+ text "Email"
79
+ width 200
80
+ on_widget_selected {
81
+ @contact_manager_presenter.toggle_sort(:email)
82
+ }
83
+ }
84
+ items bind(@contact_manager_presenter, :results),
85
+ column_properties(:first_name, :last_name, :email)
86
+ on_mouse_down { |event|
87
+ table_proxy.edit_table_item(event.table_item, event.column_index)
88
+ }
89
+ }
90
+ }
91
+ }.open
92
+ end
93
+ end
94
+
95
+ ContactManager.new.launch
@@ -0,0 +1,11 @@
1
+ class ContactManager
2
+ class Contact
3
+ attr_accessor :first_name, :last_name, :email
4
+
5
+ def initialize(attribute_map)
6
+ @first_name = attribute_map[:first_name]
7
+ @last_name = attribute_map[:last_name]
8
+ @email = attribute_map[:email]
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,36 @@
1
+ require_relative "contact_repository"
2
+
3
+ class ContactManager
4
+ class ContactManagerPresenter
5
+ attr_accessor :results
6
+ @@contact_attributes = [:first_name, :last_name, :email]
7
+ @@contact_attributes.each {|attribute_name| attr_accessor attribute_name}
8
+
9
+ def initialize(contact_repository = nil)
10
+ @contact_repository = contact_repository || ContactRepository.new
11
+ @results = []
12
+ end
13
+
14
+ def list
15
+ self.results = @contact_repository.find({})
16
+ end
17
+
18
+ def find
19
+ filter_map = {}
20
+ @@contact_attributes.each do |attribute_name|
21
+ filter_map[attribute_name] = self.send(attribute_name) if self.send(attribute_name)
22
+ end
23
+ self.results = @contact_repository.find(filter_map)
24
+ @sort_attribute_name = nil
25
+ @sort_direction_ascending = nil
26
+ end
27
+
28
+ def toggle_sort(attribute_name)
29
+ @sort_attribute_name = attribute_name
30
+ @sort_direction_ascending = !@sort_direction_ascending
31
+ sorted_results = self.results.sort_by {|contact| contact.send(attribute_name).downcase}
32
+ sorted_results = sorted_results.reverse unless @sort_direction_ascending
33
+ self.results = sorted_results
34
+ end
35
+ end
36
+ end