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.
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'