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/document.rb
ADDED
@@ -0,0 +1,405 @@
|
|
1
|
+
# Copyright (c) 2004-2006 by Henon (meinrad dot recheis at gmail dot com)
|
2
|
+
|
3
|
+
require "assert"
|
4
|
+
require "code-gen/code-generator"
|
5
|
+
require "serialize"
|
6
|
+
require "widgettree-controls"
|
7
|
+
require "relink_mechanisms"
|
8
|
+
|
9
|
+
MARKED_COLOR = Fox::FXRGB(1, 150, 250)
|
10
|
+
|
11
|
+
class UserData # TODO: to be ELIMINATED
|
12
|
+
def initialize treeitem, manager
|
13
|
+
raise "treeitem is nil" unless treeitem
|
14
|
+
@treeitem = treeitem
|
15
|
+
@manager = manager
|
16
|
+
end
|
17
|
+
attr_accessor :treeitem, :manager
|
18
|
+
end
|
19
|
+
|
20
|
+
class Document
|
21
|
+
include CodeGenerator
|
22
|
+
include Serialize
|
23
|
+
include WidgettreeControls
|
24
|
+
def initialize etype
|
25
|
+
@switcherIndex = 0
|
26
|
+
create_dlg # @ WidgettreeControls.rb
|
27
|
+
@w = {}
|
28
|
+
@names = {}
|
29
|
+
@implicit_children = true
|
30
|
+
name = nil
|
31
|
+
@type = etype
|
32
|
+
init(etype) if etype
|
33
|
+
@gendlg_state = {}
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_accessor :doclist_item
|
37
|
+
attr_accessor :name
|
38
|
+
attr_accessor :topwin, :type,
|
39
|
+
:dlg,
|
40
|
+
:marked,
|
41
|
+
:marked_wcolor,
|
42
|
+
:fxtree,
|
43
|
+
:switcherIndex, # the switcher-index of the treelist for this Document
|
44
|
+
:gendlg_state
|
45
|
+
# ~ attr_reader :w # breaks codegen
|
46
|
+
|
47
|
+
def init etype
|
48
|
+
@w[@root.to_s] = MAINWIN.topwin
|
49
|
+
classname = name = ""
|
50
|
+
if etype == "mainwin"
|
51
|
+
classname = "#{DialogBox}"
|
52
|
+
name = "mainWindow"
|
53
|
+
elsif etype == "dlg"
|
54
|
+
classname = "#{DialogBox}"
|
55
|
+
name = "dialogBox"
|
56
|
+
elsif etype == "popup"
|
57
|
+
# TODO:
|
58
|
+
end
|
59
|
+
if name
|
60
|
+
@topwin = add_widget classname, nil, @root
|
61
|
+
rename_wdg(@topwin, name)
|
62
|
+
@topwin.resize(500, 400)
|
63
|
+
@topwin.show(PLACEMENT_SCREEN)
|
64
|
+
end
|
65
|
+
if etype == "mainwin"
|
66
|
+
def @topwin.class
|
67
|
+
MainWindow
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def load filename
|
73
|
+
data = load_from_file(filename)
|
74
|
+
@name = filename
|
75
|
+
@names = data[:names] # to avoid inconsistencies while loading the widgettree
|
76
|
+
@type = data[:type]
|
77
|
+
@gendlg_state = data[:gendlg_state]
|
78
|
+
init @type
|
79
|
+
rename_wdg(@topwin, data[:hierarchy].first[:name])
|
80
|
+
@topwin.set_name(data[:hierarchy].first[:name])
|
81
|
+
@topwin.deserialize(data[:hierarchy].first[ :prop])
|
82
|
+
load_widgettree data[:hierarchy].first[:sub], "inside", @topwin
|
83
|
+
@names = data[:names] # to reset to the saved state
|
84
|
+
@topwin.layout
|
85
|
+
@fxtree.currentItem = @topwin.userData.treeitem
|
86
|
+
@topwin.update_properties
|
87
|
+
unmark
|
88
|
+
mark @topwin
|
89
|
+
end
|
90
|
+
|
91
|
+
# recursive loading function of a subtree. used by "load" and "paste".
|
92
|
+
# hashes: an array of hashes representing widgets that shall be created where(=inside/after/before the relativeWidget)
|
93
|
+
def load_widgettree hashes, where, relativeWdg
|
94
|
+
tmp = @implicit_children
|
95
|
+
@implicit_children = false
|
96
|
+
hashes.each { |hash|
|
97
|
+
# hash[:name]=get_name(hash[:name]) if @w.has_key?( hash[:name])
|
98
|
+
wdg = add_widget(hash[:cl], where, relativeWdg.userData.treeitem)
|
99
|
+
unless wdg
|
100
|
+
puts "add_widget returned nil for <#{hash[:name]}>!"
|
101
|
+
next
|
102
|
+
end
|
103
|
+
wdg.deserialize hash[:prop]
|
104
|
+
wdg.behaviour = hash[:behaviour] if hash[:behaviour]
|
105
|
+
load_widgettree hash[:sub], "inside", wdg
|
106
|
+
rename_wdg(wdg, hash[:name])
|
107
|
+
}
|
108
|
+
@implicit_children = tmp
|
109
|
+
end
|
110
|
+
|
111
|
+
def save filename
|
112
|
+
unmark
|
113
|
+
data = {
|
114
|
+
type: @type,
|
115
|
+
names: @names,
|
116
|
+
hierarchy: [],
|
117
|
+
gendlg_state: @gendlg_state
|
118
|
+
}
|
119
|
+
start_node = @root.below
|
120
|
+
traverse(@topwin, data[:hierarchy])
|
121
|
+
if filename
|
122
|
+
$fxapp.beginWaitCursor
|
123
|
+
save_to_file filename, data
|
124
|
+
$fxapp.endWaitCursor
|
125
|
+
else
|
126
|
+
puts "no filename given. didn't save."
|
127
|
+
end
|
128
|
+
data
|
129
|
+
end
|
130
|
+
|
131
|
+
def traverse(widget, nodelist)
|
132
|
+
return unless widget
|
133
|
+
hash = {}
|
134
|
+
subnodes = []
|
135
|
+
hash[:sub] = subnodes
|
136
|
+
nodelist << hash
|
137
|
+
# wdg=@w[treenode.to_s]
|
138
|
+
hash[:name] = widget.wdg_name # wdg.userData.treeitem.text
|
139
|
+
hash[:cl] = widget.class.to_s.sub("FX::", "")
|
140
|
+
prophash = {}
|
141
|
+
hash[:prop] = prophash
|
142
|
+
widget.serialize prophash
|
143
|
+
hash[:behaviour] = widget.behaviour
|
144
|
+
widget.each_child { |child|
|
145
|
+
traverse(child, subnodes) if child.respond_to? :hilighted=
|
146
|
+
}
|
147
|
+
traverse(widget.menu, subnodes) if widget.respond_to? :menu
|
148
|
+
end
|
149
|
+
|
150
|
+
def add_widget classname, opts = "after", currentitem = @fxtree.currentItem
|
151
|
+
assert(currentitem)
|
152
|
+
wdg = parent = parentitem = nil
|
153
|
+
if currentitem.parent == @root and opts != "inside"
|
154
|
+
# linking as subnode
|
155
|
+
parent = @w[currentitem.to_s]
|
156
|
+
parentitem = currentitem
|
157
|
+
opts = "inside"
|
158
|
+
elsif opts == "after" or opts == "before"
|
159
|
+
parent = @w[currentitem.parent.to_s]
|
160
|
+
parentitem = currentitem.parent
|
161
|
+
siblingitem = currentitem
|
162
|
+
elsif opts == "inside"
|
163
|
+
parent = @w[currentitem.to_s]
|
164
|
+
parentitem = currentitem
|
165
|
+
elsif currentitem == @root
|
166
|
+
parent = @w[currentitem.to_s]
|
167
|
+
parentitem = currentitem
|
168
|
+
end
|
169
|
+
begin
|
170
|
+
wdg = create_wdg(classname, parent)
|
171
|
+
raise "error creating wdg" unless wdg
|
172
|
+
wdg.wdg_name = name = add_reference(classname.downcase, wdg)
|
173
|
+
currentitem = @fxtree.appendItem parentitem, name
|
174
|
+
wdg.userData = UserData.new(currentitem, self)
|
175
|
+
@fxtree.currentItem = currentitem
|
176
|
+
if opts == "after" or opts == "before"
|
177
|
+
currentitem = relink_wdg(currentitem, opts, siblingitem).userData.treeitem
|
178
|
+
end
|
179
|
+
create_implicit_children classname
|
180
|
+
expand_parents currentitem
|
181
|
+
@fxtree.forceRefresh
|
182
|
+
set_dirty
|
183
|
+
wdg.update_properties
|
184
|
+
rescue
|
185
|
+
puts $!
|
186
|
+
puts $!.backtrace.join("\n")
|
187
|
+
end
|
188
|
+
wdg
|
189
|
+
end
|
190
|
+
|
191
|
+
def create_wdg classname, p
|
192
|
+
wdg = nil
|
193
|
+
assert(p)
|
194
|
+
check_integrity classname, p
|
195
|
+
wdg = eval(classname).new p
|
196
|
+
m = wdg.method(:backColor)
|
197
|
+
# cache real backColor so that marked widgets don't get confused with their markedColor and real backColor
|
198
|
+
def wdg.backColor=c
|
199
|
+
@backColor = c
|
200
|
+
super unless @hilighted
|
201
|
+
end
|
202
|
+
|
203
|
+
def wdg.backColor
|
204
|
+
@backColor
|
205
|
+
end
|
206
|
+
|
207
|
+
def wdg.hilighted=b
|
208
|
+
@hilighted = b
|
209
|
+
c = @hilighted ? MARKED_COLOR : @backColor
|
210
|
+
setBackColor(c)
|
211
|
+
end
|
212
|
+
wdg.backColor = wdg.getBackColor
|
213
|
+
wdg.enable
|
214
|
+
wdg.connect(SEL_LEFTBUTTONPRESS) {
|
215
|
+
onClick wdg
|
216
|
+
0
|
217
|
+
}
|
218
|
+
wdg.connect(SEL_RIGHTBUTTONPRESS) { |x, y, e|
|
219
|
+
unmark; # mark wdg
|
220
|
+
onClick wdg
|
221
|
+
@wdgMenu.popup_over(wdg, e.rootclick_x, e.rootclick_y)
|
222
|
+
0
|
223
|
+
}
|
224
|
+
wdg.create
|
225
|
+
wdg.recalc
|
226
|
+
wdg.shell.forceRefresh
|
227
|
+
wdg.create_defaults
|
228
|
+
unmark
|
229
|
+
mark wdg
|
230
|
+
wdg
|
231
|
+
end
|
232
|
+
|
233
|
+
def create_implicit_children parentclass
|
234
|
+
return unless @implicit_children
|
235
|
+
if ["Menubar"].member? parentclass
|
236
|
+
add_widget "MenuTitle", "inside"
|
237
|
+
elsif ["MenuTitle", "MenuCascade", "OptionMenu", "MenuButton"].member? parentclass
|
238
|
+
add_widget "MenuPane", "inside"
|
239
|
+
elsif ["TabItem"].member? parentclass
|
240
|
+
add_widget "VerticalFrame", "after"
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def rename_wdg wdg, newName
|
245
|
+
return unless wdg
|
246
|
+
begin
|
247
|
+
nil.instance_eval("@#{newName}", __FILE__, __LINE__) # check if newName is a suitable instance variable name
|
248
|
+
rescue Exception
|
249
|
+
puts $!
|
250
|
+
puts $!.backtrace
|
251
|
+
return
|
252
|
+
end
|
253
|
+
item = wdg.userData.treeitem
|
254
|
+
return if item.nil?
|
255
|
+
return if item == newName
|
256
|
+
if @w.has_key? newName
|
257
|
+
puts "<#{newName}> already exists!"
|
258
|
+
return
|
259
|
+
end
|
260
|
+
oldName = item.to_s
|
261
|
+
item.text = newName
|
262
|
+
wdg.wdg_name = newName
|
263
|
+
wdg.userData.treeitem = item
|
264
|
+
@w[newName] = wdg
|
265
|
+
@w.delete oldName if @w[oldName] == @w[newName]
|
266
|
+
@fxtree.update
|
267
|
+
true
|
268
|
+
end
|
269
|
+
|
270
|
+
def check_integrity type, parent
|
271
|
+
if type == "MenuPane" and !parent.respond_to?(:menu=)
|
272
|
+
raise "error: #{parent.class} cannot be parent to a MenuPane!"
|
273
|
+
elsif type == "MenuTitle" and !parent.is_a? FXToolBar
|
274
|
+
raise "not allowed: behavior undefined!"
|
275
|
+
elsif type == "MenuCascade" and !parent.is_a? FXPopup
|
276
|
+
raise "not allowed: behavior undefined!"
|
277
|
+
elsif type == "TabItem" and !parent.is_a? FXTabBar
|
278
|
+
raise 'error: #{parent.class} cannot hold a TabItem!'
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
# moves a widget in the browser and the gui
|
283
|
+
def relink_wdg item, where, relativeItem
|
284
|
+
assert(relativeItem, item, where)
|
285
|
+
wdg = @w[item.to_s]
|
286
|
+
parent = @w[relativeItem.parent.to_s]
|
287
|
+
relativeWdg = @w[relativeItem.to_s]
|
288
|
+
unless RelinkMechanisms.relink_possible?(wdg, where, relativeWdg)
|
289
|
+
puts "relink of #{wdg} #{where} #{relativeWdg} is not possible" # TODO log4r!
|
290
|
+
return
|
291
|
+
end
|
292
|
+
new = nil
|
293
|
+
if where == "before"
|
294
|
+
new = @fxtree.insertItem relativeItem, relativeItem.parent, FXTreeItem.new(item.to_s)
|
295
|
+
elsif where == "after"
|
296
|
+
new = if relativeItem.next
|
297
|
+
@fxtree.insertItem relativeItem.next, relativeItem.parent, FXTreeItem.new(item.to_s)
|
298
|
+
else
|
299
|
+
@fxtree.appendItem relativeItem.parent, FXTreeItem.new(item.to_s)
|
300
|
+
end
|
301
|
+
elsif where == "inside"
|
302
|
+
new = @fxtree.appendItem relativeItem, FXTreeItem.new(item.to_s)
|
303
|
+
else
|
304
|
+
return
|
305
|
+
end
|
306
|
+
expand_parents new
|
307
|
+
@fxtree.currentItem = new
|
308
|
+
a = []
|
309
|
+
subitem = nil
|
310
|
+
item.each { |subitem| a << subitem }
|
311
|
+
a.each { |subitem|
|
312
|
+
@fxtree.reparentItem subitem, new
|
313
|
+
}
|
314
|
+
RelinkMechanisms.relink_wdg wdg, where, relativeWdg
|
315
|
+
@fxtree.removeItem item
|
316
|
+
wdg.userData.treeitem = new # TODO don't use userData. better a singleton instance var
|
317
|
+
unmark
|
318
|
+
mark wdg
|
319
|
+
@fxtree.forceRefresh
|
320
|
+
wdg.shell.forceRefresh
|
321
|
+
set_dirty
|
322
|
+
wdg
|
323
|
+
end
|
324
|
+
|
325
|
+
# used to add a newly instanciated widget to the hashmap @widgets which
|
326
|
+
# associates widget names to widget references
|
327
|
+
# note: this method renames ambiguous names
|
328
|
+
def add_reference name, wdg
|
329
|
+
assert(wdg)
|
330
|
+
name = get_name(name)
|
331
|
+
@w[name] = wdg
|
332
|
+
wdg.set_name name
|
333
|
+
name
|
334
|
+
end
|
335
|
+
|
336
|
+
# makes shure a widget name is unique within the widgettree
|
337
|
+
# applies a simple renaming scheme and returns the unique name
|
338
|
+
def get_name(name)
|
339
|
+
begin
|
340
|
+
if @names.has_key? name
|
341
|
+
@names[name] += 1
|
342
|
+
else
|
343
|
+
@names[name] = 1
|
344
|
+
end
|
345
|
+
postfix = ""
|
346
|
+
postfix = @names[name].to_s if @names[name] > 0
|
347
|
+
wdg_name = name + postfix
|
348
|
+
end while(@w.has_key?(wdg_name)) # check, that name is unique
|
349
|
+
wdg_name
|
350
|
+
end
|
351
|
+
|
352
|
+
# sets the document as modified, as to ask the user to save on exit
|
353
|
+
def set_dirty
|
354
|
+
unless @dirty
|
355
|
+
@dirty = true
|
356
|
+
DocMan.instance.set_dirty self
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
def show # ????
|
361
|
+
MAINWIN.topwin.show(Fox::PLACEMENT_SCREEN)
|
362
|
+
end
|
363
|
+
|
364
|
+
# expands or collapses all subnodes of the item in the widget browser treelist
|
365
|
+
def expand item, bool = true
|
366
|
+
if bool
|
367
|
+
@fxtree.expandTree item
|
368
|
+
else
|
369
|
+
@fxtree.collapseTree item
|
370
|
+
end
|
371
|
+
item.each { |sub|
|
372
|
+
expand sub, bool
|
373
|
+
}
|
374
|
+
end
|
375
|
+
|
376
|
+
# expands all parents for the item to be shown
|
377
|
+
def expand_parents item
|
378
|
+
assert item
|
379
|
+
unless item.parent.nil?
|
380
|
+
@fxtree.expandTree item.parent
|
381
|
+
expand_parents item.parent
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
# colorizes the background of the currently selected widget.
|
386
|
+
# if marked allready the original color is restored
|
387
|
+
def mark wdg
|
388
|
+
return unless wdg
|
389
|
+
if wdg == @marked
|
390
|
+
wdg.hilighted = wdg.instance_eval { !@hilighted }
|
391
|
+
else
|
392
|
+
unmark
|
393
|
+
wdg.hilighted = true
|
394
|
+
@marked = wdg
|
395
|
+
$__wdg__ = @marked # for console debugging
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
# makes shure the current widget is not marked
|
400
|
+
def unmark
|
401
|
+
return unless @marked
|
402
|
+
@marked.hilighted = false
|
403
|
+
@marked = nil
|
404
|
+
end
|
405
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
---
|
2
|
+
DND Events :
|
3
|
+
- SEL_BEGINDRAG
|
4
|
+
- SEL_ENDDRAG
|
5
|
+
- SEL_DRAGGED
|
6
|
+
- SEL_DND_ENTER
|
7
|
+
- SEL_DND_LEAVE
|
8
|
+
- SEL_DND_DROP
|
9
|
+
- SEL_DND_MOTION
|
10
|
+
- SEL_DND_REQUEST
|
11
|
+
Keyboard Events :
|
12
|
+
- SEL_KEYPRESS
|
13
|
+
- SEL_KEYRELEASE
|
14
|
+
- SEL_KEYMAP
|
15
|
+
Mouse Events :
|
16
|
+
- SEL_LEFTBUTTONPRESS
|
17
|
+
- SEL_LEFTBUTTONRELEASE
|
18
|
+
- SEL_MIDDLEBUTTONPRESS
|
19
|
+
- SEL_MIDDLEBUTTONRELEASE
|
20
|
+
- SEL_RIGHTBUTTONPRESS
|
21
|
+
- SEL_RIGHTBUTTONRELEASE
|
22
|
+
- SEL_MOTION
|
23
|
+
- SEL_CLICKED
|
24
|
+
- SEL_DOUBLECLICKED
|
25
|
+
- SEL_TRIPLECLICKED
|
26
|
+
- SEL_MOUSEWHEEL
|
27
|
+
Clipboard Events :
|
28
|
+
- SEL_CLIPBOARD_LOST
|
29
|
+
- SEL_CLIPBOARD_GAINED
|
30
|
+
- SEL_CLIPBOARD_REQUEST
|
31
|
+
Focus Events :
|
32
|
+
- SEL_FOCUS_SELF
|
33
|
+
- SEL_FOCUS_RIGHT
|
34
|
+
- SEL_FOCUS_LEFT
|
35
|
+
- SEL_FOCUS_DOWN
|
36
|
+
- SEL_FOCUS_UP
|
37
|
+
- SEL_FOCUS_NEXT
|
38
|
+
- SEL_FOCUS_PREV
|
39
|
+
- SEL_FOCUSIN
|
40
|
+
- SEL_FOCUSOUT
|
41
|
+
Window Events:
|
42
|
+
- SEL_ENTER
|
43
|
+
- SEL_LEAVE
|
44
|
+
- SEL_PAINT
|
45
|
+
- SEL_CREATE
|
46
|
+
- SEL_DESTROY
|
47
|
+
- SEL_UNMAP
|
48
|
+
- SEL_MAP
|
49
|
+
- SEL_CONFIGURE
|
50
|
+
- SEL_UPDATE
|
51
|
+
- SEL_RAISED
|
52
|
+
- SEL_LOWERED
|
53
|
+
- SEL_CLOSE
|
54
|
+
- SEL_DELETE
|
55
|
+
- SEL_MINIMIZE
|
56
|
+
- SEL_RESTORE
|
57
|
+
- SEL_MAXIMIZE
|
58
|
+
Common Events:
|
59
|
+
- SEL_COMMAND
|
60
|
+
- SEL_CHANGED
|
61
|
+
Selection Events:
|
62
|
+
- SEL_SELECTION_LOST
|
63
|
+
- SEL_SELECTION_GAINED
|
64
|
+
- SEL_SELECTION_REQUEST
|
65
|
+
- SEL_DESELECTED
|
66
|
+
- SEL_SELECTED
|
67
|
+
TreeList Events:
|
68
|
+
- SEL_EXPANDED
|
69
|
+
- SEL_COLLAPSED
|
70
|
+
Time Events:
|
71
|
+
- SEL_TIMEOUT
|
72
|
+
- SEL_CHORE
|
73
|
+
Other Events:
|
74
|
+
- SEL_SIGNAL
|
75
|
+
- SEL_LASSOED
|
76
|
+
- SEL_PICKED
|
77
|
+
- SEL_QUERY_TIP
|
78
|
+
- SEL_QUERY_HELP
|
79
|
+
- SEL_UNGRABBED
|
80
|
+
- SEL_VERIFY
|
81
|
+
- SEL_INSERTED
|
82
|
+
- SEL_REPLACED
|
83
|
+
- SEL_DELETED
|
84
|
+
- SEL_OPENED
|
85
|
+
- SEL_CLOSED
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Copyright (c) 2004-2006 by Henon (meinrad dot recheis at gmail dot com)
|
2
|
+
|
3
|
+
class Module
|
4
|
+
def __sends__ *args
|
5
|
+
args.each { |arg|
|
6
|
+
class_eval <<-CEEND, __FILE__, __LINE__ + 1
|
7
|
+
def on_#{arg}(&callback)
|
8
|
+
@#{arg}_observers ||= {}
|
9
|
+
@#{arg}_observers[caller[0]]=callback
|
10
|
+
return caller[0]
|
11
|
+
end
|
12
|
+
def del_#{arg}(id)
|
13
|
+
@#{arg}_observers ||= {}
|
14
|
+
return @#{arg}_observers.delete( id)
|
15
|
+
end
|
16
|
+
private
|
17
|
+
def #{arg} *the_args
|
18
|
+
@#{arg}_observers ||= {}
|
19
|
+
@#{arg}_observers.each { |caller, cb|
|
20
|
+
cb.call *the_args
|
21
|
+
}
|
22
|
+
end
|
23
|
+
CEEND
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if __FILE__ == $0
|
29
|
+
class TextBox
|
30
|
+
__sends__ "text_changed", "key_pressed"
|
31
|
+
|
32
|
+
def initialize txt = ""
|
33
|
+
@txt = txt
|
34
|
+
end
|
35
|
+
|
36
|
+
def txt= txt
|
37
|
+
@txt = txt
|
38
|
+
text_changed
|
39
|
+
end
|
40
|
+
|
41
|
+
def key_press key
|
42
|
+
key_pressed key
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
box = TextBox.new
|
47
|
+
text_changed_id = box.on_text_changed { puts "Text changed!" }
|
48
|
+
5.times { |i|
|
49
|
+
box.on_key_pressed { |k| puts "(#{i}) Key pressed: #{k}" }
|
50
|
+
}
|
51
|
+
|
52
|
+
box.txt = "New text!"
|
53
|
+
box.del_text_changed(text_changed_id)
|
54
|
+
box.txt = "New text!"
|
55
|
+
|
56
|
+
box.key_press "j"
|
57
|
+
end
|
data/src/events.yaml
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
---
|
2
|
+
- SEL_ENDDRAG
|
3
|
+
- SEL_DRAGGED
|
4
|
+
- SEL_LASSOED
|
5
|
+
- SEL_TIMEOUT
|
6
|
+
- SEL_SIGNAL
|
7
|
+
- SEL_CLIPBOARD_LOST
|
8
|
+
- SEL_CLIPBOARD_GAINED
|
9
|
+
- SEL_CLIPBOARD_REQUEST
|
10
|
+
- SEL_CHORE
|
11
|
+
- SEL_FOCUS_SELF
|
12
|
+
- SEL_FOCUS_RIGHT
|
13
|
+
- SEL_FOCUS_LEFT
|
14
|
+
- SEL_FOCUS_DOWN
|
15
|
+
- SEL_FOCUS_UP
|
16
|
+
- SEL_FOCUS_NEXT
|
17
|
+
- SEL_FOCUS_PREV
|
18
|
+
- SEL_DND_ENTER
|
19
|
+
- SEL_KEYPRESS
|
20
|
+
- SEL_DND_LEAVE
|
21
|
+
- SEL_KEYRELEASE
|
22
|
+
- SEL_DND_DROP
|
23
|
+
- SEL_LEFTBUTTONPRESS
|
24
|
+
- SEL_DND_MOTION
|
25
|
+
- SEL_LEFTBUTTONRELEASE
|
26
|
+
- SEL_DND_REQUEST
|
27
|
+
- SEL_MIDDLEBUTTONPRESS
|
28
|
+
- SEL_IO_READ
|
29
|
+
- SEL_MIDDLEBUTTONRELEASE
|
30
|
+
- SEL_IO_WRITE
|
31
|
+
- SEL_RIGHTBUTTONPRESS
|
32
|
+
- SEL_IO_EXCEPT
|
33
|
+
- SEL_RIGHTBUTTONRELEASE
|
34
|
+
- SEL_PICKED
|
35
|
+
- SEL_MOTION
|
36
|
+
- SEL_QUERY_TIP
|
37
|
+
- SEL_ENTER
|
38
|
+
- SEL_QUERY_HELP
|
39
|
+
- SEL_LEAVE
|
40
|
+
- SEL_FOCUSIN
|
41
|
+
- SEL_FOCUSOUT
|
42
|
+
- SEL_KEYMAP
|
43
|
+
- SEL_UNGRABBED
|
44
|
+
- SEL_PAINT
|
45
|
+
- SEL_CREATE
|
46
|
+
- SEL_DESTROY
|
47
|
+
- SEL_UNMAP
|
48
|
+
- SEL_MAP
|
49
|
+
- SEL_CONFIGURE
|
50
|
+
- SEL_SELECTION_LOST
|
51
|
+
- SEL_SELECTION_GAINED
|
52
|
+
- SEL_SELECTION_REQUEST
|
53
|
+
- SEL_RAISED
|
54
|
+
- SEL_LOWERED
|
55
|
+
- SEL_CLOSE
|
56
|
+
- SEL_DELETE
|
57
|
+
- SEL_MINIMIZE
|
58
|
+
- SEL_RESTORE
|
59
|
+
- SEL_MAXIMIZE
|
60
|
+
- SEL_UPDATE
|
61
|
+
- SEL_COMMAND
|
62
|
+
- SEL_CLICKED
|
63
|
+
- SEL_DOUBLECLICKED
|
64
|
+
- SEL_TRIPLECLICKED
|
65
|
+
- SEL_MOUSEWHEEL
|
66
|
+
- SEL_CHANGED
|
67
|
+
- SEL_VERIFY
|
68
|
+
- SEL_DESELECTED
|
69
|
+
- SEL_SELECTED
|
70
|
+
- SEL_INSERTED
|
71
|
+
- SEL_REPLACED
|
72
|
+
- SEL_DELETED
|
73
|
+
- SEL_OPENED
|
74
|
+
- SEL_CLOSED
|
75
|
+
- SEL_EXPANDED
|
76
|
+
- SEL_COLLAPSED
|
77
|
+
- SEL_BEGINDRAG
|