glimmer 0.1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/COPYING.LGPL +504 -0
  2. data/README +27 -0
  3. data/samples/contactmanager/contact.rb +12 -0
  4. data/samples/contactmanager/contact_manager.rb +65 -0
  5. data/samples/contactmanager/contact_manager_presenter.rb +23 -0
  6. data/samples/contactmanager/contact_repository.rb +27 -0
  7. data/samples/hello_world.rb +26 -0
  8. data/samples/login.rb +97 -0
  9. data/samples/tictactoe/tic_tac_toe.rb +67 -0
  10. data/samples/tictactoe/tic_tac_toe_board.rb +149 -0
  11. data/src/command_handler.rb +11 -0
  12. data/src/command_handler_chain_factory.rb +23 -0
  13. data/src/command_handler_chain_link.rb +22 -0
  14. data/src/command_handlers.rb +26 -0
  15. data/src/command_handlers/bind_command_handler.rb +29 -0
  16. data/src/command_handlers/data_binding_command_handler.rb +64 -0
  17. data/src/command_handlers/models/model_observer.rb +25 -0
  18. data/src/command_handlers/models/observable_array.rb +46 -0
  19. data/src/command_handlers/models/observable_model.rb +35 -0
  20. data/src/command_handlers/models/r_runnable.rb +14 -0
  21. data/src/command_handlers/models/r_shell.rb +27 -0
  22. data/src/command_handlers/models/r_widget.rb +146 -0
  23. data/src/command_handlers/models/r_widget_listener.rb +12 -0
  24. data/src/command_handlers/models/r_widget_packages.rb +9 -0
  25. data/src/command_handlers/models/table_items_updater.rb +39 -0
  26. data/src/command_handlers/models/widget_observer.rb +23 -0
  27. data/src/command_handlers/shell_command_handler.rb +18 -0
  28. data/src/command_handlers/swt_constant_command_handler.rb +22 -0
  29. data/src/command_handlers/table_column_properties_data_binding_command_handler.rb +24 -0
  30. data/src/command_handlers/table_items_data_binding_command_handler.rb +30 -0
  31. data/src/command_handlers/widget_command_handler.rb +26 -0
  32. data/src/command_handlers/widget_listener_command_handler.rb +35 -0
  33. data/src/command_handlers/widget_method_command_handler.rb +22 -0
  34. data/src/glimmer.rb +45 -0
  35. data/src/parent.rb +8 -0
  36. data/src/shine.rb +24 -0
  37. data/src/swt.rb +10 -0
  38. data/src/xml.rb +10 -0
  39. data/src/xml_command_handlers.rb +18 -0
  40. data/src/xml_command_handlers/html_command_handler.rb +49 -0
  41. data/src/xml_command_handlers/models/depth_first_search_iterator.rb +20 -0
  42. data/src/xml_command_handlers/models/name_space_visitor.rb +21 -0
  43. data/src/xml_command_handlers/models/node.rb +83 -0
  44. data/src/xml_command_handlers/models/node_visitor.rb +12 -0
  45. data/src/xml_command_handlers/models/xml_visitor.rb +62 -0
  46. data/src/xml_command_handlers/xml_command_handler.rb +22 -0
  47. data/src/xml_command_handlers/xml_name_space_command_handler.rb +34 -0
  48. data/src/xml_command_handlers/xml_tag_command_handler.rb +26 -0
  49. data/src/xml_command_handlers/xml_text_command_handler.rb +22 -0
  50. data/test/glimmer_constant_test.rb +36 -0
  51. data/test/glimmer_data_binding_test.rb +236 -0
  52. data/test/glimmer_listeners_test.rb +61 -0
  53. data/test/glimmer_shine_data_binding_test.rb +88 -0
  54. data/test/glimmer_table_data_binding_test.rb +135 -0
  55. data/test/glimmer_test.rb +233 -0
  56. data/test/observable_model_test.rb +27 -0
  57. data/test/r_widget_test.rb +52 -0
  58. data/test/samples/contactmanager/contact_manager_presenter_test.rb +60 -0
  59. data/test/samples/tictactoe/tic_tac_toe_test.rb +265 -0
  60. data/test/xml/glimmer_xml_test.rb +163 -0
  61. metadata +126 -0
@@ -0,0 +1,20 @@
1
+ # Copyright (C) 2007-2008 Annas Al Maleh
2
+ # Licensed under the LGPL. See /COPYING.LGPL for more details.
3
+
4
+ class DepthFirstSearchIterator
5
+ def initialize(node, node_visitor)
6
+ @node = node
7
+ @node_visitor = node_visitor
8
+ end
9
+
10
+ def iterate
11
+ process(@node)
12
+ end
13
+
14
+ def process(node)
15
+ @node_visitor.process_before_children(node)
16
+ node.children.each { |child| process(child) } unless node.is_a?(String)
17
+ @node_visitor.process_after_children(node)
18
+ end
19
+
20
+ end
@@ -0,0 +1,21 @@
1
+ # Copyright (C) 2007-2008 Annas Al Maleh
2
+ # Licensed under the LGPL. See /COPYING.LGPL for more details.
3
+
4
+ require File.dirname(__FILE__) + "/node_visitor"
5
+
6
+ class NameSpaceVisitor < NodeVisitor
7
+
8
+ def initialize(name_space_name)
9
+ @name_space_name = name_space_name
10
+ end
11
+
12
+ def process_before_children(node)
13
+ return if node.is_a?(String)
14
+ node.name_space = Node.new(nil, @name_space_name, nil) if node and !node.name_space
15
+ end
16
+
17
+ def process_after_children(node)
18
+ #NOOP
19
+ end
20
+
21
+ end
@@ -0,0 +1,83 @@
1
+ # Copyright (C) 2007-2008 Annas Al Maleh
2
+ # Licensed under the LGPL. See /COPYING.LGPL for more details.
3
+
4
+ require File.dirname(__FILE__) + "/depth_first_search_iterator"
5
+ require File.dirname(__FILE__) + "/xml_visitor"
6
+
7
+ class Node
8
+ include Parent, Glimmer
9
+
10
+ attr_accessor :children, :name, :contents, :attributes, :is_name_space, :is_attribute, :name_space, :parent
11
+
12
+ def initialize(parent, name, attributes, &contents)
13
+ @is_name_space = false
14
+ @children = []
15
+ @parent = parent
16
+ if (parent and parent.is_name_space)
17
+ @name_space = parent
18
+ @parent = @name_space.parent
19
+ end
20
+ @parent.children << self if @parent
21
+ @name = name
22
+ @contents = contents
23
+ @attributes = attributes
24
+ if @attributes
25
+ @attributes.each_key do |attribute|
26
+ if attribute.is_a?(Node)
27
+ attribute.is_attribute = true
28
+ attribute.parent.children.delete(attribute) if attribute.parent
29
+ attribute.parent = nil #attributes do not usually have parents
30
+ end
31
+ end
32
+ p attributes
33
+ end
34
+ end
35
+
36
+ def method_missing(symbol, *args, &block)
37
+ @is_name_space = true
38
+ parent.children.delete(self) if parent
39
+ Glimmer.add_contents(self) {@tag = super}
40
+ @tag
41
+ end
42
+
43
+ def to_xml
44
+ xml_visitor = XmlVisitor.new
45
+ DepthFirstSearchIterator.new(self, xml_visitor).iterate
46
+ xml_visitor.document
47
+ end
48
+
49
+ def process_block(block)
50
+ return_value = block.call(@widget)
51
+ if return_value.is_a?(String) and !@children.include?(return_value)
52
+ text = return_value
53
+ first_match = text.match(/[#][^{]+[{][^}]+[}]/)
54
+ match = first_match
55
+ while (match)
56
+ Glimmer.module_eval(text_command(match.pre_match))
57
+ tag_text = match.to_s
58
+ Glimmer.module_eval(rubyize(tag_text))
59
+ text = tag_text
60
+ post_match = match.post_match
61
+ match = text.match(/[#]\w+[{]\w+[}]/)
62
+ end
63
+ Glimmer.module_eval(text_command(post_match)) if post_match
64
+ @children << return_value unless first_match
65
+ end
66
+ end
67
+
68
+ def text_command(text)
69
+ "text \"#{text}\""
70
+ end
71
+
72
+ def rubyize(text)
73
+ text = text.gsub(/[}]/, '"}')
74
+ text = text.gsub(/[{]/, '{"')
75
+ text = text.gsub(/[#]/, '')
76
+ end
77
+
78
+ #override Object default id method and route it to Glimmer engine
79
+ def id
80
+ method_missing(:id)
81
+ end
82
+
83
+ end
@@ -0,0 +1,12 @@
1
+ # Copyright (C) 2007-2008 Annas Al Maleh
2
+ # Licensed under the LGPL. See /COPYING.LGPL for more details.
3
+
4
+ class NodeVisitor
5
+ def process_before_children
6
+ raise "must be implemented by a class"
7
+ end
8
+
9
+ def process_after_children
10
+ raise "must be implemented by a class"
11
+ end
12
+ end
@@ -0,0 +1,62 @@
1
+ # Copyright (C) 2007-2008 Annas Al Maleh
2
+ # Licensed under the LGPL. See /COPYING.LGPL for more details.
3
+
4
+ require File.dirname(__FILE__) + "/node_visitor"
5
+
6
+ class XmlVisitor < NodeVisitor
7
+
8
+ attr_reader :document
9
+
10
+ def initialize
11
+ @document = ""
12
+ end
13
+
14
+ def process_before_children(node)
15
+ if (node.is_a?(String))
16
+ @document << node
17
+ return
18
+ end
19
+ begin_open_tag(node)
20
+ append_attributes(node) if node.attributes
21
+ end_open_tag(node)
22
+ end
23
+
24
+ def process_after_children(node)
25
+ return if (node.is_a?(String))
26
+ append_close_tag(node)
27
+ end
28
+
29
+ def begin_open_tag(node)
30
+ @document << "<"
31
+ @document << "#{node.name_space.name}:" if node.name_space
32
+ @document << node.name
33
+ end
34
+
35
+ def end_open_tag(node)
36
+ if (node.contents)
37
+ @document << ">"
38
+ else
39
+ @document << " " if node.attributes.keys.size > 0
40
+ @document << "/>"
41
+ end
42
+ end
43
+
44
+ def append_close_tag(node)
45
+ if (node.contents)
46
+ @document << "</"
47
+ @document << "#{node.name_space.name}:" if node.name_space
48
+ @document << "#{node.name}>"
49
+ end
50
+ end
51
+
52
+ def append_attributes(node)
53
+ puts "Take 3"
54
+ p node.attributes
55
+ node.attributes.each_key do |attribute|
56
+ attribute_name = attribute
57
+ attribute_name = "#{attribute.name_space.name}:#{attribute.name}" if attribute.is_a?(Node)
58
+ @document << " #{attribute_name}=\"#{node.attributes[attribute]}\""
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,22 @@
1
+ # Copyright (C) 2007-2008 Annas Al Maleh
2
+ # Licensed under the LGPL. See /COPYING.LGPL for more details.
3
+
4
+ require "facets/dictionary"
5
+ require File.dirname(__FILE__) + "/../command_handler"
6
+ require File.dirname(__FILE__) + "/models/node"
7
+
8
+ class XmlCommandHandler
9
+ include CommandHandler
10
+
11
+ def can_handle?(parent, command_symbol, *args, &block)
12
+ (parent == nil or parent.is_a?(Node)) and
13
+ (args.size == 0 or ((args.size == 1) and ((args[0].is_a?(Hash)) or (args[0].is_a?(Hash)))))
14
+ end
15
+
16
+ def do_handle(parent, command_symbol, *args, &block)
17
+ attributes = Dictionary.new
18
+ attributes = args[0] if (args.size == 1)
19
+ Node.new(parent, command_symbol.to_s, attributes, &block)
20
+ end
21
+
22
+ end
@@ -0,0 +1,34 @@
1
+ # Copyright (C) 2007-2008 Annas Al Maleh
2
+ # Licensed under the LGPL. See /COPYING.LGPL for more details.
3
+
4
+ require File.dirname(__FILE__) + "/../command_handler"
5
+ require File.dirname(__FILE__) + "/models/node"
6
+ require File.dirname(__FILE__) + "/models/depth_first_search_iterator"
7
+ require File.dirname(__FILE__) + "/models/name_space_visitor"
8
+
9
+ class XmlNameSpaceCommandHandler
10
+ include CommandHandler, Glimmer
11
+
12
+ def can_handle?(parent, command_symbol, *args, &block)
13
+ (parent == nil or parent.is_a?(Node)) and
14
+ (command_symbol.to_s == "name_space")
15
+ (args.size == 1) and
16
+ (args[0].is_a?(Symbol)) and
17
+ block
18
+ end
19
+
20
+ def do_handle(parent, command_symbol, *args, &block)
21
+ node = block.call
22
+ unless node.is_a?(String)
23
+ name_space_visitor = NameSpaceVisitor.new(args[0].to_s)
24
+ DepthFirstSearchIterator.new(node, name_space_visitor).iterate
25
+ def node.process_block(block)
26
+ puts 'block'
27
+ #NOOP
28
+ end
29
+ end
30
+ parent.children << node if parent and !parent.children.include?(node)
31
+ node
32
+ end
33
+
34
+ end
@@ -0,0 +1,26 @@
1
+ # Copyright (C) 2007-2008 Annas Al Maleh
2
+ # Licensed under the LGPL. See /COPYING.LGPL for more details.
3
+
4
+ require "facets/dictionary"
5
+ require File.dirname(__FILE__) + "/../command_handler"
6
+ require File.dirname(__FILE__) + "/models/node"
7
+
8
+ class XmlTagCommandHandler
9
+ include CommandHandler
10
+
11
+ def can_handle?(parent, command_symbol, *args, &block)
12
+ (parent == nil or parent.is_a?(Node)) and
13
+ (command_symbol.to_s == "tag") and
14
+ ((args.size == 1) and ((args[0].is_a?(Hash)) or (args[0].is_a?(Hash)))) and
15
+ args[0].include?(:_name)
16
+ end
17
+
18
+ def do_handle(parent, command_symbol, *args, &block)
19
+ attributes = nil
20
+ attributes = args[0] if (args.size == 1)
21
+ tag_name = attributes[:_name]
22
+ attributes.delete(:_name)
23
+ Node.new(parent, tag_name, attributes, &block)
24
+ end
25
+
26
+ end
@@ -0,0 +1,22 @@
1
+ # Copyright (C) 2007-2008 Annas Al Maleh
2
+ # Licensed under the LGPL. See /COPYING.LGPL for more details.
3
+
4
+ require File.dirname(__FILE__) + "/../command_handler"
5
+ require File.dirname(__FILE__) + "/models/node"
6
+
7
+ class XmlTextCommandHandler
8
+ include CommandHandler
9
+
10
+ def can_handle?(parent, command_symbol, *args, &block)
11
+ (parent == nil or parent.is_a?(Node)) and
12
+ (command_symbol.to_s == "text") and
13
+ ((args.size == 1) and (args[0].is_a?(String))) and
14
+ !block
15
+ end
16
+
17
+ def do_handle(parent, command_symbol, *args, &block)
18
+ parent.children << args[0] if parent
19
+ args[0]
20
+ end
21
+
22
+ end
@@ -0,0 +1,36 @@
1
+ # Copyright (C) 2007-2008 Annas Al Maleh
2
+ # Licensed under the LGPL. See /COPYING.LGPL for more details.
3
+
4
+ require "test/unit"
5
+ require File.dirname(__FILE__) + "/../src/swt"
6
+
7
+ class GlimmerTest < Test::Unit::TestCase
8
+ include Glimmer
9
+
10
+ include_package 'org.eclipse.swt'
11
+ include_package 'org.eclipse.swt.widgets'
12
+ include_package 'org.eclipse.swt.layout'
13
+
14
+ def teardown
15
+ @target.display.dispose if @target.display
16
+ end
17
+
18
+ def test_shell_with_default_layout
19
+ @target = shell {
20
+ composite(border | no_focus) {
21
+ }
22
+ }
23
+
24
+ assert_equal 1, @target.widget.children.size
25
+ assert_instance_of Composite, @target.widget.children[0]
26
+ composite_widget = @target.widget.children[0]
27
+ assert_has_style SWT::NO_FOCUS, composite_widget
28
+ assert_has_style SWT::BORDER, composite_widget
29
+ end
30
+
31
+ def assert_has_style(style, widget)
32
+ assert_equal style, widget.getStyle & style
33
+ end
34
+
35
+ end
36
+
@@ -0,0 +1,236 @@
1
+ # Copyright (C) 2007-2008 Annas Al Maleh
2
+ # Licensed under the LGPL. See /COPYING.LGPL for more details.
3
+
4
+ require "test/unit"
5
+ require File.dirname(__FILE__) + "/../src/swt"
6
+
7
+ class GlimmerDataBindingTest < Test::Unit::TestCase
8
+ include Glimmer
9
+
10
+ include_package 'org.eclipse.swt'
11
+ include_package 'org.eclipse.swt.widgets'
12
+ include_package 'org.eclipse.swt.layout'
13
+
14
+ def teardown
15
+ @target.display.dispose if @target.display
16
+ end
17
+
18
+ class Person
19
+ attr_accessor :name, :age, :adult
20
+ end
21
+
22
+ def test_text_widget_data_binding_string_property
23
+ person = Person.new
24
+ person.name = "Bruce Ting"
25
+
26
+ @target = shell {
27
+ composite {
28
+ @text = text {
29
+ text bind(person, :name)
30
+ }
31
+ }
32
+ }
33
+
34
+ assert_equal "Bruce Ting", @text.widget.getText
35
+
36
+ person.name = "Lady Butterfly"
37
+ assert_equal "Lady Butterfly", @text.widget.getText
38
+
39
+ @text.widget.setText("Allen Cork")
40
+ assert_equal "Allen Cork", person.name
41
+ end
42
+
43
+ def test_text_widget_data_binding_fixnum_property
44
+ person = Person.new
45
+ person.age = 15
46
+
47
+ @target = shell {
48
+ composite {
49
+ @text = text {
50
+ text bind(person, :age, :fixnum)
51
+ }
52
+ }
53
+ }
54
+
55
+ assert_equal "15", @text.widget.getText
56
+
57
+ person.age = 27
58
+ assert_equal "27", @text.widget.getText
59
+
60
+ @text.widget.setText("30")
61
+ assert_equal 30, person.age
62
+ end
63
+
64
+ def test_label_widget_data_binding_string_property
65
+ person = Person.new
66
+ person.name = "Bruce Ting"
67
+
68
+ @target = shell {
69
+ composite {
70
+ @label = label {
71
+ text bind(person, :name)
72
+ }
73
+ }
74
+ }
75
+
76
+ assert_equal "Bruce Ting", @label.widget.getText
77
+
78
+ person.name = "Lady Butterfly"
79
+ assert_equal "Lady Butterfly", @label.widget.getText
80
+ end
81
+
82
+ def test_checkbox_widget_data_binding_boolean_property
83
+ person = Person.new
84
+ person.adult = true
85
+
86
+ @target = shell {
87
+ composite {
88
+ @check_box = button(SWT::CHECK) {
89
+ selection bind(person, :adult)
90
+ }
91
+ }
92
+ }
93
+
94
+ assert_equal true, @check_box.widget.getSelection
95
+
96
+ person.adult = false
97
+ assert_equal false, @check_box.widget.getSelection
98
+
99
+ @check_box.widget.setSelection(true)
100
+ @check_box.widget.notifyListeners(SWT::Selection, nil)
101
+ assert_equal true, person.adult
102
+ end
103
+
104
+ def test_radio_widget_data_binding_boolean_property
105
+ person = Person.new
106
+ person.adult = true
107
+
108
+ @target = shell {
109
+ composite {
110
+ @radio = button(SWT::RADIO) {
111
+ selection bind(person, :adult)
112
+ }
113
+ }
114
+ }
115
+
116
+ assert_equal true, @radio.widget.getSelection
117
+
118
+ person.adult = false
119
+ assert_equal false, @radio.widget.getSelection
120
+
121
+ @radio.widget.setSelection(true)
122
+ @radio.widget.notifyListeners(SWT::Selection, nil)
123
+ assert_equal true, person.adult
124
+ end
125
+
126
+ def test_spinner_widget_data_binding_fixnum_property
127
+ person = Person.new
128
+ person.age = 17
129
+
130
+ @target = shell {
131
+ composite {
132
+ @spinner = spinner {
133
+ selection bind(person, :age)
134
+ }
135
+ }
136
+ }
137
+
138
+ assert_equal 17, @spinner.widget.getSelection
139
+
140
+ person.age = 20
141
+ assert_equal 20, @spinner.widget.getSelection
142
+
143
+ @spinner.widget.setSelection(34)
144
+ @spinner.widget.notifyListeners(SWT::Selection, nil)
145
+ assert_equal 34, person.age
146
+ end
147
+
148
+ def test_widget_data_binding_enablement
149
+ person = Person.new
150
+ person.adult = true
151
+
152
+ @target = shell {
153
+ composite {
154
+ @text = text {
155
+ enabled bind(person, :adult)
156
+ }
157
+ }
158
+ }
159
+
160
+ assert_equal true, @text.widget.isEnabled
161
+
162
+ person.adult = false
163
+ assert_equal false, @text.widget.isEnabled
164
+ end
165
+
166
+ def test_multiple_widget_data_binding_enablement_to_same_model_property
167
+ person = Person.new
168
+ person.adult = true
169
+
170
+ @target = shell {
171
+ composite {
172
+ @text = text {
173
+ enabled bind(person, :adult)
174
+ }
175
+ @text2 = text {
176
+ enabled bind(person, :adult)
177
+ }
178
+ @text3 = text {
179
+ enabled bind(person, :adult)
180
+ }
181
+ }
182
+ }
183
+
184
+ assert_equal true, @text.widget.isEnabled
185
+ assert_equal true, @text2.widget.isEnabled
186
+ assert_equal true, @text3.widget.isEnabled
187
+
188
+ person.adult = false
189
+ assert_equal false, @text.widget.isEnabled
190
+ assert_equal false, @text2.widget.isEnabled
191
+ assert_equal false, @text3.widget.isEnabled
192
+ end
193
+
194
+ def test_multiple_widget_data_bindings_to_different_model_properties
195
+ person = Person.new
196
+ person.name = "Nancy"
197
+ person.age = 15
198
+ person.adult = true
199
+
200
+ @target = shell {
201
+ composite {
202
+ @label = label {
203
+ text bind(person, :name)
204
+ }
205
+ @text = text {
206
+ text bind(person, :age, :fixnum)
207
+ }
208
+ @check_box = button(SWT::CHECK) {
209
+ selection bind(person, :adult)
210
+ }
211
+ }
212
+ }
213
+
214
+ assert_equal "Nancy", @label.widget.getText
215
+ assert_equal "15", @text.widget.getText
216
+ assert_equal true, @check_box.widget.getSelection
217
+
218
+ person.name = "Drew"
219
+ assert_equal "Drew", @label.widget.getText
220
+
221
+ person.age = 27
222
+ assert_equal "27", @text.widget.getText
223
+
224
+ person.adult = false
225
+ assert_equal false, @check_box.widget.getSelection
226
+
227
+ @text.widget.setText("30")
228
+ assert_equal 30, person.age
229
+
230
+ @check_box.widget.setSelection(true)
231
+ @check_box.widget.notifyListeners(SWT::Selection, nil)
232
+ assert_equal true, person.adult
233
+ end
234
+
235
+ end
236
+