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.
- checksums.yaml +4 -4
- data/README.md +95 -20
- data/VERSION +1 -1
- data/lib/glimmer-dsl-opal.rb +10 -8
- data/lib/glimmer/data_binding/element_binding.rb +35 -0
- data/lib/glimmer/data_binding/observable_element.rb +14 -0
- data/lib/glimmer/dsl/opal/bind_expression.rb +37 -0
- data/lib/glimmer/dsl/opal/button_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/combo_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/combo_selection_data_binding_expression.rb +40 -0
- data/lib/glimmer/dsl/opal/composite_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/data_binding_expression.rb +34 -0
- data/lib/glimmer/dsl/opal/dsl.rb +9 -0
- data/lib/glimmer/dsl/opal/label_expression.rb +2 -2
- data/lib/glimmer/dsl/opal/property_expression.rb +1 -1
- data/lib/glimmer/dsl/opal/shell_expression.rb +2 -2
- data/lib/glimmer/dsl/opal/widget_listener_expression.rb +18 -0
- data/lib/glimmer/opal/div_proxy.rb +14 -0
- data/lib/glimmer/opal/{shell.rb → document_proxy.rb} +19 -5
- data/lib/glimmer/opal/element_proxy.rb +52 -0
- data/lib/glimmer/opal/event_listener_proxy.rb +18 -0
- data/lib/glimmer/opal/input_proxy.rb +30 -0
- data/lib/glimmer/opal/label_proxy.rb +24 -0
- data/lib/glimmer/opal/select_proxy.rb +58 -0
- data/lib/samples/elaborate/contact_manager.rb +95 -0
- data/lib/samples/elaborate/contact_manager/contact.rb +11 -0
- data/lib/samples/elaborate/contact_manager/contact_manager_presenter.rb +36 -0
- data/lib/samples/elaborate/contact_manager/contact_repository.rb +244 -0
- data/lib/samples/elaborate/launch +6 -0
- data/lib/samples/elaborate/login.rb +88 -0
- data/lib/samples/elaborate/tic_tac_toe.rb +53 -0
- data/lib/samples/elaborate/tic_tac_toe/board.rb +124 -0
- data/lib/samples/elaborate/tic_tac_toe/cell.rb +27 -0
- data/lib/samples/hello/hello_browser.rb +8 -0
- data/lib/samples/hello/hello_combo.rb +34 -0
- data/lib/samples/hello/hello_computed.rb +69 -0
- data/lib/samples/hello/hello_computed/contact.rb +21 -0
- data/lib/samples/hello/hello_list_multi_selection.rb +44 -0
- data/lib/samples/hello/hello_list_single_selection.rb +34 -0
- data/lib/samples/hello/hello_tab.rb +24 -0
- data/lib/samples/hello/hello_world.rb +8 -0
- data/lib/samples/hello/launch +10 -0
- data/lib/samples/launch +4 -0
- metadata +39 -6
- 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/
|
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::
|
12
|
+
Glimmer::Opal::LabelProxy.new(parent, args)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -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/
|
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::
|
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
|
@@ -1,10 +1,15 @@
|
|
1
|
+
require 'glimmer/opal/element_proxy'
|
2
|
+
|
1
3
|
module Glimmer
|
2
4
|
module Opal
|
3
|
-
class
|
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
|
21
|
-
|
22
|
-
|
23
|
-
|
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,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
|