glimmer-dsl-opal 0.0.2 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +704 -40
- data/VERSION +1 -1
- data/lib/glimmer-dsl-opal.rb +3 -2
- data/lib/glimmer/data_binding/element_binding.rb +1 -1
- data/lib/glimmer/data_binding/ext/observable_model.rb +40 -0
- data/lib/glimmer/data_binding/list_selection_binding.rb +51 -0
- data/lib/glimmer/dsl/opal/async_exec_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/browser_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/button_expression.rb +1 -0
- data/lib/glimmer/dsl/opal/dsl.rb +15 -1
- data/lib/glimmer/dsl/opal/grid_layout_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/layout_data_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/list_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/list_selection_data_binding_expression.rb +42 -0
- data/lib/glimmer/dsl/opal/message_box_expression.rb +20 -0
- data/lib/glimmer/dsl/opal/observe_expression.rb +32 -0
- data/lib/glimmer/dsl/opal/property_expression.rb +6 -2
- data/lib/glimmer/dsl/opal/tab_folder_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/tab_item_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/text_expression.rb +22 -0
- data/lib/glimmer/opal/display_proxy.rb +23 -0
- data/lib/glimmer/opal/div_proxy.rb +9 -1
- data/lib/glimmer/opal/document_proxy.rb +131 -5
- data/lib/glimmer/opal/element_proxy.rb +246 -11
- data/lib/glimmer/opal/grid_layout_proxy.rb +54 -0
- data/lib/glimmer/opal/iframe_proxy.rb +23 -0
- data/lib/glimmer/opal/input_proxy.rb +16 -1
- data/lib/glimmer/opal/label_proxy.rb +2 -1
- data/lib/glimmer/opal/layout_data_proxy.rb +31 -0
- data/lib/glimmer/opal/list_proxy.rb +80 -0
- data/lib/glimmer/opal/modal.rb +94 -0
- data/lib/glimmer/opal/point.rb +5 -0
- data/lib/glimmer/opal/property_owner.rb +22 -0
- data/lib/glimmer/opal/select_proxy.rb +2 -1
- data/lib/glimmer/opal/tab_folder.rb +46 -0
- data/lib/glimmer/opal/tab_item.rb +98 -0
- data/lib/samples/elaborate/login.rb +0 -1
- data/lib/samples/elaborate/tic_tac_toe.rb +5 -5
- data/lib/samples/hello/hello_tab.rb +2 -2
- metadata +25 -2
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'glimmer/opal/property_owner'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module Opal
|
5
|
+
class GridLayoutProxy
|
6
|
+
include PropertyOwner
|
7
|
+
attr_reader :parent, :args, :num_columns, :make_columns_equal_width, :horizontal_spacing, :vertical_spacing
|
8
|
+
|
9
|
+
def initialize(parent, args)
|
10
|
+
@parent = parent
|
11
|
+
@args = args
|
12
|
+
@parent.add_css_class('grid-layout')
|
13
|
+
@horizontal_spacing = 10
|
14
|
+
@vertical_spacing = 10
|
15
|
+
@num_columns = @args.first || 1
|
16
|
+
reapply
|
17
|
+
end
|
18
|
+
|
19
|
+
def num_columns=(columns)
|
20
|
+
@num_columns = columns
|
21
|
+
# @parent.add_css_class("num-columns-#{@num_columns}")
|
22
|
+
reapply
|
23
|
+
end
|
24
|
+
|
25
|
+
def make_columns_equal_width=(equal_width)
|
26
|
+
@make_columns_equal_width = equal_width
|
27
|
+
# @parent.add_css_class('make_columns_equal_width') if @make_columns_equal_width
|
28
|
+
reapply
|
29
|
+
end
|
30
|
+
|
31
|
+
def horizontal_spacing=(spacing)
|
32
|
+
@horizontal_spacing = spacing
|
33
|
+
# @parent.add_css_class("horizontal-spacing-#{@horizontal_spacing}")
|
34
|
+
reapply
|
35
|
+
end
|
36
|
+
|
37
|
+
def vertical_spacing=(spacing)
|
38
|
+
@vertical_spacing = spacing
|
39
|
+
# @parent.add_css_class("vertical-spacing-#{@vertical_spacing}")
|
40
|
+
reapply
|
41
|
+
end
|
42
|
+
|
43
|
+
def reapply
|
44
|
+
@parent.css = <<~CSS
|
45
|
+
display: grid;
|
46
|
+
grid-template-columns: #{'auto ' * @num_columns.to_i};
|
47
|
+
grid-row-gap: #{@vertical_spacing}px;
|
48
|
+
grid-column-gap: #{@horizontal_spacing}px;
|
49
|
+
justify-content: start;
|
50
|
+
CSS
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'glimmer/opal/element_proxy'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module Opal
|
5
|
+
class IframeProxy < ElementProxy
|
6
|
+
attr_reader :url
|
7
|
+
|
8
|
+
def url=(value)
|
9
|
+
@url = value
|
10
|
+
redraw
|
11
|
+
end
|
12
|
+
|
13
|
+
def dom
|
14
|
+
iframe_id = id
|
15
|
+
iframe_url = url
|
16
|
+
@dom ||= DOM {
|
17
|
+
iframe(src: iframe_url, frameBorder: 0) {
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -14,6 +14,17 @@ module Glimmer
|
|
14
14
|
{
|
15
15
|
'on_widget_selected' => {
|
16
16
|
event: 'click'
|
17
|
+
},
|
18
|
+
'on_modify_text' => {
|
19
|
+
event: 'keyup',
|
20
|
+
event_handler: -> (event_listener) {
|
21
|
+
-> (event) {
|
22
|
+
if args.last[:type] == 'text'
|
23
|
+
@text = event.target.value
|
24
|
+
event_listener.call(event)
|
25
|
+
end
|
26
|
+
}
|
27
|
+
}
|
17
28
|
}
|
18
29
|
}
|
19
30
|
end
|
@@ -21,8 +32,12 @@ module Glimmer
|
|
21
32
|
def dom
|
22
33
|
input_text = @text
|
23
34
|
input_id = id
|
35
|
+
input_style = css
|
36
|
+
input_args = @args.last
|
37
|
+
input_disabled = @enabled ? {} : {'disabled': 'disabled'}
|
38
|
+
input_args = input_args.merge(type: 'password') if has_style?(:password)
|
24
39
|
@dom ||= DOM {
|
25
|
-
input id: input_id,
|
40
|
+
input input_args.merge(id: input_id, style: input_style, value: input_text, style: 'min-width: 27px;').merge(input_disabled)
|
26
41
|
}
|
27
42
|
end
|
28
43
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'glimmer/opal/property_owner'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module Opal
|
5
|
+
class LayoutDataProxy
|
6
|
+
include PropertyOwner
|
7
|
+
attr_reader :parent, :args, :horizontal_alignment, :grab_excess_horizontal_space
|
8
|
+
|
9
|
+
def initialize(parent, args)
|
10
|
+
@parent = parent
|
11
|
+
@args = args
|
12
|
+
reapply
|
13
|
+
end
|
14
|
+
|
15
|
+
def horizontal_alignment=(horizontal_alignment)
|
16
|
+
@horizontal_alignment = horizontal_alignment
|
17
|
+
reapply
|
18
|
+
end
|
19
|
+
|
20
|
+
def grab_excess_horizontal_space=(grab_excess_horizontal_space)
|
21
|
+
@grab_excess_horizontal_space = grab_excess_horizontal_space
|
22
|
+
reapply
|
23
|
+
end
|
24
|
+
|
25
|
+
def reapply
|
26
|
+
# @parent.css = <<~CSS
|
27
|
+
# CSS
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'glimmer/opal/element_proxy'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module Opal
|
5
|
+
class ListProxy < ElementProxy
|
6
|
+
ITEM_EMPTY = '_____'
|
7
|
+
attr_reader :items, :selection
|
8
|
+
|
9
|
+
def initialize(parent, args)
|
10
|
+
super(parent, args)
|
11
|
+
@selection = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def items=(items)
|
15
|
+
@items = items.map {|item| item.strip == '' ? ITEM_EMPTY : item}
|
16
|
+
redraw
|
17
|
+
end
|
18
|
+
|
19
|
+
def index_of(item)
|
20
|
+
@items.index(item)
|
21
|
+
end
|
22
|
+
|
23
|
+
# used for multi-selection taking an array
|
24
|
+
def selection=(selection)
|
25
|
+
@selection = selection
|
26
|
+
redraw
|
27
|
+
end
|
28
|
+
|
29
|
+
# used for single selection taking an index
|
30
|
+
def select(index, meta = false)
|
31
|
+
selected_item = @items[index]
|
32
|
+
if @selection.include?(selected_item)
|
33
|
+
@selection.delete(selected_item) if meta
|
34
|
+
else
|
35
|
+
@selection = [] if !meta || (!has_style?(:multi) && @selection.to_a.size >= 1)
|
36
|
+
@selection << selected_item
|
37
|
+
end
|
38
|
+
self.selection = @selection
|
39
|
+
end
|
40
|
+
|
41
|
+
def observation_request_to_event_mapping
|
42
|
+
{
|
43
|
+
'on_widget_selected' => {
|
44
|
+
event: 'click',
|
45
|
+
event_handler: -> (event_listener) {
|
46
|
+
-> (event) {
|
47
|
+
selected_item = event.target.text
|
48
|
+
select(index_of(selected_item), event.meta?)
|
49
|
+
event_listener.call(event)
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def name
|
57
|
+
'ul'
|
58
|
+
end
|
59
|
+
|
60
|
+
def dom
|
61
|
+
list_items = @items
|
62
|
+
list_id = id
|
63
|
+
list_style = css
|
64
|
+
list_selection = selection
|
65
|
+
@dom ||= DOM {
|
66
|
+
ul(id: list_id, style: list_style) {
|
67
|
+
list_items.to_a.each_with_index do |item, index|
|
68
|
+
li_class = ''
|
69
|
+
li_class += ' selected-list-item' if list_selection.include?(item)
|
70
|
+
li_class += ' empty-list-item' if item == ITEM_EMPTY
|
71
|
+
li(class: li_class) {
|
72
|
+
item
|
73
|
+
}
|
74
|
+
end
|
75
|
+
}
|
76
|
+
}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'glimmer/opal/element_proxy'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module Opal
|
5
|
+
class Modal < ElementProxy
|
6
|
+
attr_reader :text, :message
|
7
|
+
|
8
|
+
def initialize(parent, args)
|
9
|
+
i = 0
|
10
|
+
@parent = parent
|
11
|
+
@args = args
|
12
|
+
@children = Set.new
|
13
|
+
@css_classes = Set.new(['modal'])
|
14
|
+
@css = ''
|
15
|
+
@enabled = true
|
16
|
+
content do
|
17
|
+
on_widget_selected {
|
18
|
+
hide
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def text=(txt)
|
24
|
+
@text = txt
|
25
|
+
redraw if @dom
|
26
|
+
end
|
27
|
+
|
28
|
+
def message=(msg)
|
29
|
+
@message = msg
|
30
|
+
redraw if @dom
|
31
|
+
end
|
32
|
+
|
33
|
+
def document
|
34
|
+
element = self
|
35
|
+
begin
|
36
|
+
element = element.parent
|
37
|
+
end while(element.parent)
|
38
|
+
element
|
39
|
+
end
|
40
|
+
|
41
|
+
def open
|
42
|
+
document.add_child(self)
|
43
|
+
end
|
44
|
+
|
45
|
+
def hide
|
46
|
+
dom.remove
|
47
|
+
end
|
48
|
+
|
49
|
+
def content(&block)
|
50
|
+
Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Opal::MessageBoxExpression.new, &block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def name
|
54
|
+
'div'
|
55
|
+
end
|
56
|
+
|
57
|
+
def selector
|
58
|
+
super + ' .close'
|
59
|
+
end
|
60
|
+
|
61
|
+
def observation_request_to_event_mapping
|
62
|
+
{
|
63
|
+
'on_widget_selected' => {
|
64
|
+
event: 'click'
|
65
|
+
},
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def dom
|
70
|
+
modal_id = id
|
71
|
+
modal_style = css
|
72
|
+
modal_text = text
|
73
|
+
modal_message = message
|
74
|
+
modal_css_classes = css_classes
|
75
|
+
modal_class = modal_css_classes.to_a.join(' ')
|
76
|
+
@dom ||= DOM {
|
77
|
+
div(id: modal_id, style: modal_style, class: modal_class) {
|
78
|
+
div(class: 'modal-content') {
|
79
|
+
header.text {
|
80
|
+
modal_text
|
81
|
+
}
|
82
|
+
p.message {
|
83
|
+
modal_message
|
84
|
+
}
|
85
|
+
input(type: 'button', class: 'close', autofocus: 'autofocus', value: 'OK')
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
require 'glimmer/dsl/opal/message_box_expression'
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Glimmer
|
2
|
+
module Opal
|
3
|
+
# Adapts Glimmer UI classes to SWT JavaBean property owner classes (which are now adapted to Opal)
|
4
|
+
module PropertyOwner
|
5
|
+
def get_attribute(attribute_name)
|
6
|
+
send(attribute_getter(attribute_name))
|
7
|
+
end
|
8
|
+
|
9
|
+
def set_attribute(attribute_name, *args)
|
10
|
+
send(attribute_setter(attribute_name), *args) unless send(attribute_getter(attribute_name)) == args.first
|
11
|
+
end
|
12
|
+
|
13
|
+
def attribute_setter(attribute_name)
|
14
|
+
"#{attribute_name.to_s.underscore}="
|
15
|
+
end
|
16
|
+
|
17
|
+
def attribute_getter(attribute_name)
|
18
|
+
attribute_name.to_s.underscore
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -41,8 +41,9 @@ module Glimmer
|
|
41
41
|
select_text = @text
|
42
42
|
items = @items
|
43
43
|
select_id = id
|
44
|
+
select_style = css
|
44
45
|
@dom ||= DOM {
|
45
|
-
select(id: select_id) {
|
46
|
+
select(id: select_id, style: select_style) {
|
46
47
|
items.to_a.each do |item|
|
47
48
|
option_hash = {value: item}
|
48
49
|
option_hash[:selected] = 'selected' if select_text == item
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'glimmer/opal/div_proxy'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module Opal
|
5
|
+
class TabFolder < ElementProxy
|
6
|
+
attr_reader :tabs
|
7
|
+
|
8
|
+
def initialize(parent, args)
|
9
|
+
super(parent, args)
|
10
|
+
@tabs = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_child(child)
|
14
|
+
super(child)
|
15
|
+
if @children.size == 1
|
16
|
+
child.show
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def hide_all_tab_content
|
21
|
+
@children.each(&:hide)
|
22
|
+
end
|
23
|
+
|
24
|
+
def name
|
25
|
+
'div'
|
26
|
+
end
|
27
|
+
|
28
|
+
def tabs_dom
|
29
|
+
tabs_id = id + '-tabs'
|
30
|
+
@tabs_dom ||= DOM {
|
31
|
+
div(id: tabs_id, class: 'tabs')
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def dom
|
36
|
+
tab_folder_id = id
|
37
|
+
tab_folder_id_style = css
|
38
|
+
@dom ||= DOM {
|
39
|
+
div(id: tab_folder_id, style: tab_folder_id_style, class: 'tab-folder') {
|
40
|
+
|
41
|
+
}
|
42
|
+
}.tap {|the_dom| the_dom << tabs_dom }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'glimmer/opal/input_proxy'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module Opal
|
5
|
+
class TabItem < DivProxy
|
6
|
+
include Glimmer
|
7
|
+
attr_reader :text, :content_visible
|
8
|
+
|
9
|
+
def initialize(parent, args)
|
10
|
+
super(parent, args)
|
11
|
+
css_classes << 'tab-item'
|
12
|
+
content do
|
13
|
+
on_widget_selected {
|
14
|
+
@parent.hide_all_tab_content
|
15
|
+
show
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def content(&block)
|
21
|
+
Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Opal::TabItemExpression.new, &block)
|
22
|
+
end
|
23
|
+
|
24
|
+
def show
|
25
|
+
@content_visible = true
|
26
|
+
redraw
|
27
|
+
end
|
28
|
+
|
29
|
+
def hide
|
30
|
+
@content_visible = false
|
31
|
+
redraw
|
32
|
+
end
|
33
|
+
|
34
|
+
def text=(value)
|
35
|
+
@text = value
|
36
|
+
redraw
|
37
|
+
end
|
38
|
+
|
39
|
+
def name
|
40
|
+
'button'
|
41
|
+
end
|
42
|
+
|
43
|
+
def selector
|
44
|
+
super + '-tab'
|
45
|
+
end
|
46
|
+
|
47
|
+
def observation_request_to_event_mapping
|
48
|
+
{
|
49
|
+
'on_widget_selected' => {
|
50
|
+
event: 'click'
|
51
|
+
},
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def redraw
|
56
|
+
if @tab_dom
|
57
|
+
old_tab_dom = @tab_dom
|
58
|
+
@tab_dom = nil
|
59
|
+
old_tab_dom.replace tab_dom
|
60
|
+
else
|
61
|
+
tab_dom
|
62
|
+
end
|
63
|
+
super
|
64
|
+
end
|
65
|
+
|
66
|
+
def tab_dom
|
67
|
+
tab_id = id + '-tab'
|
68
|
+
tab_text = text
|
69
|
+
tab_active = content_visible ? 'active' : ''
|
70
|
+
@tab_dom ||= DOM {
|
71
|
+
button(id: tab_id, class: "tab #{tab_active}") {
|
72
|
+
tab_text
|
73
|
+
}
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def dom
|
78
|
+
tab_item_id = id
|
79
|
+
tab_item_id_style = css
|
80
|
+
tab_item_css_classes = css_classes
|
81
|
+
if content_visible
|
82
|
+
tab_item_css_classes.delete('hide')
|
83
|
+
else
|
84
|
+
tab_item_css_classes << 'hide'
|
85
|
+
end
|
86
|
+
if !@parent.tabs.include?(self)
|
87
|
+
@parent.tabs_dom << tab_dom
|
88
|
+
@parent.tabs << self
|
89
|
+
end
|
90
|
+
@dom ||= DOM {
|
91
|
+
div(id: tab_item_id, style: tab_item_id_style, class: tab_item_css_classes.to_a.join(' ')) {
|
92
|
+
}
|
93
|
+
}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
require 'glimmer/dsl/opal/tab_item_expression'
|