glimmer-dsl-opal 0.0.2 → 0.0.7

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +704 -40
  3. data/VERSION +1 -1
  4. data/lib/glimmer-dsl-opal.rb +3 -2
  5. data/lib/glimmer/data_binding/element_binding.rb +1 -1
  6. data/lib/glimmer/data_binding/ext/observable_model.rb +40 -0
  7. data/lib/glimmer/data_binding/list_selection_binding.rb +51 -0
  8. data/lib/glimmer/dsl/opal/async_exec_expression.rb +17 -0
  9. data/lib/glimmer/dsl/opal/browser_expression.rb +17 -0
  10. data/lib/glimmer/dsl/opal/button_expression.rb +1 -0
  11. data/lib/glimmer/dsl/opal/dsl.rb +15 -1
  12. data/lib/glimmer/dsl/opal/grid_layout_expression.rb +17 -0
  13. data/lib/glimmer/dsl/opal/layout_data_expression.rb +17 -0
  14. data/lib/glimmer/dsl/opal/list_expression.rb +17 -0
  15. data/lib/glimmer/dsl/opal/list_selection_data_binding_expression.rb +42 -0
  16. data/lib/glimmer/dsl/opal/message_box_expression.rb +20 -0
  17. data/lib/glimmer/dsl/opal/observe_expression.rb +32 -0
  18. data/lib/glimmer/dsl/opal/property_expression.rb +6 -2
  19. data/lib/glimmer/dsl/opal/tab_folder_expression.rb +17 -0
  20. data/lib/glimmer/dsl/opal/tab_item_expression.rb +17 -0
  21. data/lib/glimmer/dsl/opal/text_expression.rb +22 -0
  22. data/lib/glimmer/opal/display_proxy.rb +23 -0
  23. data/lib/glimmer/opal/div_proxy.rb +9 -1
  24. data/lib/glimmer/opal/document_proxy.rb +131 -5
  25. data/lib/glimmer/opal/element_proxy.rb +246 -11
  26. data/lib/glimmer/opal/grid_layout_proxy.rb +54 -0
  27. data/lib/glimmer/opal/iframe_proxy.rb +23 -0
  28. data/lib/glimmer/opal/input_proxy.rb +16 -1
  29. data/lib/glimmer/opal/label_proxy.rb +2 -1
  30. data/lib/glimmer/opal/layout_data_proxy.rb +31 -0
  31. data/lib/glimmer/opal/list_proxy.rb +80 -0
  32. data/lib/glimmer/opal/modal.rb +94 -0
  33. data/lib/glimmer/opal/point.rb +5 -0
  34. data/lib/glimmer/opal/property_owner.rb +22 -0
  35. data/lib/glimmer/opal/select_proxy.rb +2 -1
  36. data/lib/glimmer/opal/tab_folder.rb +46 -0
  37. data/lib/glimmer/opal/tab_item.rb +98 -0
  38. data/lib/samples/elaborate/login.rb +0 -1
  39. data/lib/samples/elaborate/tic_tac_toe.rb +5 -5
  40. data/lib/samples/hello/hello_tab.rb +2 -2
  41. 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, type: 'button', value: input_text
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
@@ -13,8 +13,9 @@ module Glimmer
13
13
  def dom
14
14
  label_text = @text
15
15
  label_id = id
16
+ label_style = css
16
17
  @dom ||= DOM {
17
- label(id: label_id) {
18
+ label(id: label_id, style: label_style) {
18
19
  label_text
19
20
  }
20
21
  }
@@ -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,5 @@
1
+ module Glimmer
2
+ module Opal
3
+ Point = Struct.new(:x, :y)
4
+ end
5
+ end
@@ -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'