foxguib 1.1.0
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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/changelog.txt +128 -0
- data/doc/www/index.html +173 -0
- data/doc/www/upload.rb +9 -0
- data/examples/event_handler.rb +67 -0
- data/examples/event_handlers.rbin +0 -0
- data/examples/guib_testdialog.rb +31 -0
- data/examples/testdialog.rb +29 -0
- data/exe/foxguib +1 -0
- data/foxGUIb-debug.rb +37 -0
- data/foxGUIb.rb +88 -0
- data/foxGUIb_win32.rbw +1 -0
- data/foxguib.gemspec +26 -0
- data/license.txt +49 -0
- data/readme.txt +1 -0
- data/release_notes.txt +68 -0
- data/src/assert.rb +8 -0
- data/src/cfgman.rb +27 -0
- data/src/code-gen/code-generator.rb +171 -0
- data/src/code-gen/property-generators.rb +65 -0
- data/src/code-gen/widget-generator.rb +22 -0
- data/src/convert.rb +60 -0
- data/src/direct_widget_manipulation.rb +343 -0
- data/src/docman.rb +260 -0
- data/src/document.rb +405 -0
- data/src/event_categories.yaml +85 -0
- data/src/event_listener.rb +57 -0
- data/src/events.yaml +77 -0
- data/src/events_docu.yaml +228 -0
- data/src/get_events.rb +64 -0
- data/src/gui/ArrowButton.tga +0 -0
- data/src/gui/BoxMinus.tga +0 -0
- data/src/gui/BoxPlus.tga +0 -0
- data/src/gui/Button.tga +0 -0
- data/src/gui/CheckButton.tga +0 -0
- data/src/gui/ComboBox.tga +0 -0
- data/src/gui/Dial.tga +0 -0
- data/src/gui/GroupBox.tga +0 -0
- data/src/gui/HorizontalFrame.tga +0 -0
- data/src/gui/HorizontalSeparator.tga +0 -0
- data/src/gui/Label.tga +0 -0
- data/src/gui/MDIChild.tga +0 -0
- data/src/gui/MDIClient.tga +0 -0
- data/src/gui/Matrix.tga +0 -0
- data/src/gui/MenuCaption.tga +0 -0
- data/src/gui/MenuCascade.tga +0 -0
- data/src/gui/MenuCheck.tga +0 -0
- data/src/gui/MenuCommand.tga +0 -0
- data/src/gui/MenuPane.tga +0 -0
- data/src/gui/MenuRadio.tga +0 -0
- data/src/gui/MenuSeparator.tga +0 -0
- data/src/gui/MenuTitle.tga +0 -0
- data/src/gui/Menubar.tga +0 -0
- data/src/gui/Packer.tga +0 -0
- data/src/gui/ProgressBar.tga +0 -0
- data/src/gui/RadioButton.tga +0 -0
- data/src/gui/RadioMutex.tga +0 -0
- data/src/gui/ScrollWindow.tga +0 -0
- data/src/gui/Scrollbar.tga +0 -0
- data/src/gui/Shutter.tga +0 -0
- data/src/gui/ShutterItem.tga +0 -0
- data/src/gui/Slider.tga +0 -0
- data/src/gui/Spinner.tga +0 -0
- data/src/gui/Splitter.tga +0 -0
- data/src/gui/StatusBar.tga +0 -0
- data/src/gui/Statusline.tga +0 -0
- data/src/gui/Switcher.tga +0 -0
- data/src/gui/TabBar.tga +0 -0
- data/src/gui/TabBook.tga +0 -0
- data/src/gui/TabItem.tga +0 -0
- data/src/gui/Text.tga +0 -0
- data/src/gui/TextField.tga +0 -0
- data/src/gui/ToggleButton.tga +0 -0
- data/src/gui/Toolbar.tga +0 -0
- data/src/gui/VerticalFrame.tga +0 -0
- data/src/gui/VerticalSeparator.tga +0 -0
- data/src/gui/_guib_event_editor.rb +185 -0
- data/src/gui/_guib_event_editor.rbin +0 -0
- data/src/gui/_guib_genruby.rb +414 -0
- data/src/gui/_guib_genruby.rbin +0 -0
- data/src/gui/_guib_mainwin.rb +574 -0
- data/src/gui/_guib_mainwin.rbin +0 -0
- data/src/gui/event_editor.rb +180 -0
- data/src/gui/genruby.rb +155 -0
- data/src/gui/guib__console.rb +265 -0
- data/src/gui/mainwin.rb +71 -0
- data/src/gui/ruby_console.rb +263 -0
- data/src/gui/svg/Matrix.svg +87 -0
- data/src/gui/svg/MenuCheck.svg +135 -0
- data/src/gui/svg/MenuRadio.svg +130 -0
- data/src/gui/svg/RadioMutex.svg +119 -0
- data/src/gui/textview.rb +101 -0
- data/src/gui/textview.rbin +0 -0
- data/src/minitest.rb +60 -0
- data/src/prop-lists.rb +323 -0
- data/src/prop-types.rb +606 -0
- data/src/properties.rb +119 -0
- data/src/propman.rb +88 -0
- data/src/relink_mechanisms.rb +95 -0
- data/src/serialize.rb +167 -0
- data/src/state_machine.rb +73 -0
- data/src/version.rb +6 -0
- data/src/widget-lists.rb +118 -0
- data/src/widget-selector.rb +85 -0
- data/src/widgettree-controls.rb +183 -0
- data.tar.gz.sig +0 -0
- metadata +236 -0
- metadata.gz.sig +0 -0
data/src/prop-types.rb
ADDED
@@ -0,0 +1,606 @@
|
|
1
|
+
# Copyright (c) 2004-2006 by Henon (meinrad dot recheis at gmail dot com)
|
2
|
+
require "libGUIb16"
|
3
|
+
require "code-gen/property-generators"
|
4
|
+
include Fox
|
5
|
+
include FX
|
6
|
+
|
7
|
+
# for consistency; add dup method to all classes that don't support it (i.e. Nilclass)
|
8
|
+
class Object
|
9
|
+
def dup
|
10
|
+
self
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# seems to be not needed any more
|
15
|
+
# ~ #pasted here to help independent compilation
|
16
|
+
# ~ class HorizontalFrame < Fox::FXHorizontalFrame
|
17
|
+
# ~ def initialize(p, opts=0)
|
18
|
+
# ~ super(p, opts|Fox::LAYOUT_FILL_X|Fox::LAYOUT_FILL_Y, 0,0,0,0,0,0,0,0,0,0)
|
19
|
+
# ~ end
|
20
|
+
# ~ end
|
21
|
+
|
22
|
+
# overwrite dup methods of Hash and Array with a real (recursive) duplication method
|
23
|
+
class Hash
|
24
|
+
def dup
|
25
|
+
h = {}
|
26
|
+
each { |k, v| h[k.dup] = v.dup }
|
27
|
+
h
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Array
|
32
|
+
def dup
|
33
|
+
collect { |e| e.dup }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# abstract property Manipulator base class
|
38
|
+
class SuperProp < HorizontalFrame
|
39
|
+
def initialize p, method, init_data = nil
|
40
|
+
super(p)
|
41
|
+
self.layoutHints = LAYOUT_FILL_X
|
42
|
+
self.frameStyle = 0
|
43
|
+
pad 0, 0, 0, 0
|
44
|
+
# flag for Container to know whether the property should be shown or not
|
45
|
+
@visible = true
|
46
|
+
@method = method
|
47
|
+
@controls = []
|
48
|
+
@enabled = false
|
49
|
+
@wdg = nil
|
50
|
+
@c = CheckButton.new(self) { |c|
|
51
|
+
c.text = ""
|
52
|
+
c.connect(SEL_COMMAND) {
|
53
|
+
set_enabled(@c.state)
|
54
|
+
}
|
55
|
+
}
|
56
|
+
@sep = VerticalSeparator.new(self, SEPARATOR_LINE) { |s| s.pad 0, 0, 0, 0 }
|
57
|
+
init
|
58
|
+
set_enabled false
|
59
|
+
end
|
60
|
+
attr_reader :method
|
61
|
+
attr_reader :enabled
|
62
|
+
# the current widget, needet for event callbacks
|
63
|
+
attr_accessor :wdg, :visible
|
64
|
+
def show
|
65
|
+
super if @visible and parent.shown?
|
66
|
+
end
|
67
|
+
|
68
|
+
# to be overridden by subclasses
|
69
|
+
def init
|
70
|
+
method_label
|
71
|
+
end
|
72
|
+
|
73
|
+
def method_label
|
74
|
+
l = Label.new(self) { |l|
|
75
|
+
l.text = @method
|
76
|
+
@controls << l
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def method_s
|
81
|
+
method.gsub(/=$/, " = ")
|
82
|
+
end
|
83
|
+
|
84
|
+
# a text manipulator for textual properties
|
85
|
+
def text_input
|
86
|
+
@tf = TextField.new(self) { |tf|
|
87
|
+
tf.layoutHints = LAYOUT_RIGHT
|
88
|
+
tf.numColumns = 5
|
89
|
+
tf.disable
|
90
|
+
tf.connect(SEL_COMMAND) {
|
91
|
+
@wdg.update_wdg self if @wdg
|
92
|
+
}
|
93
|
+
tf.connect(SEL_CHANGED) {
|
94
|
+
@wdg.update_wdg self
|
95
|
+
}
|
96
|
+
@controls << tf
|
97
|
+
}
|
98
|
+
@tf
|
99
|
+
end
|
100
|
+
|
101
|
+
# a little texteditor dialog
|
102
|
+
def texteditor p
|
103
|
+
@texted = DialogBox.new p
|
104
|
+
@texted.resize(200, 150)
|
105
|
+
VerticalFrame.new(@texted) { |v|
|
106
|
+
v.pad 4, 4, 4, 4
|
107
|
+
VerticalFrame.new(v) { |tfr|
|
108
|
+
tfr.frameStyle = FRAME_SUNKEN
|
109
|
+
tfr.pad 0, 0, 0, 0
|
110
|
+
@text = Text.new(tfr) { |t|
|
111
|
+
t.text = @tf.text
|
112
|
+
}
|
113
|
+
}
|
114
|
+
HorizontalFrame.new(v) { |h|
|
115
|
+
Button.new(h, LAYOUT_RIGHT) { |b|
|
116
|
+
b.text = "Apply"
|
117
|
+
b.connect(SEL_COMMAND) {
|
118
|
+
@tf.text = @text.text
|
119
|
+
@wdg.update_wdg self if @wdg
|
120
|
+
@texted.destroy
|
121
|
+
}
|
122
|
+
}
|
123
|
+
Button.new(h, LAYOUT_RIGHT) { |b|
|
124
|
+
b.text = "Cancel"
|
125
|
+
b.connect(SEL_COMMAND) {
|
126
|
+
@texted.destroy
|
127
|
+
}
|
128
|
+
}
|
129
|
+
}
|
130
|
+
}
|
131
|
+
@texted.create
|
132
|
+
@texted.show(PLACEMENT_CURSOR)
|
133
|
+
end
|
134
|
+
|
135
|
+
# gets the data from the property widget
|
136
|
+
def get_data
|
137
|
+
if @tf
|
138
|
+
begin
|
139
|
+
data = deserialize(@tf.text)
|
140
|
+
@tf.textColor = FXRGB(0, 0, 0)
|
141
|
+
data
|
142
|
+
rescue Exception
|
143
|
+
@tf.textColor = FXRGB(255, 0, 0)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# sets the data value of the property widget
|
149
|
+
def set_data data
|
150
|
+
if @tf
|
151
|
+
@tf.textColor = FXRGB(0, 0, 0)
|
152
|
+
@tf.text = serialize(data)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# resets the widget and the prop-widget to the default state
|
157
|
+
def reset_default
|
158
|
+
@wdg.reset_default self if @wdg
|
159
|
+
end
|
160
|
+
|
161
|
+
# enables or disables the PropWidget
|
162
|
+
def set_enabled bool
|
163
|
+
reset_default unless bool
|
164
|
+
@enabled = bool
|
165
|
+
@c.state = bool
|
166
|
+
@controls.each { |w|
|
167
|
+
w.enabled = bool
|
168
|
+
change_text_color(w, bool)
|
169
|
+
}
|
170
|
+
end
|
171
|
+
|
172
|
+
# changes the text color of the prop-widget, so that it appears disabled or enabled
|
173
|
+
def change_text_color w, t
|
174
|
+
return unless w.respond_to? :textColor=
|
175
|
+
w.textColor = if t
|
176
|
+
FXRGB(0, 0, 0)
|
177
|
+
else
|
178
|
+
FXRGB(100, 100, 100)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def serialize data
|
183
|
+
data
|
184
|
+
end
|
185
|
+
|
186
|
+
def deserialize data
|
187
|
+
data
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
class NameProp < SuperProp
|
192
|
+
def initialize p
|
193
|
+
super(p, "Name:")
|
194
|
+
@c.hide
|
195
|
+
@sep.hide
|
196
|
+
method_label
|
197
|
+
text_input
|
198
|
+
@tf.enable
|
199
|
+
@tf.connect(SEL_CHANGED) {
|
200
|
+
@tf.textColor = FXRGB(255, 0, 0)
|
201
|
+
}
|
202
|
+
@tf.numColumns = 15
|
203
|
+
@tf.connect(SEL_COMMAND) {
|
204
|
+
begin
|
205
|
+
@tf.textColor = FXRGB(0, 0, 0) if @wdg.userData.manager.rename_wdg @wdg, @tf.text
|
206
|
+
rescue Exception
|
207
|
+
puts "oops, trying to rename a deleted widget!"
|
208
|
+
end
|
209
|
+
}
|
210
|
+
end
|
211
|
+
|
212
|
+
def init
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
class StringProp < SuperProp
|
217
|
+
include StringPropCodeGen
|
218
|
+
def init
|
219
|
+
super
|
220
|
+
Button.new(self) { |b|
|
221
|
+
b.text = "..."
|
222
|
+
b.layoutHints = LAYOUT_RIGHT
|
223
|
+
b.connect(SEL_COMMAND) {
|
224
|
+
texteditor self
|
225
|
+
}
|
226
|
+
@controls << b
|
227
|
+
}
|
228
|
+
text_input
|
229
|
+
@tf.numColumns = 15
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
class IntProp < SuperProp
|
234
|
+
include IntPropCodeGen
|
235
|
+
def init
|
236
|
+
method_label
|
237
|
+
text_input
|
238
|
+
end
|
239
|
+
|
240
|
+
def deserialize data
|
241
|
+
data.to_i
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
class BoolProp < SuperProp
|
246
|
+
include BoolPropCodeGen
|
247
|
+
def init
|
248
|
+
method_label
|
249
|
+
@ck = CheckButton.new(self) { |c|
|
250
|
+
# ~ c.checkState=@datum
|
251
|
+
c.text = ""
|
252
|
+
c.layoutHints = LAYOUT_RIGHT
|
253
|
+
c.disable
|
254
|
+
c.connect(SEL_COMMAND) {
|
255
|
+
@wdg.update_wdg self if @wdg
|
256
|
+
}
|
257
|
+
}
|
258
|
+
@controls << @ck
|
259
|
+
end
|
260
|
+
|
261
|
+
def get_data
|
262
|
+
@ck.state
|
263
|
+
end
|
264
|
+
|
265
|
+
def set_data data
|
266
|
+
@ck.state = data
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
class ColorProp < SuperProp
|
271
|
+
include ColorPropCodeGen
|
272
|
+
def init
|
273
|
+
method_label
|
274
|
+
VerticalFrame.new(self) { |pa|
|
275
|
+
pa.pad 0, 0, 0, 0
|
276
|
+
pa.frameStyle = FRAME_LINE
|
277
|
+
pa.layoutHints = LAYOUT_RIGHT
|
278
|
+
@b = Button.new(pa) { |b|
|
279
|
+
b.text = " C "
|
280
|
+
b.frameStyle = FRAME_NONE
|
281
|
+
b.connect(SEL_COMMAND) {
|
282
|
+
$color_dlg.rgba = deserialize(@tf.text)
|
283
|
+
if $color_dlg.execute == 1
|
284
|
+
set_data $color_dlg.getRGBA
|
285
|
+
@wdg.update_wdg self if @wdg
|
286
|
+
end
|
287
|
+
}
|
288
|
+
@controls << b
|
289
|
+
}
|
290
|
+
}
|
291
|
+
text_input
|
292
|
+
@tf.numColumns = 15
|
293
|
+
end
|
294
|
+
|
295
|
+
def get_data
|
296
|
+
color = super
|
297
|
+
@b.backColor = color if color
|
298
|
+
color
|
299
|
+
end
|
300
|
+
|
301
|
+
def set_data(color)
|
302
|
+
super
|
303
|
+
@b.backColor = color
|
304
|
+
end
|
305
|
+
|
306
|
+
def serialize data
|
307
|
+
Color.new.from_FXColor(data).to_s
|
308
|
+
end
|
309
|
+
|
310
|
+
def deserialize data
|
311
|
+
Color.new.from_s(data).to_FXColor
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
class FontProp < SuperProp
|
316
|
+
include FontPropCodeGen
|
317
|
+
def init
|
318
|
+
method_label
|
319
|
+
VerticalFrame.new(self) { |pa|
|
320
|
+
pa.pad 0, 0, 0, 0
|
321
|
+
pa.frameStyle = FRAME_LINE
|
322
|
+
pa.layoutHints = LAYOUT_RIGHT
|
323
|
+
@b = Button.new(pa) { |b|
|
324
|
+
b.text = " F "
|
325
|
+
b.frameStyle = FRAME_NONE
|
326
|
+
b.connect(SEL_COMMAND) {
|
327
|
+
fd = Fox::FXFontDesc.new
|
328
|
+
$font_dlg.fontSelection = fd.from_s(@tf.text)
|
329
|
+
if $font_dlg.execute == 1
|
330
|
+
fd = $font_dlg.fontSelection
|
331
|
+
font = Font.new
|
332
|
+
font.fd = fd
|
333
|
+
@tf.text = fd.to_s
|
334
|
+
@wdg.update_wdg self if @wdg
|
335
|
+
end
|
336
|
+
}
|
337
|
+
@controls << b
|
338
|
+
}
|
339
|
+
}
|
340
|
+
text_input
|
341
|
+
@tf.numColumns = 15
|
342
|
+
end
|
343
|
+
|
344
|
+
def serialize data
|
345
|
+
data.fontDesc.to_s
|
346
|
+
end
|
347
|
+
|
348
|
+
def deserialize data
|
349
|
+
Font.new.from_s(data).to_FXFont
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
class ConstProp < SuperProp
|
354
|
+
include ConstPropCodeGen
|
355
|
+
def initialize p, method, array
|
356
|
+
@array = array
|
357
|
+
super
|
358
|
+
end
|
359
|
+
|
360
|
+
def init
|
361
|
+
method_label
|
362
|
+
dropdown
|
363
|
+
end
|
364
|
+
|
365
|
+
def dropdown
|
366
|
+
@b = MenuButton.new(self) { |b|
|
367
|
+
@controls << b
|
368
|
+
b.text = ""
|
369
|
+
b.layoutHints = LAYOUT_RIGHT
|
370
|
+
}
|
371
|
+
@checklist = []
|
372
|
+
Popup.new(@b) { |popup|
|
373
|
+
@b.menu = popup
|
374
|
+
popup.connect(SEL_MAP) {
|
375
|
+
state = @wdg.send(@method.chop) if @wdg
|
376
|
+
set_data state
|
377
|
+
}
|
378
|
+
VerticalFrame.new(popup) { |v|
|
379
|
+
@array.each { |const|
|
380
|
+
CheckButton.new(v) { |c|
|
381
|
+
@checklist << c
|
382
|
+
c.text = const
|
383
|
+
c.layoutHints = LAYOUT_LEFT
|
384
|
+
c.connect(SEL_COMMAND) {
|
385
|
+
@wdg.update_wdg self if @wdg
|
386
|
+
}
|
387
|
+
}
|
388
|
+
}
|
389
|
+
}
|
390
|
+
HorizontalSeparator.new popup
|
391
|
+
MenuCommand.new(popup) { |ok| ok.text = "OK" }
|
392
|
+
HorizontalSeparator.new popup
|
393
|
+
Button.new(popup) { |checkall|
|
394
|
+
checkall.text = "check all"
|
395
|
+
checkall.frameStyle = FRAME_NONE
|
396
|
+
checkall.connect(SEL_COMMAND) { checkall true }
|
397
|
+
}
|
398
|
+
Button.new(popup) { |uncheckall|
|
399
|
+
uncheckall.text = "uncheck all"
|
400
|
+
uncheckall.frameStyle = FRAME_NONE
|
401
|
+
uncheckall.connect(SEL_COMMAND) { checkall false }
|
402
|
+
}
|
403
|
+
}
|
404
|
+
end
|
405
|
+
|
406
|
+
def get_data
|
407
|
+
a = []
|
408
|
+
@checklist.each { |c|
|
409
|
+
a << "Fox::" + c.text if c.state
|
410
|
+
}
|
411
|
+
state = eval(a.join("|"))
|
412
|
+
state || 0
|
413
|
+
end
|
414
|
+
|
415
|
+
def set_data(state)
|
416
|
+
return unless @wdg
|
417
|
+
@wdg.send(@method, 0)
|
418
|
+
sticky = @wdg.send(@method.chop)
|
419
|
+
@wdg.send(@method, eval(@array.join("|")))
|
420
|
+
unmod = @wdg.send(@method.chop)
|
421
|
+
@wdg.send(@method, state)
|
422
|
+
@checklist.each { |child|
|
423
|
+
const = eval(child.text)
|
424
|
+
child.check = ((state & const == const) ? true : false)
|
425
|
+
child.disable if sticky & const == const
|
426
|
+
child.disable unless unmod & const == const
|
427
|
+
}
|
428
|
+
end
|
429
|
+
|
430
|
+
def checkall b
|
431
|
+
a = []
|
432
|
+
@checklist.each { |child|
|
433
|
+
child.check = b if child.enabled
|
434
|
+
a << child.text
|
435
|
+
}
|
436
|
+
state = eval(a.join("|"))
|
437
|
+
@wdg.update_wdg self if @wdg
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
class IconProp < SuperProp
|
442
|
+
include IconPropCodeGen
|
443
|
+
def init
|
444
|
+
super
|
445
|
+
Button.new(self) { |b|
|
446
|
+
b.text = "..."
|
447
|
+
b.layoutHints = LAYOUT_RIGHT
|
448
|
+
b.connect(SEL_COMMAND) {
|
449
|
+
dlg = IconDialog.new self
|
450
|
+
filename = dlg.start
|
451
|
+
set_data deserialize(filename)
|
452
|
+
@wdg.update_wdg self if @wdg
|
453
|
+
}
|
454
|
+
@controls << b
|
455
|
+
}
|
456
|
+
text_input
|
457
|
+
@tf.numColumns = 15
|
458
|
+
end
|
459
|
+
# ~ def deserialize data
|
460
|
+
# ~ Icon.new(data).img
|
461
|
+
# ~ fail unless File.exist?( data)
|
462
|
+
# ~ return data
|
463
|
+
# ~ end
|
464
|
+
end
|
465
|
+
|
466
|
+
class RangeProp < SuperProp
|
467
|
+
include RangePropCodeGen
|
468
|
+
def init
|
469
|
+
super
|
470
|
+
text_input
|
471
|
+
@tf.numColumns = 15
|
472
|
+
@tf.connect(SEL_CHANGED) {
|
473
|
+
update
|
474
|
+
}
|
475
|
+
@tf.connect(SEL_COMMAND) {
|
476
|
+
update
|
477
|
+
}
|
478
|
+
end
|
479
|
+
|
480
|
+
def update
|
481
|
+
range = deserialize(@tf.text)
|
482
|
+
@wdg.update_wdg self if @wdg
|
483
|
+
@tf.textColor = FXRGB(0, 0, 0)
|
484
|
+
rescue Exception
|
485
|
+
@tf.textColor = FXRGB(255, 0, 0)
|
486
|
+
puts $!
|
487
|
+
puts $!.backtrace
|
488
|
+
end
|
489
|
+
|
490
|
+
def deserialize data
|
491
|
+
begin
|
492
|
+
range = eval(data)
|
493
|
+
fail unless range.is_a? Range
|
494
|
+
fail unless range.first.is_a? Numeric
|
495
|
+
fail unless range.last.is_a? Numeric
|
496
|
+
rescue Exception
|
497
|
+
range = 0..0
|
498
|
+
puts $!
|
499
|
+
puts $!.backtrace
|
500
|
+
end
|
501
|
+
range
|
502
|
+
end
|
503
|
+
|
504
|
+
def serialize data
|
505
|
+
data.inspect
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
# unit testing code
|
510
|
+
if __FILE__ == $0
|
511
|
+
require "minitest"
|
512
|
+
test("Range Property Manipulator") {
|
513
|
+
app = FX::App.new
|
514
|
+
w = FX::MainWindow.new app
|
515
|
+
s = FX::Spinner.new w
|
516
|
+
rangeInst = RangeProp.new(s, "range")
|
517
|
+
# testing deserialize
|
518
|
+
assert_equal 1..10, rangeInst.deserialize("1..10")
|
519
|
+
assert_raises(RuntimeError) {
|
520
|
+
rangeInst.deserialize("0")
|
521
|
+
}
|
522
|
+
assert_equal "-37..100", rangeInst.serialize(-37..100)
|
523
|
+
aRange = 1..2
|
524
|
+
rangeInst.set_data(aRange)
|
525
|
+
assert_equal aRange, rangeInst.get_data
|
526
|
+
true
|
527
|
+
}
|
528
|
+
|
529
|
+
test("Color Property Manipulator") {
|
530
|
+
app = FX::App.new
|
531
|
+
w = FX::MainWindow.new app
|
532
|
+
v = FX::VerticalFrame.new w
|
533
|
+
colorInst = ColorProp.new(v, "color")
|
534
|
+
color_data = "255,255,255,255"
|
535
|
+
# trying to get data before setting
|
536
|
+
data = colorInst.get_data
|
537
|
+
assert_equal 0, data
|
538
|
+
# testing deserialize and serialize
|
539
|
+
ser_data = colorInst.serialize(deser_data = colorInst.deserialize(color_data))
|
540
|
+
assert_equal color_data, ser_data
|
541
|
+
# testing get and set data
|
542
|
+
colorInst.set_data(colorInst.deserialize(color_data))
|
543
|
+
ser_data = colorInst.serialize(data = colorInst.get_data)
|
544
|
+
assert_equal color_data, ser_data
|
545
|
+
true
|
546
|
+
}
|
547
|
+
|
548
|
+
test("Font Property Manipulator") {
|
549
|
+
app = FX::App.new
|
550
|
+
w = FX::MainWindow.new app
|
551
|
+
t = FX::Text.new w
|
552
|
+
fontInst = FontProp.new(t, "font")
|
553
|
+
font_data = "Tahoma"
|
554
|
+
# testing serialize and deserialize
|
555
|
+
ser_data = fontInst.serialize(deser_data = fontInst.deserialize(font_data))
|
556
|
+
assert_equal Font.new.from_s(font_data).to_s, ser_data
|
557
|
+
true
|
558
|
+
}
|
559
|
+
|
560
|
+
test("Boolean Property Manipulator") {
|
561
|
+
app = FX::App.new
|
562
|
+
w = FX::MainWindow.new app
|
563
|
+
t = FX::Text.new w
|
564
|
+
boolInst = BoolProp.new(t, "bool")
|
565
|
+
bool_data = true
|
566
|
+
# getting data before setting it
|
567
|
+
assert_equal false, boolInst.get_data
|
568
|
+
# getting and setting data
|
569
|
+
boolInst.set_data bool_data
|
570
|
+
assert_equal bool_data, boolInst.get_data
|
571
|
+
true
|
572
|
+
}
|
573
|
+
|
574
|
+
test("Super Property Manipulator") {
|
575
|
+
app = FX::App.new
|
576
|
+
w = FX::MainWindow.new app
|
577
|
+
t = FX::Text.new w
|
578
|
+
superInst = SuperProp.new(t, "super")
|
579
|
+
data = "string"
|
580
|
+
# testing serialize and deserialize
|
581
|
+
ser_data = superInst.serialize superInst.deserialize(data)
|
582
|
+
assert_equal data, ser_data
|
583
|
+
# getting data before setting it
|
584
|
+
assert_nil superInst.get_data
|
585
|
+
assert_equal false, superInst.enabled
|
586
|
+
# enabling the property and testing get data before setting data
|
587
|
+
superInst.set_enabled true
|
588
|
+
assert_nil superInst.get_data
|
589
|
+
# setting and getting data
|
590
|
+
superInst.text_input
|
591
|
+
type_array = [
|
592
|
+
5,
|
593
|
+
"string",
|
594
|
+
true,
|
595
|
+
ColorProp.new(t, "color").deserialize("255,255,255,255"),
|
596
|
+
FontProp.new(t, "font").deserialize("Tahoma"),
|
597
|
+
1..5
|
598
|
+
]
|
599
|
+
type_array.each { |var|
|
600
|
+
superInst.set_data var
|
601
|
+
assert_equal var.to_s, superInst.get_data
|
602
|
+
}
|
603
|
+
true
|
604
|
+
}
|
605
|
+
|
606
|
+
end
|
data/src/properties.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
# Copyright (c) 2004-2006 by Henon (meinrad dot recheis at gmail dot com)
|
2
|
+
|
3
|
+
# extension module for Fox::FXWindow that is only mixed in at foxGUIb runtime.
|
4
|
+
module Properties
|
5
|
+
def create_defaults
|
6
|
+
# @defaults: { method_string=> default-value }
|
7
|
+
@defaults = {}
|
8
|
+
@wdgprops ||= []
|
9
|
+
for proplist in [$color_props, $general_props, $const_props, @wdgprops]
|
10
|
+
proplist.each { |method, type, array|
|
11
|
+
next unless respond_to? method
|
12
|
+
@defaults[method] = send(method.chop)
|
13
|
+
@defaults[method] = 1 if method.chop == "numColumns"
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
# list of property objects
|
18
|
+
attr_reader :defaults
|
19
|
+
|
20
|
+
# load the properties of the widget into the property manager
|
21
|
+
def update_properties
|
22
|
+
PropMan.instance.nameProp.wdg = self
|
23
|
+
PropMan.instance.nameProp.set_data userData.treeitem.to_s
|
24
|
+
PropMan.instance.type_lbl.text = self.class.to_s
|
25
|
+
PropMan.instance.props.each { |m, manip|
|
26
|
+
if @defaults.keys.member? m
|
27
|
+
|
28
|
+
next unless respond_to?(m.chop)
|
29
|
+
value = send(m.chop)
|
30
|
+
manip.wdg = self
|
31
|
+
|
32
|
+
if value.to_s == @defaults[m].to_s
|
33
|
+
manip.set_enabled false
|
34
|
+
value = @defaults[m]
|
35
|
+
else
|
36
|
+
manip.set_enabled true
|
37
|
+
end
|
38
|
+
|
39
|
+
manip.set_data value
|
40
|
+
manip.visible = true
|
41
|
+
manip.show
|
42
|
+
else
|
43
|
+
manip.visible = false
|
44
|
+
manip.hide
|
45
|
+
manip.recalc
|
46
|
+
end
|
47
|
+
}
|
48
|
+
EventEditor.instance.set_widget self
|
49
|
+
end
|
50
|
+
|
51
|
+
def reset_default prop_manip
|
52
|
+
value = @defaults[prop_manip.method]
|
53
|
+
prop_manip.set_data(value)
|
54
|
+
|
55
|
+
update_wdg prop_manip
|
56
|
+
end
|
57
|
+
|
58
|
+
# a property has been changed. update widget
|
59
|
+
def update_wdg prop_manip
|
60
|
+
value = prop_manip.get_data
|
61
|
+
m = prop_manip.method
|
62
|
+
begin
|
63
|
+
send(m, value)
|
64
|
+
rescue Exception
|
65
|
+
puts "error setting property: #{m}, value: #{value}"
|
66
|
+
puts $!
|
67
|
+
puts $!.backtrace
|
68
|
+
end
|
69
|
+
recalc
|
70
|
+
shell.forceRefresh
|
71
|
+
set_dirty
|
72
|
+
end
|
73
|
+
|
74
|
+
def set_name name
|
75
|
+
PropMan.instance.nameProp.set_data name
|
76
|
+
PropMan.instance.nameProp.wdg = self
|
77
|
+
end
|
78
|
+
|
79
|
+
def set_dirty
|
80
|
+
userData.manager.set_dirty
|
81
|
+
end
|
82
|
+
|
83
|
+
# serializes all properties into this hash
|
84
|
+
def serialize hash
|
85
|
+
@defaults.each { |m, default|
|
86
|
+
manip = PropMan.instance.props[m]
|
87
|
+
value = send(m.chop)
|
88
|
+
hash[m] = manip.serialize(value)
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
# loads all properties from the hash
|
93
|
+
def deserialize hash
|
94
|
+
hash.each { |method, value|
|
95
|
+
manip = PropMan.instance.props[method]
|
96
|
+
unless manip
|
97
|
+
puts "no property object for #{method}!!"
|
98
|
+
next
|
99
|
+
end
|
100
|
+
dvalue = manip.deserialize(value)
|
101
|
+
# ~ if ["icon=", "altIcon="].member?( method)
|
102
|
+
# ~ PropMan.instance.init_icons self
|
103
|
+
# ~ PropMan.instance.icons[self][method]=value
|
104
|
+
# ~ end
|
105
|
+
begin
|
106
|
+
send(method, dvalue) if respond_to? method
|
107
|
+
rescue Exception
|
108
|
+
puts "#{method}: invalid value, #{$!}"
|
109
|
+
puts $!.backtrace
|
110
|
+
end
|
111
|
+
recalc
|
112
|
+
shell.forceRefresh
|
113
|
+
}
|
114
|
+
end
|
115
|
+
end # module Properties
|
116
|
+
|
117
|
+
class Fox::FXWindow
|
118
|
+
include Properties
|
119
|
+
end
|