fxri 0.3.3 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,192 +1,192 @@
1
- # Copyright (c) 2004, 2005 Martin Ankerl
2
- require 'set'
3
-
4
- # Packet_List is a more convenient wrapper for FXIconList. This class has to be used
5
- # in combination with Packet_Item.
6
- class Packet_List < FXIconList
7
- include Responder
8
-
9
- # Create a new Packet_List. All parameters are passed to the parental constructor FXIconList.
10
- def initialize(data, *args)
11
- @data = data
12
- @sort_mutex = Mutex.new
13
- @sort_thread = nil
14
- if FOXVERSION=="1.0"
15
- def getItem(num)
16
- retrieveItem(num)
17
- end
18
- end
19
-
20
- @header_item_index = 0
21
- @reversed = true
22
- @conversions = Array.new
23
- @items = Set.new
24
- super(*args)
25
-
26
- header.connect(SEL_COMMAND) do |sender, sel, item_number|
27
- on_cmd_header(item_number)
28
- end
29
-
30
-
31
- # HACK: only works when one header is there.
32
- self.connect(SEL_CONFIGURE) do |sender, sel, data|
33
- update_header_width
34
- end
35
- end
36
-
37
- def create
38
- super
39
- recalc
40
- end
41
-
42
- # HACK: only works when one header is there.
43
- def update_header_width
44
- header.setItemSize(0, width-verticalScrollBar.width)
45
- recalc
46
- end
47
-
48
-
49
- # Called whenever a header is clicked
50
- def on_cmd_header(header_item_index)
51
- @data.gui_mutex.synchronize do
52
- header.setArrowDir(@header_item_index, MAYBE)
53
- if @header_item_index == header_item_index
54
- @reversed = !@reversed
55
- else
56
- @reversed = true
57
- end
58
- @header_item_index = header_item_index
59
- header.setArrowDir(@header_item_index, @reversed)
60
- sortItems
61
- end
62
- # sort array
63
- @data.items.sort! do |a, b|
64
- cmp = a.sortable(header_item_index) <=> b.sortable(header_item_index)
65
- if @reversed
66
- -cmp
67
- else
68
- cmp
69
- end
70
- end
71
- return 0
72
- end
73
-
74
- def sortItems
75
- @items.each do |item|
76
- item.update_sort_key
77
- end
78
- super
79
- end
80
-
81
- # Check if the search order is reversed (happens when clicking on the same header twice)
82
- def reversed?
83
- @reversed
84
- end
85
-
86
- # Get index of the header that should be used for sorting
87
- def sort_index
88
- @header_item_index
89
- end
90
-
91
- # Add a new header. The block that you need to specify is used to convert a string of this
92
- # column into something that can be used for sorting. The yielded parameter item_colum_text
93
- # is the text of one item of this column.
94
- def add_header(text, width, &conversion) # :yields: item_column_text
95
- appendHeader(text, nil, width)
96
- header.setArrowDir(0, false) if @conversions.empty?
97
- @conversions.push conversion
98
- end
99
-
100
- # Create a new Packet_Item. After the icon, you can specify the text for each of the columns.
101
- # Here is an example:
102
- # list.create_item(my_icon, "Martin", "Ankerl", "2005")
103
- def create_item(icon, *args)
104
- Packet_Item.new(self, icon, *args)
105
- end
106
-
107
- # Add a new Packet_Item to this list.Called from within Packet_Item during Packet_Item#parent=
108
- def add_item(item)
109
- @items.add item
110
- appendItem(item.fox_item)
111
- item
112
- end
113
-
114
- # Remove the given Packet_Item from the list. This is slow, because
115
- # the item has to be searched with a linear search. To remove all items
116
- # use #clear.
117
- def remove_item(item)
118
- i = 0
119
- @items.delete item
120
- fox_item = item.fox_item
121
- i += 1 while i < numItems && fox_item != getItem(i)
122
- removeItem(i) if i < numItems
123
- item
124
- end
125
-
126
- def appendItem(*args)
127
- $fx_icon_item_remove_mutex.synchronize do
128
- #puts "appendItem"
129
- super
130
- end
131
- end
132
-
133
- # Before actually deleting, the item has to be marked as deleted to prevent
134
- # drawing afterwards.
135
- def removeItem(*args)
136
- $fx_icon_item_remove_mutex.synchronize do
137
- #puts "removeitem"
138
- # at first, mark item as deleted to prevent drawing afterwards
139
- getItem(args[0]).deleted
140
- # do the evil delete
141
- super
142
- end
143
- end
144
-
145
- # Remove all items, but do this within the mutex to be sure everything goes ok.
146
- def clearItems(*args)
147
- $fx_icon_item_remove_mutex.synchronize do
148
- #puts "clearitems"
149
- super
150
- end
151
- end
152
-
153
- # This may be called when the item is currently beeing deleted.
154
- # this method works only before or after the delete, therefore
155
- # the mutex is necessary.
156
- def getContentWidth(*args)
157
- $fx_icon_item_remove_mutex.synchronize do
158
- #puts "contentwidth"
159
- super
160
- end
161
- end
162
-
163
- # This may be called when the item is currently beeing deleted.
164
- # this method works only before or after the delete, therefore
165
- # the mutex is necessary.
166
- def getContentHeight(*args)
167
- $fx_icon_item_remove_mutex.synchronize do
168
- #puts "contentheight"
169
- super
170
- end
171
- end
172
-
173
- # Removes all items from the list.
174
- def clear
175
- @items.each { |item| item.clear }
176
- @items.clear
177
- # todo: mutex!?
178
- clearItems
179
- end
180
-
181
- # use in combination with Packet_Item#show
182
- def dirty_clear
183
- clearItems
184
- @items.clear
185
- end
186
-
187
- # Get the sort for a given header index. The sort function has been supplied
188
- # when calling #new. This is used from Packet_Item.
189
- def sort_function(header_item_index)
190
- @conversions[header_item_index]
191
- end
192
- end
1
+ # Copyright (c) 2004, 2005 Martin Ankerl
2
+ require 'set'
3
+
4
+ # Packet_List is a more convenient wrapper for FXIconList. This class has to be used
5
+ # in combination with Packet_Item.
6
+ class Packet_List < FXIconList
7
+ include Responder
8
+
9
+ # Create a new Packet_List. All parameters are passed to the parental constructor FXIconList.
10
+ def initialize(data, *args)
11
+ @data = data
12
+ @sort_mutex = Mutex.new
13
+ @sort_thread = nil
14
+ if FOXVERSION=="1.0"
15
+ def getItem(num)
16
+ retrieveItem(num)
17
+ end
18
+ end
19
+
20
+ @header_item_index = 0
21
+ @reversed = true
22
+ @conversions = Array.new
23
+ @items = Set.new
24
+ super(*args)
25
+
26
+ header.connect(SEL_COMMAND) do |sender, sel, item_number|
27
+ on_cmd_header(item_number)
28
+ end
29
+
30
+
31
+ # HACK: only works when one header is there.
32
+ self.connect(SEL_CONFIGURE) do |sender, sel, data|
33
+ update_header_width
34
+ end
35
+ end
36
+
37
+ def create
38
+ super
39
+ recalc
40
+ end
41
+
42
+ # HACK: only works when one header is there.
43
+ def update_header_width
44
+ header.setItemSize(0, width-verticalScrollBar.width)
45
+ recalc
46
+ end
47
+
48
+
49
+ # Called whenever a header is clicked
50
+ def on_cmd_header(header_item_index)
51
+ @data.gui_mutex.synchronize do
52
+ header.setArrowDir(@header_item_index, MAYBE)
53
+ if @header_item_index == header_item_index
54
+ @reversed = !@reversed
55
+ else
56
+ @reversed = true
57
+ end
58
+ @header_item_index = header_item_index
59
+ header.setArrowDir(@header_item_index, @reversed)
60
+ sortItems
61
+ end
62
+ # sort array
63
+ @data.items.sort! do |a, b|
64
+ cmp = a.sortable(header_item_index) <=> b.sortable(header_item_index)
65
+ if @reversed
66
+ -cmp
67
+ else
68
+ cmp
69
+ end
70
+ end
71
+ return 0
72
+ end
73
+
74
+ def sortItems
75
+ @items.each do |item|
76
+ item.update_sort_key
77
+ end
78
+ super
79
+ end
80
+
81
+ # Check if the search order is reversed (happens when clicking on the same header twice)
82
+ def reversed?
83
+ @reversed
84
+ end
85
+
86
+ # Get index of the header that should be used for sorting
87
+ def sort_index
88
+ @header_item_index
89
+ end
90
+
91
+ # Add a new header. The block that you need to specify is used to convert a string of this
92
+ # column into something that can be used for sorting. The yielded parameter item_colum_text
93
+ # is the text of one item of this column.
94
+ def add_header(text, width, &conversion) # :yields: item_column_text
95
+ appendHeader(text, nil, width)
96
+ header.setArrowDir(0, false) if @conversions.empty?
97
+ @conversions.push conversion
98
+ end
99
+
100
+ # Create a new Packet_Item. After the icon, you can specify the text for each of the columns.
101
+ # Here is an example:
102
+ # list.create_item(my_icon, "Martin", "Ankerl", "2005")
103
+ def create_item(icon, *args)
104
+ Packet_Item.new(self, icon, *args)
105
+ end
106
+
107
+ # Add a new Packet_Item to this list.Called from within Packet_Item during Packet_Item#parent=
108
+ def add_item(item)
109
+ @items.add item
110
+ appendItem(item.fox_item)
111
+ item
112
+ end
113
+
114
+ # Remove the given Packet_Item from the list. This is slow, because
115
+ # the item has to be searched with a linear search. To remove all items
116
+ # use #clear.
117
+ def remove_item(item)
118
+ i = 0
119
+ @items.delete item
120
+ fox_item = item.fox_item
121
+ i += 1 while i < numItems && fox_item != getItem(i)
122
+ removeItem(i) if i < numItems
123
+ item
124
+ end
125
+
126
+ def appendItem(*args)
127
+ $fx_icon_item_remove_mutex.synchronize do
128
+ #puts "appendItem"
129
+ super
130
+ end
131
+ end
132
+
133
+ # Before actually deleting, the item has to be marked as deleted to prevent
134
+ # drawing afterwards.
135
+ def removeItem(*args)
136
+ $fx_icon_item_remove_mutex.synchronize do
137
+ #puts "removeitem"
138
+ # at first, mark item as deleted to prevent drawing afterwards
139
+ getItem(args[0]).deleted
140
+ # do the evil delete
141
+ super
142
+ end
143
+ end
144
+
145
+ # Remove all items, but do this within the mutex to be sure everything goes ok.
146
+ def clearItems(*args)
147
+ $fx_icon_item_remove_mutex.synchronize do
148
+ #puts "clearitems"
149
+ super
150
+ end
151
+ end
152
+
153
+ # This may be called when the item is currently beeing deleted.
154
+ # this method works only before or after the delete, therefore
155
+ # the mutex is necessary.
156
+ def getContentWidth(*args)
157
+ $fx_icon_item_remove_mutex.synchronize do
158
+ #puts "contentwidth"
159
+ super
160
+ end
161
+ end
162
+
163
+ # This may be called when the item is currently beeing deleted.
164
+ # this method works only before or after the delete, therefore
165
+ # the mutex is necessary.
166
+ def getContentHeight(*args)
167
+ $fx_icon_item_remove_mutex.synchronize do
168
+ #puts "contentheight"
169
+ super
170
+ end
171
+ end
172
+
173
+ # Removes all items from the list.
174
+ def clear
175
+ @items.each { |item| item.clear }
176
+ @items.clear
177
+ # todo: mutex!?
178
+ clearItems
179
+ end
180
+
181
+ # use in combination with Packet_Item#show
182
+ def dirty_clear
183
+ clearItems
184
+ @items.clear
185
+ end
186
+
187
+ # Get the sort for a given header index. The sort function has been supplied
188
+ # when calling #new. This is used from Packet_Item.
189
+ def sort_function(header_item_index)
190
+ @conversions[header_item_index]
191
+ end
192
+ end
@@ -1,233 +1,238 @@
1
- # Author:: Martin Ankerl (mailto:martin.ankerl@gmail.com)
2
-
3
- # Recursive_Open_Struct provides a convenient interface to a hierarchy of configuration
4
- # parameters. You do not need to define the accessors, they are created automatically
5
- # on demand.
6
- #
7
- # Have a look at this example:
8
- #
9
- # ac = Recursive_Open_Struct.new
10
- # ac.window.name = "SuperDuper"
11
- # ac.app.version = "2.1.3"
12
- # ac.this.is.automatically.created = "blabla"
13
- #
14
- # After you have created all of your configuration parameters, to prevent
15
- # typos when using the parameters, the structure can be closed:
16
- #
17
- # ac.close
18
- #
19
- # After closing,
20
- #
21
- # ac.widnow.name = "UberSuperDuper"
22
- #
23
- # You get the usual NoMethodError, because 'widnow' does not exist.
24
- #
25
- class Recursive_Open_Struct
26
- # Create a new Recursive_Open_Struct.
27
- def initialize
28
- @methods = Hash.new
29
- @open = true
30
- end
31
-
32
- # automatically add parameters
33
- def method_missing(method, *params) # :nodoc:
34
- # setting or getting?
35
- is_setting = !params.empty?
36
-
37
- key = method.id2name
38
- # remove trailing =
39
- key.chop! if is_setting
40
-
41
- # if structure is closed, disable hierarchy creation
42
- super unless @methods.has_key?(key) || @open
43
-
44
- if is_setting
45
- # assigning a new value
46
- if @methods[key].class == Recursive_Open_Struct
47
- raise TypeError, "overwriting previously created hierarchy entry '#{key}' not allowed", caller(1)
48
- end
49
- @methods[key] = *params
50
- else
51
- # no param: create new Recursive_Open_Struct object, if nothing is set.
52
- unless @methods.has_key?(key)
53
- @methods[key] = Recursive_Open_Struct.new
54
- end
55
- end
56
- @methods[key]
57
- end
58
-
59
- # An alternative way to access the value of an attribute
60
- # s = Recursive_Open_Struct.new
61
- # s.name = "Hugo"
62
- # s["name"] # "Hugo"
63
- def [](key)
64
- @methods[key]
65
- end
66
-
67
- # An alternative way to set the value of an attribute
68
- # s = Recursive_Open_Struct.new
69
- # s["name"] = "Hugo"
70
- # s.name # "Hugo"
71
- def []=(key, value)
72
- self.send((key+"=").to_sym, value)
73
- end
74
-
75
- # call-seq:
76
- # attrs() -> an_array
77
- #
78
- # Return a sorted array of attribute names, similar to #methods.
79
- #
80
- # s = Recursive_Open_Struct.new
81
- # s.name = "martinus"
82
- # s.age = 25
83
- # s.attrs # returns ["age", "name"]
84
- def attrs
85
- @methods.keys.sort
86
- end
87
-
88
- # After calling #close, no further modification of the configuration hierarchy
89
- # is allowed. This is not as strict as #freeze, because you are still allowed
90
- # to modify data.
91
- #
92
- # s = Recursive_Open_Struct.new
93
- # s.name = "Hugo"
94
- # s.close
95
- # s.name = "martinus" # does still work
96
- # s.age = 25 # raises NoMethodError
97
- def close
98
- do_set_open_status(false)
99
- end
100
-
101
- # Reopens a Recursive_Open_Struct which was closed with #close earlier.
102
- # After this call, it is possible to modify the structure again.
103
- def re_open
104
- do_set_open_status(true)
105
- end
106
-
107
- # call-seq:
108
- # open?() -> boolean
109
- #
110
- # Return whether the structure is still open or not.
111
- #
112
- # s = Recursive_Open_Struct.new
113
- # s.open? # returns true
114
- # s.close
115
- # s.open? # returns false
116
- def open?
117
- @open
118
- end
119
-
120
- # call-seq:
121
- # each() { |elem| ... }
122
- #
123
- # Iterates through all elements of the Recursive_Open_Struct in alphabetic order.
124
- def each
125
- attrs.each do |attr|
126
- yield @methods[attr]
127
- end
128
- end
129
-
130
- protected
131
-
132
- def do_set_open_status(status)
133
- @methods.each_value do |val|
134
- val.do_set_open_status(status) if val.class == Recursive_Open_Struct
135
- end
136
- @open = status
137
- end
138
- end
139
-
140
- if __FILE__ == $0
141
- require 'test/unit'
142
-
143
- class TestRecursiveOpenStruct < Test::Unit::TestCase
144
- def setup
145
- @s = Recursive_Open_Struct.new
146
- end
147
-
148
- def setAndAssertValue(val)
149
- @s.test = val
150
- assert_equal(val, @s.test)
151
- @s.close
152
- assert_equal(val, @s.test)
153
- @s.test = "asdf"
154
- assert_equal("asdf", @s.test)
155
- end
156
-
157
- def testSetNil
158
- setAndAssertValue(nil)
159
- end
160
-
161
- def testSimple
162
- @s.test = "xx"
163
- @s.close
164
- assert_equal("xx", @s.test)
165
- end
166
-
167
- def testSetFalse
168
- setAndAssertValue(false)
169
- end
170
-
171
- def testSetStr
172
- setAndAssertValue("topfen")
173
- end
174
-
175
- def testSetClass
176
- setAndAssertValue(String)
177
- end
178
-
179
- def testSetTrue
180
- setAndAssertValue(true)
181
- end
182
-
183
- def testSet0
184
- setAndAssertValue(0)
185
- end
186
-
187
- def testRaiseTypeError
188
- @s.a.b = 1
189
- assert_raise(TypeError) do
190
- @s.a = 3
191
- end
192
- end
193
-
194
- def testAttrs
195
- assert_equal([], @s.attrs)
196
- @s.b = "x"
197
- @s.a = "a"
198
- assert_equal(["a", "b"], @s.attrs)
199
- end
200
-
201
- def testRecursive
202
- @s.a.b = 1
203
- @s.a.c = 2
204
- assert_equal(["a"], @s.attrs)
205
- end
206
-
207
- def testStrange
208
- @s.a
209
- assert_equal(["a"], @s.attrs)
210
- assert_equal(Recursive_Open_Struct, @s.a.class)
211
- @s.a.x = "asfd"
212
- assert_equal("asfd", @s.a.x)
213
- end
214
-
215
- def testKlammer
216
- @s.a = "asdf"
217
- assert_equal("asdf", @s["a"])
218
- @s.b_x = "hog"
219
- assert_equal("hog", @s["b_x"])
220
- @s.c.b.a = 1234
221
- assert_equal(1234, @s["c"]["b"]["a"])
222
- end
223
-
224
- def testDeep
225
- @s.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z = false
226
- @s.close
227
- assert_raise(NoMethodError) do
228
- @s.blub = "hellow"
229
- end
230
- assert_equal(false, @s.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z)
231
- end
232
- end
233
- end
1
+ # Author:: Martin Ankerl (mailto:martin.ankerl@gmail.com)
2
+
3
+ # Recursive_Open_Struct provides a convenient interface to a hierarchy of configuration
4
+ # parameters. You do not need to define the accessors, they are created automatically
5
+ # on demand.
6
+ #
7
+ # Have a look at this example:
8
+ #
9
+ # ac = Recursive_Open_Struct.new
10
+ # ac.window.name = "SuperDuper"
11
+ # ac.app.version = "2.1.3"
12
+ # ac.this.is.automatically.created = "blabla"
13
+ #
14
+ # After you have created all of your configuration parameters, to prevent
15
+ # typos when using the parameters, the structure can be closed:
16
+ #
17
+ # ac.close
18
+ #
19
+ # After closing,
20
+ #
21
+ # ac.widnow.name = "UberSuperDuper"
22
+ #
23
+ # You get the usual NoMethodError, because 'widnow' does not exist.
24
+ #
25
+ class Recursive_Open_Struct
26
+ # Create a new Recursive_Open_Struct.
27
+ def initialize
28
+ @methods = Hash.new
29
+ @open = true
30
+ end
31
+
32
+ # automatically add parameters
33
+ def method_missing(method, *params) # :nodoc:
34
+ # setting or getting?
35
+ is_setting = !params.empty?
36
+
37
+ key = method.id2name
38
+ # remove trailing =
39
+ key.chop! if is_setting
40
+
41
+ # if structure is closed, disable hierarchy creation
42
+ #super unless @methods.has_key?(key) || @open
43
+ unless @methods.has_key?(key) || @open
44
+ puts "Calling super with @open = #{@open} and key = #{key}"
45
+ puts "@methods.has_key?(key) returns #{@methods.has_key?(key)}"
46
+ super
47
+ end
48
+
49
+ if is_setting
50
+ # assigning a new value
51
+ if @methods[key].class == Recursive_Open_Struct
52
+ raise TypeError, "overwriting previously created hierarchy entry '#{key}' not allowed", caller(1)
53
+ end
54
+ @methods[key] = *params
55
+ else
56
+ # no param: create new Recursive_Open_Struct object, if nothing is set.
57
+ unless @methods.has_key?(key)
58
+ @methods[key] = Recursive_Open_Struct.new
59
+ end
60
+ end
61
+ @methods[key]
62
+ end
63
+
64
+ # An alternative way to access the value of an attribute
65
+ # s = Recursive_Open_Struct.new
66
+ # s.name = "Hugo"
67
+ # s["name"] # "Hugo"
68
+ def [](key)
69
+ @methods[key]
70
+ end
71
+
72
+ # An alternative way to set the value of an attribute
73
+ # s = Recursive_Open_Struct.new
74
+ # s["name"] = "Hugo"
75
+ # s.name # "Hugo"
76
+ def []=(key, value)
77
+ self.send((key+"=").to_sym, value)
78
+ end
79
+
80
+ # call-seq:
81
+ # attrs() -> an_array
82
+ #
83
+ # Return a sorted array of attribute names, similar to #methods.
84
+ #
85
+ # s = Recursive_Open_Struct.new
86
+ # s.name = "martinus"
87
+ # s.age = 25
88
+ # s.attrs # returns ["age", "name"]
89
+ def attrs
90
+ @methods.keys.sort
91
+ end
92
+
93
+ # After calling #close, no further modification of the configuration hierarchy
94
+ # is allowed. This is not as strict as #freeze, because you are still allowed
95
+ # to modify data.
96
+ #
97
+ # s = Recursive_Open_Struct.new
98
+ # s.name = "Hugo"
99
+ # s.close
100
+ # s.name = "martinus" # does still work
101
+ # s.age = 25 # raises NoMethodError
102
+ def close
103
+ do_set_open_status(false)
104
+ end
105
+
106
+ # Reopens a Recursive_Open_Struct which was closed with #close earlier.
107
+ # After this call, it is possible to modify the structure again.
108
+ def re_open
109
+ do_set_open_status(true)
110
+ end
111
+
112
+ # call-seq:
113
+ # open?() -> boolean
114
+ #
115
+ # Return whether the structure is still open or not.
116
+ #
117
+ # s = Recursive_Open_Struct.new
118
+ # s.open? # returns true
119
+ # s.close
120
+ # s.open? # returns false
121
+ def open?
122
+ @open
123
+ end
124
+
125
+ # call-seq:
126
+ # each() { |elem| ... }
127
+ #
128
+ # Iterates through all elements of the Recursive_Open_Struct in alphabetic order.
129
+ def each
130
+ attrs.each do |attr|
131
+ yield @methods[attr]
132
+ end
133
+ end
134
+
135
+ protected
136
+
137
+ def do_set_open_status(status)
138
+ @methods.each_value do |val|
139
+ val.do_set_open_status(status) if val.class == Recursive_Open_Struct
140
+ end
141
+ @open = status
142
+ end
143
+ end
144
+
145
+ if __FILE__ == $0
146
+ require 'test/unit'
147
+
148
+ class TestRecursiveOpenStruct < Test::Unit::TestCase
149
+ def setup
150
+ @s = Recursive_Open_Struct.new
151
+ end
152
+
153
+ def setAndAssertValue(val)
154
+ @s.test = val
155
+ assert_equal(val, @s.test)
156
+ @s.close
157
+ assert_equal(val, @s.test)
158
+ @s.test = "asdf"
159
+ assert_equal("asdf", @s.test)
160
+ end
161
+
162
+ def testSetNil
163
+ setAndAssertValue(nil)
164
+ end
165
+
166
+ def testSimple
167
+ @s.test = "xx"
168
+ @s.close
169
+ assert_equal("xx", @s.test)
170
+ end
171
+
172
+ def testSetFalse
173
+ setAndAssertValue(false)
174
+ end
175
+
176
+ def testSetStr
177
+ setAndAssertValue("topfen")
178
+ end
179
+
180
+ def testSetClass
181
+ setAndAssertValue(String)
182
+ end
183
+
184
+ def testSetTrue
185
+ setAndAssertValue(true)
186
+ end
187
+
188
+ def testSet0
189
+ setAndAssertValue(0)
190
+ end
191
+
192
+ def testRaiseTypeError
193
+ @s.a.b = 1
194
+ assert_raise(TypeError) do
195
+ @s.a = 3
196
+ end
197
+ end
198
+
199
+ def testAttrs
200
+ assert_equal([], @s.attrs)
201
+ @s.b = "x"
202
+ @s.a = "a"
203
+ assert_equal(["a", "b"], @s.attrs)
204
+ end
205
+
206
+ def testRecursive
207
+ @s.a.b = 1
208
+ @s.a.c = 2
209
+ assert_equal(["a"], @s.attrs)
210
+ end
211
+
212
+ def testStrange
213
+ @s.a
214
+ assert_equal(["a"], @s.attrs)
215
+ assert_equal(Recursive_Open_Struct, @s.a.class)
216
+ @s.a.x = "asfd"
217
+ assert_equal("asfd", @s.a.x)
218
+ end
219
+
220
+ def testKlammer
221
+ @s.a = "asdf"
222
+ assert_equal("asdf", @s["a"])
223
+ @s.b_x = "hog"
224
+ assert_equal("hog", @s["b_x"])
225
+ @s.c.b.a = 1234
226
+ assert_equal(1234, @s["c"]["b"]["a"])
227
+ end
228
+
229
+ def testDeep
230
+ @s.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z = false
231
+ @s.close
232
+ assert_raise(NoMethodError) do
233
+ @s.blub = "hellow"
234
+ end
235
+ assert_equal(false, @s.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z)
236
+ end
237
+ end
238
+ end