fxri 0.3.3 → 0.3.4

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