foxguib 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|