fxruby 1.6.5 → 1.6.6
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/apes02.html +2 -2
- data/doc/apes03.html +1 -1
- data/doc/book.html +1 -1
- data/doc/changes.html +55 -21
- data/doc/differences.html +9 -9
- data/doc/implementation.html +1 -1
- data/doc/library.html +5 -5
- data/doc/opengl.html +5 -5
- data/doc/pt02.html +1 -1
- data/doc/scintilla.html +4 -4
- data/doc/subversion.html +1 -1
- data/examples/accell.rb +36 -0
- data/examples/babelfish.rb +6 -9
- data/examples/bounce.rb +5 -4
- data/examples/button.rb +19 -21
- data/examples/datatarget.rb +9 -8
- data/examples/dctest.rb +7 -13
- data/examples/dialog.rb +12 -16
- data/examples/dilbert.rb +4 -4
- data/examples/dirlist.rb +6 -5
- data/examples/dragdrop.rb +30 -33
- data/examples/dragsource.rb +22 -22
- data/examples/dropsite.rb +16 -17
- data/examples/foursplit.rb +8 -13
- data/examples/gltest.rb +21 -24
- data/examples/glviewer.rb +56 -58
- data/examples/header.rb +25 -25
- data/examples/iconlist.rb +12 -8
- data/examples/image.rb +36 -34
- data/examples/imageviewer.rb +44 -43
- data/examples/inputs.rb +15 -15
- data/examples/mditest.rb +6 -5
- data/examples/pig.rb +1 -0
- data/examples/raabrowser.rb +31 -40
- data/examples/ratio.rb +27 -16
- data/examples/rulerview.rb +4 -3
- data/examples/scribble.rb +14 -17
- data/examples/shutter.rb +10 -9
- data/examples/splitter.rb +7 -6
- data/examples/tabbook.rb +59 -17
- data/examples/table.rb +12 -16
- data/ext/fox16/FXRuby.cpp +2 -2
- data/lib/fox16/glshapes.rb +6 -6
- data/lib/fox16/iterators.rb +13 -8
- data/lib/fox16/kwargs.rb +604 -380
- data/lib/fox16/version.rb +1 -1
- data/tests/TC_FXTreeList.rb +13 -13
- data/tests/TC_FXTreeListBox.rb +3 -3
- metadata +4 -3
data/examples/dragdrop.rb
CHANGED
@@ -1,29 +1,31 @@
|
|
1
1
|
require 'fox16'
|
2
|
+
require 'fox16/kwargs'
|
2
3
|
|
3
4
|
include Fox
|
4
5
|
|
5
6
|
class DragDropWindow < FXMainWindow
|
7
|
+
|
6
8
|
def initialize(anApp)
|
7
9
|
# Initialize base class
|
8
|
-
super(anApp, "Drag and Drop",
|
10
|
+
super(anApp, "Drag and Drop", :opts => DECOR_ALL, :width => 400, :height => 300)
|
9
11
|
|
10
12
|
# Fill main window with canvas
|
11
|
-
@canvas = FXCanvas.new(self,
|
13
|
+
@canvas = FXCanvas.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
12
14
|
@canvas.backColor = "red"
|
13
15
|
|
14
16
|
# Enable canvas for drag-and-drop messages
|
15
17
|
@canvas.dropEnable
|
16
18
|
|
17
19
|
# Handle expose events on the canvas
|
18
|
-
@canvas.connect(SEL_PAINT)
|
19
|
-
FXDCWindow.new(@canvas, event)
|
20
|
+
@canvas.connect(SEL_PAINT) do |sender, sel, event|
|
21
|
+
FXDCWindow.new(@canvas, event) do |dc|
|
20
22
|
dc.foreground = @canvas.backColor
|
21
23
|
dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w, event.rect.h)
|
22
|
-
|
23
|
-
|
24
|
+
end
|
25
|
+
end
|
24
26
|
|
25
27
|
# Handle left button press
|
26
|
-
@canvas.connect(SEL_LEFTBUTTONPRESS)
|
28
|
+
@canvas.connect(SEL_LEFTBUTTONPRESS) do
|
27
29
|
#
|
28
30
|
# Capture (grab) the mouse when the button goes down, so that all future
|
29
31
|
# mouse events will be reported to this widget, even if those events occur
|
@@ -34,49 +36,44 @@ class DragDropWindow < FXMainWindow
|
|
34
36
|
# Advertise which drag types we can offer
|
35
37
|
dragTypes = [FXWindow.colorType]
|
36
38
|
@canvas.beginDrag(dragTypes)
|
37
|
-
|
39
|
+
end
|
38
40
|
|
39
41
|
# Handle mouse motion events
|
40
|
-
@canvas.connect(SEL_MOTION)
|
42
|
+
@canvas.connect(SEL_MOTION) do |sender, sel, event|
|
41
43
|
if @canvas.dragging?
|
42
44
|
@canvas.handleDrag(event.root_x, event.root_y)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
unless @canvas.didAccept == DRAG_REJECT
|
46
|
+
@canvas.dragCursor = getApp().getDefaultCursor(DEF_SWATCH_CURSOR)
|
47
|
+
else
|
48
|
+
@canvas.dragCursor = getApp().getDefaultCursor(DEF_DNDSTOP_CURSOR)
|
49
|
+
end
|
48
50
|
end
|
49
|
-
|
51
|
+
end
|
50
52
|
|
51
53
|
# Handle SEL_DND_MOTION messages from the canvas
|
52
|
-
@canvas.connect(SEL_DND_MOTION)
|
53
|
-
if @canvas.offeredDNDType?(FROM_DRAGNDROP, FXWindow.colorType)
|
54
|
-
|
55
|
-
end
|
56
|
-
}
|
54
|
+
@canvas.connect(SEL_DND_MOTION) do
|
55
|
+
@canvas.acceptDrop if @canvas.offeredDNDType?(FROM_DRAGNDROP, FXWindow.colorType)
|
56
|
+
end
|
57
57
|
|
58
58
|
# Handle left button release
|
59
|
-
@canvas.connect(SEL_LEFTBUTTONRELEASE)
|
59
|
+
@canvas.connect(SEL_LEFTBUTTONRELEASE) do
|
60
60
|
@canvas.ungrab
|
61
61
|
@canvas.endDrag
|
62
|
-
|
62
|
+
end
|
63
63
|
|
64
64
|
# Handle SEL_DND_DROP message from the canvas
|
65
|
-
@canvas.connect(SEL_DND_DROP)
|
65
|
+
@canvas.connect(SEL_DND_DROP) do
|
66
66
|
# Try to obtain the data as color values first
|
67
67
|
data = @canvas.getDNDData(FROM_DRAGNDROP, FXWindow.colorType)
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
}
|
68
|
+
|
69
|
+
# Update canvas background color
|
70
|
+
@canvas.backColor = Fox.fxdecodeColorData(data) unless data.nil?
|
71
|
+
end
|
73
72
|
|
74
73
|
# Handle request for DND data
|
75
|
-
@canvas.connect(SEL_DND_REQUEST)
|
76
|
-
if event.target == FXWindow.colorType
|
77
|
-
|
78
|
-
end
|
79
|
-
}
|
74
|
+
@canvas.connect(SEL_DND_REQUEST) do |sender, sel, event|
|
75
|
+
@canvas.setDNDData(FROM_DRAGNDROP, FXWindow.colorType, Fox.fxencodeColorData(@canvas.backColor)) if event.target == FXWindow.colorType
|
76
|
+
end
|
80
77
|
end
|
81
78
|
|
82
79
|
def create
|
data/examples/dragsource.rb
CHANGED
@@ -1,26 +1,28 @@
|
|
1
1
|
require 'fox16'
|
2
|
+
require 'fox16/kwargs'
|
2
3
|
|
3
4
|
include Fox
|
4
5
|
|
5
6
|
class DragSource < FXMainWindow
|
7
|
+
|
6
8
|
def initialize(anApp)
|
7
9
|
# Initialize base class
|
8
|
-
super(anApp, "Drag Source",
|
10
|
+
super(anApp, "Drag Source", :opts => DECOR_ALL, :width => 400, :height => 300)
|
9
11
|
|
10
12
|
# Fill main window with canvas
|
11
|
-
@canvas = FXCanvas.new(self,
|
13
|
+
@canvas = FXCanvas.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
12
14
|
@canvas.backColor = "red"
|
13
15
|
|
14
16
|
# Handle expose events on the canvas
|
15
|
-
@canvas.connect(SEL_PAINT)
|
16
|
-
FXDCWindow.new(@canvas, event)
|
17
|
+
@canvas.connect(SEL_PAINT) do |sender, sel, event|
|
18
|
+
FXDCWindow.new(@canvas, event) do |dc|
|
17
19
|
dc.foreground = @canvas.backColor
|
18
20
|
dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w, event.rect.h)
|
19
|
-
|
20
|
-
|
21
|
+
end
|
22
|
+
end
|
21
23
|
|
22
24
|
# Handle left button press
|
23
|
-
@canvas.connect(SEL_LEFTBUTTONPRESS)
|
25
|
+
@canvas.connect(SEL_LEFTBUTTONPRESS) do
|
24
26
|
#
|
25
27
|
# Capture (grab) the mouse when the button goes down, so that all future
|
26
28
|
# mouse events will be reported to this widget, even if those events occur
|
@@ -31,32 +33,30 @@ class DragSource < FXMainWindow
|
|
31
33
|
# Advertise which drag types we can offer
|
32
34
|
dragTypes = [FXWindow.colorType]
|
33
35
|
@canvas.beginDrag(dragTypes)
|
34
|
-
|
36
|
+
end
|
35
37
|
|
36
38
|
# Handle mouse motion events
|
37
|
-
@canvas.connect(SEL_MOTION)
|
39
|
+
@canvas.connect(SEL_MOTION) do |sender, sel, event|
|
38
40
|
if @canvas.dragging?
|
39
41
|
@canvas.handleDrag(event.root_x, event.root_y)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
unless @canvas.didAccept == DRAG_REJECT
|
43
|
+
@canvas.dragCursor = getApp().getDefaultCursor(DEF_SWATCH_CURSOR)
|
44
|
+
else
|
45
|
+
@canvas.dragCursor = getApp().getDefaultCursor(DEF_DNDSTOP_CURSOR)
|
46
|
+
end
|
45
47
|
end
|
46
|
-
|
48
|
+
end
|
47
49
|
|
48
50
|
# Handle left button release
|
49
|
-
@canvas.connect(SEL_LEFTBUTTONRELEASE)
|
51
|
+
@canvas.connect(SEL_LEFTBUTTONRELEASE) do
|
50
52
|
@canvas.ungrab
|
51
53
|
@canvas.endDrag
|
52
|
-
|
54
|
+
end
|
53
55
|
|
54
56
|
# Handle request for DND data
|
55
|
-
@canvas.connect(SEL_DND_REQUEST)
|
56
|
-
if event.target == FXWindow.colorType
|
57
|
-
|
58
|
-
end
|
59
|
-
}
|
57
|
+
@canvas.connect(SEL_DND_REQUEST) do |sender, sel, event|
|
58
|
+
@canvas.setDNDData(FROM_DRAGNDROP, FXWindow.colorType, Fox.fxencodeColorData(@canvas.backColor)) if event.target == FXWindow.colorType
|
59
|
+
end
|
60
60
|
end
|
61
61
|
|
62
62
|
def create
|
data/examples/dropsite.rb
CHANGED
@@ -1,42 +1,41 @@
|
|
1
1
|
require 'fox16'
|
2
|
+
require 'fox16/kwargs'
|
2
3
|
|
3
4
|
include Fox
|
4
5
|
|
5
6
|
class DropSite < FXMainWindow
|
7
|
+
|
6
8
|
def initialize(anApp)
|
7
9
|
# Initialize base class
|
8
|
-
super(anApp, "Drop Site"
|
10
|
+
super(anApp, "Drop Site",:opts => DECOR_ALL, :width => 400, :height => 300)
|
9
11
|
|
10
12
|
# Fill main window with canvas
|
11
|
-
@canvas = FXCanvas.new(self,
|
13
|
+
@canvas = FXCanvas.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
12
14
|
|
13
15
|
# Handle expose events on the canvas
|
14
|
-
@canvas.connect(SEL_PAINT)
|
15
|
-
FXDCWindow.new(@canvas, event)
|
16
|
+
@canvas.connect(SEL_PAINT) do |sender, sel, event|
|
17
|
+
FXDCWindow.new(@canvas, event) do |dc|
|
16
18
|
dc.foreground = @canvas.backColor
|
17
19
|
dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w, event.rect.h)
|
18
|
-
|
19
|
-
|
20
|
+
end
|
21
|
+
end
|
20
22
|
|
21
23
|
# Enable canvas for drag-and-drop messages
|
22
24
|
@canvas.dropEnable
|
23
25
|
|
24
26
|
# Handle SEL_DND_MOTION messages from the canvas
|
25
|
-
@canvas.connect(SEL_DND_MOTION)
|
26
|
-
if @canvas.offeredDNDType?(FROM_DRAGNDROP, FXWindow.colorType)
|
27
|
-
|
28
|
-
end
|
29
|
-
}
|
27
|
+
@canvas.connect(SEL_DND_MOTION) do
|
28
|
+
@canvas.acceptDrop if @canvas.offeredDNDType?(FROM_DRAGNDROP, FXWindow.colorType)
|
29
|
+
end
|
30
30
|
|
31
31
|
# Handle SEL_DND_DROP message from the canvas
|
32
|
-
@canvas.connect(SEL_DND_DROP)
|
32
|
+
@canvas.connect(SEL_DND_DROP) do
|
33
33
|
# Try to obtain the data as color values first
|
34
34
|
data = @canvas.getDNDData(FROM_DRAGNDROP, FXWindow.colorType)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
}
|
35
|
+
|
36
|
+
# Update canvas background color
|
37
|
+
@canvas.backColor = Fox.fxdecodeColorData(data) unless data.nil?
|
38
|
+
end
|
40
39
|
end
|
41
40
|
|
42
41
|
def create
|
data/examples/foursplit.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'fox16'
|
4
|
+
require 'fox16/kwargs'
|
4
5
|
|
5
6
|
include Fox
|
6
7
|
|
7
8
|
class FourSplitWindow < FXMainWindow
|
8
9
|
def initialize(app)
|
9
10
|
# Call the base class initialize() first
|
10
|
-
super(app, "4-Way Splitter Test",
|
11
|
+
super(app, "4-Way Splitter Test", :opts => DECOR_ALL, :width => 800, :height => 600)
|
11
12
|
|
12
13
|
# Menu bar, along the top
|
13
14
|
menubar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
|
@@ -47,14 +48,11 @@ class FourSplitWindow < FXMainWindow
|
|
47
48
|
# but the fourth is itself another 4-splitter. There is no
|
48
49
|
# restriction on nesting these kinds of widgets.
|
49
50
|
|
50
|
-
FXButton.new(splitter, "Top &Left\tThis splitter tracks",
|
51
|
-
nil, 0, FRAME_RAISED|FRAME_THICK)
|
51
|
+
FXButton.new(splitter, "Top &Left\tThis splitter tracks", :opts => FRAME_RAISED|FRAME_THICK)
|
52
52
|
|
53
|
-
FXButton.new(splitter, "Top &Right\tThis splitter tracks",
|
54
|
-
nil, 0, FRAME_RAISED|FRAME_THICK)
|
53
|
+
FXButton.new(splitter, "Top &Right\tThis splitter tracks", :opts => FRAME_RAISED|FRAME_THICK)
|
55
54
|
|
56
|
-
FXButton.new(splitter, "&Bottom Left\tThis splitter tracks",
|
57
|
-
nil, 0, FRAME_SUNKEN|FRAME_THICK)
|
55
|
+
FXButton.new(splitter, "&Bottom Left\tThis splitter tracks", :opts => FRAME_SUNKEN|FRAME_THICK)
|
58
56
|
|
59
57
|
subsplitter = FX4Splitter.new(splitter, LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
60
58
|
|
@@ -66,20 +64,17 @@ class FourSplitWindow < FXMainWindow
|
|
66
64
|
end
|
67
65
|
|
68
66
|
button = FXButton.new(subsplitter,
|
69
|
-
"the&y CAN\tThis splitter does NOT track",
|
70
|
-
nil, 0, FRAME_SUNKEN|FRAME_THICK)
|
67
|
+
"the&y CAN\tThis splitter does NOT track", :opts => FRAME_SUNKEN|FRAME_THICK)
|
71
68
|
button.backColor = FXRGB(128, 0, 0)
|
72
69
|
button.textColor = FXRGB(255, 255, 255)
|
73
70
|
|
74
71
|
button = FXButton.new(subsplitter,
|
75
|
-
"be &NESTED\tThis splitter does NOT track",
|
76
|
-
nil, 0, FRAME_SUNKEN|FRAME_THICK)
|
72
|
+
"be &NESTED\tThis splitter does NOT track", :opts => FRAME_SUNKEN|FRAME_THICK)
|
77
73
|
button.backColor = FXRGB(0, 0, 200)
|
78
74
|
button.textColor = FXRGB(255, 255, 255)
|
79
75
|
|
80
76
|
button = FXButton.new(subsplitter,
|
81
|
-
"&arbitrarily!\tThis splitter does NOT track",
|
82
|
-
nil, 0, FRAME_SUNKEN|FRAME_THICK)
|
77
|
+
"&arbitrarily!\tThis splitter does NOT track", :opts => FRAME_SUNKEN|FRAME_THICK)
|
83
78
|
button.backColor = FXRGB(128, 128, 0)
|
84
79
|
button.textColor = FXRGB(255, 255, 255)
|
85
80
|
|
data/examples/gltest.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'fox16'
|
4
|
+
require 'fox16/kwargs'
|
4
5
|
begin
|
5
6
|
require 'opengl'
|
6
7
|
rescue LoadError
|
@@ -193,7 +194,7 @@ class GLTestWindow < FXMainWindow
|
|
193
194
|
|
194
195
|
def initialize(app)
|
195
196
|
# Invoke the base class initializer
|
196
|
-
super(app, "OpenGL Test Application",
|
197
|
+
super(app, "OpenGL Test Application", :opts => DECOR_ALL, :width => 800, :height => 600)
|
197
198
|
|
198
199
|
# Construct the main window elements
|
199
200
|
frame = FXHorizontalFrame.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
@@ -223,17 +224,14 @@ class GLTestWindow < FXMainWindow
|
|
223
224
|
@glvisual = FXGLVisual.new(getApp(), VISUAL_DOUBLEBUFFER)
|
224
225
|
|
225
226
|
# Drawing glcanvas
|
226
|
-
@glcanvas = FXGLCanvas.new(glpanel, @glvisual,
|
227
|
-
|
228
|
-
@glcanvas.connect(
|
229
|
-
drawScene
|
230
|
-
}
|
231
|
-
@glcanvas.connect(SEL_CONFIGURE) {
|
227
|
+
@glcanvas = FXGLCanvas.new(glpanel, @glvisual, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
|
228
|
+
@glcanvas.connect(SEL_PAINT) { drawScene }
|
229
|
+
@glcanvas.connect(SEL_CONFIGURE) do
|
232
230
|
if @glcanvas.makeCurrent
|
233
231
|
GL.Viewport(0, 0, @glcanvas.width, @glcanvas.height)
|
234
232
|
@glcanvas.makeNonCurrent
|
235
233
|
end
|
236
|
-
|
234
|
+
end
|
237
235
|
|
238
236
|
# Right pane for the buttons
|
239
237
|
buttonFrame = FXVerticalFrame.new(frame, LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
|
@@ -251,37 +249,36 @@ class GLTestWindow < FXMainWindow
|
|
251
249
|
spinTimerBtn = FXButton.new(buttonFrame, "Spin &Timer\tSpin using interval timers\nNote the app blocks until the interal has elapsed...",nil,nil,0,FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
|
252
250
|
spinTimerBtn.padLeft, spinTimerBtn.padRight = 10, 10
|
253
251
|
spinTimerBtn.padTop, spinTimerBtn.padBottom = 5, 5
|
254
|
-
spinTimerBtn.connect(SEL_COMMAND)
|
252
|
+
spinTimerBtn.connect(SEL_COMMAND) do
|
255
253
|
@spinning = true
|
256
254
|
@timer = getApp().addTimeout(TIMER_INTERVAL, method(:onTimeout))
|
257
|
-
|
258
|
-
spinTimerBtn.connect(SEL_UPDATE)
|
255
|
+
end
|
256
|
+
spinTimerBtn.connect(SEL_UPDATE) do |sender, sel, ptr|
|
259
257
|
@spinning ? sender.disable : sender.enable
|
260
|
-
|
258
|
+
end
|
261
259
|
|
262
260
|
# Spin according to chore
|
263
261
|
spinChoreBtn = FXButton.new(buttonFrame,
|
264
262
|
"Spin &Chore\tSpin as fast as possible using chores\nNote even though the
|
265
263
|
app is very responsive, it never blocks;\nthere is always something to
|
266
|
-
do...",
|
267
|
-
nil, 0, FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
|
264
|
+
do...", :opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
|
268
265
|
spinChoreBtn.padLeft, spinChoreBtn.padRight = 10, 10
|
269
266
|
spinChoreBtn.padTop, spinChoreBtn.padBottom = 5, 5
|
270
|
-
spinChoreBtn.connect(SEL_COMMAND)
|
267
|
+
spinChoreBtn.connect(SEL_COMMAND) do
|
271
268
|
@spinning = true
|
272
269
|
@chore = getApp().addChore(method(:onChore))
|
273
|
-
|
274
|
-
spinChoreBtn.connect(SEL_UPDATE)
|
270
|
+
end
|
271
|
+
spinChoreBtn.connect(SEL_UPDATE) do |sender, sel, ptr|
|
275
272
|
@spinning ? sender.disable : sender.enable
|
276
|
-
|
273
|
+
end
|
277
274
|
|
278
275
|
# Stop spinning
|
279
276
|
stopBtn = FXButton.new(buttonFrame,
|
280
|
-
"&Stop Spin\tStop this mad spinning, I'm getting dizzy",
|
281
|
-
|
277
|
+
"&Stop Spin\tStop this mad spinning, I'm getting dizzy",
|
278
|
+
:opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
|
282
279
|
stopBtn.padLeft, stopBtn.padRight = 10, 10
|
283
280
|
stopBtn.padTop, stopBtn.padBottom = 5, 5
|
284
|
-
stopBtn.connect(SEL_COMMAND)
|
281
|
+
stopBtn.connect(SEL_COMMAND) do
|
285
282
|
@spinning = false
|
286
283
|
if @timer
|
287
284
|
getApp().removeTimeout(@timer)
|
@@ -291,10 +288,10 @@ class GLTestWindow < FXMainWindow
|
|
291
288
|
getApp().removeChore(@chore)
|
292
289
|
@chore = nil
|
293
290
|
end
|
294
|
-
|
295
|
-
stopBtn.connect(SEL_UPDATE)
|
291
|
+
end
|
292
|
+
stopBtn.connect(SEL_UPDATE) do |sender, sel, ptr|
|
296
293
|
@spinning ? sender.enable : sender.disable
|
297
|
-
|
294
|
+
end
|
298
295
|
|
299
296
|
# Exit button
|
300
297
|
exitBtn = FXButton.new(buttonFrame, "&Exit\tExit the application", nil,
|
data/examples/glviewer.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'fox16'
|
4
4
|
require 'fox16/responder'
|
5
|
+
require 'fox16/kwargs'
|
5
6
|
begin
|
6
7
|
require 'fox16/glshapes'
|
7
8
|
rescue LoadError
|
@@ -23,67 +24,67 @@ class TabBook < FXTabBook
|
|
23
24
|
"Angles\tCamera Angles\tSwitch to camera angles panel.")
|
24
25
|
|
25
26
|
# Angles page
|
26
|
-
angles = FXMatrix.new(panels, 3,
|
27
|
-
MATRIX_BY_COLUMNS|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT
|
28
|
-
|
29
|
-
angles.padRight = 10
|
30
|
-
angles.padTop = 10
|
31
|
-
angles.padBottom = 10
|
27
|
+
angles = FXMatrix.new(panels, 3,
|
28
|
+
:opts => FRAME_THICK|FRAME_RAISED|MATRIX_BY_COLUMNS|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT,
|
29
|
+
:padding => 10)
|
32
30
|
|
33
31
|
FXLabel.new(angles, "X:")
|
34
|
-
FXTextField.new(angles, 6,
|
32
|
+
FXTextField.new(angles, 6,
|
33
|
+
mdiclient, FXGLViewer::ID_ROLL,
|
35
34
|
TEXTFIELD_INTEGER|JUSTIFY_RIGHT|FRAME_SUNKEN|FRAME_THICK)
|
36
|
-
x_dial = FXDial.new(angles,
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
x_dial = FXDial.new(angles,
|
36
|
+
mdiclient, FXGLViewer::ID_DIAL_X,
|
37
|
+
:opts => FRAME_SUNKEN|FRAME_THICK|DIAL_CYCLIC|DIAL_HORIZONTAL|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_CENTER_Y,
|
38
|
+
:width => 160, :height => 14, :padding => 0)
|
40
39
|
x_dial.tipText = "Rotate about X"
|
41
40
|
x_dial.notchOffset = 900
|
42
41
|
|
43
42
|
FXLabel.new(angles, "Y:")
|
44
|
-
FXTextField.new(angles, 6,
|
43
|
+
FXTextField.new(angles, 6,
|
44
|
+
mdiclient, FXGLViewer::ID_PITCH,
|
45
45
|
TEXTFIELD_INTEGER|JUSTIFY_RIGHT|FRAME_SUNKEN|FRAME_THICK)
|
46
|
-
y_dial = FXDial.new(angles,
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
y_dial = FXDial.new(angles,
|
47
|
+
mdiclient, FXGLViewer::ID_DIAL_Y,
|
48
|
+
:opts => FRAME_SUNKEN|FRAME_THICK|DIAL_CYCLIC|DIAL_HORIZONTAL|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_CENTER_Y,
|
49
|
+
:width => 160, :height => 14, :padding => 0)
|
50
50
|
y_dial.tipText = "Rotate about Y"
|
51
51
|
y_dial.notchOffset = 900
|
52
52
|
|
53
53
|
FXLabel.new(angles, "Z:")
|
54
|
-
FXTextField.new(angles, 6,
|
54
|
+
FXTextField.new(angles, 6,
|
55
|
+
mdiclient, FXGLViewer::ID_YAW,
|
55
56
|
TEXTFIELD_INTEGER|JUSTIFY_RIGHT|FRAME_SUNKEN|FRAME_THICK)
|
56
|
-
z_dial = FXDial.new(angles,
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
z_dial = FXDial.new(angles,
|
58
|
+
mdiclient, FXGLViewer::ID_DIAL_Z,
|
59
|
+
:opts => FRAME_SUNKEN|FRAME_THICK|DIAL_CYCLIC|DIAL_HORIZONTAL|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_CENTER_Y,
|
60
|
+
:width => 160, :height => 14, :padding => 0)
|
60
61
|
z_dial.tipText = "Rotate about Z"
|
61
62
|
z_dial.notchOffset = 900
|
62
63
|
|
63
64
|
FXLabel.new(angles, "FOV:")
|
64
65
|
fov = FXTextField.new(angles, 5, mdiclient, FXGLViewer::ID_FOV,
|
65
66
|
JUSTIFY_RIGHT|FRAME_SUNKEN|FRAME_THICK)
|
66
|
-
FXFrame.new(angles,
|
67
|
+
FXFrame.new(angles, :opts => FRAME_NONE)
|
67
68
|
fov.tipText = "Field of view"
|
68
69
|
|
69
70
|
FXLabel.new(angles, "Zoom:")
|
70
71
|
zz = FXTextField.new(angles, 5, mdiclient, FXGLViewer::ID_ZOOM,
|
71
72
|
JUSTIFY_RIGHT|FRAME_SUNKEN|FRAME_THICK)
|
72
|
-
FXFrame.new(angles,
|
73
|
+
FXFrame.new(angles, :opts => FRAME_NONE)
|
73
74
|
zz.tipText = "Zooming"
|
74
75
|
|
75
76
|
FXLabel.new(angles, "Scale X:")
|
76
77
|
FXTextField.new(angles, 5, mdiclient, FXGLViewer::ID_SCALE_X,
|
77
78
|
JUSTIFY_RIGHT|FRAME_SUNKEN|FRAME_THICK)
|
78
|
-
FXFrame.new(angles,
|
79
|
+
FXFrame.new(angles, :opts => FRAME_NONE)
|
79
80
|
FXLabel.new(angles, "Scale Y:")
|
80
81
|
FXTextField.new(angles, 5, mdiclient, FXGLViewer::ID_SCALE_Y,
|
81
82
|
JUSTIFY_RIGHT|FRAME_SUNKEN|FRAME_THICK)
|
82
|
-
FXFrame.new(angles,
|
83
|
+
FXFrame.new(angles, :opts => FRAME_NONE)
|
83
84
|
FXLabel.new(angles, "Scale Z:")
|
84
85
|
FXTextField.new(angles, 5, mdiclient, FXGLViewer::ID_SCALE_Z,
|
85
86
|
JUSTIFY_RIGHT|FRAME_SUNKEN|FRAME_THICK)
|
86
|
-
FXFrame.new(angles,
|
87
|
+
FXFrame.new(angles, :opts => FRAME_NONE)
|
87
88
|
end
|
88
89
|
|
89
90
|
def createColorsPage(panels, mdiclient)
|
@@ -91,33 +92,30 @@ class TabBook < FXTabBook
|
|
91
92
|
FXTabItem.new(panels, "Colors\tColors\tSwitch to color panel.")
|
92
93
|
|
93
94
|
# Colors page
|
94
|
-
colors = FXMatrix.new(panels, 2,
|
95
|
-
FRAME_RAISED|LAYOUT_FILL_Y|LAYOUT_CENTER_X|LAYOUT_TOP|LAYOUT_LEFT
|
96
|
-
|
97
|
-
colors.padRight = 10
|
98
|
-
colors.padTop = 10
|
99
|
-
colors.padBottom = 10
|
95
|
+
colors = FXMatrix.new(panels, 2,
|
96
|
+
MATRIX_BY_COLUMNS|FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_Y|LAYOUT_CENTER_X|LAYOUT_TOP|LAYOUT_LEFT,
|
97
|
+
:padding => 10)
|
100
98
|
FXLabel.new(colors, "Background:", nil,
|
101
99
|
LAYOUT_RIGHT|LAYOUT_CENTER_Y|JUSTIFY_RIGHT)
|
102
100
|
FXColorWell.new(colors, 0, mdiclient, FXGLViewer::ID_BACK_COLOR,
|
103
|
-
COLORWELL_OPAQUEONLY|LAYOUT_TOP|LAYOUT_LEFT,
|
101
|
+
COLORWELL_OPAQUEONLY|LAYOUT_TOP|LAYOUT_LEFT, :padding => 0)
|
104
102
|
FXLabel.new(colors, "Ambient:", nil,
|
105
103
|
LAYOUT_RIGHT|LAYOUT_CENTER_Y|JUSTIFY_RIGHT)
|
106
104
|
FXColorWell.new(colors, 0, mdiclient, FXGLViewer::ID_AMBIENT_COLOR,
|
107
|
-
COLORWELL_OPAQUEONLY|LAYOUT_TOP|LAYOUT_LEFT,
|
105
|
+
COLORWELL_OPAQUEONLY|LAYOUT_TOP|LAYOUT_LEFT, :padding => 0)
|
108
106
|
|
109
107
|
FXLabel.new(colors, "Light Amb:", nil,
|
110
108
|
LAYOUT_RIGHT|LAYOUT_CENTER_Y|JUSTIFY_RIGHT)
|
111
109
|
FXColorWell.new(colors, 0, mdiclient, FXGLViewer::ID_LIGHT_AMBIENT,
|
112
|
-
COLORWELL_OPAQUEONLY|LAYOUT_TOP|LAYOUT_LEFT,
|
110
|
+
COLORWELL_OPAQUEONLY|LAYOUT_TOP|LAYOUT_LEFT, :padding => 0)
|
113
111
|
FXLabel.new(colors, "Light Diff:", nil,
|
114
112
|
LAYOUT_RIGHT|LAYOUT_CENTER_Y|JUSTIFY_RIGHT)
|
115
113
|
FXColorWell.new(colors, 0, mdiclient, FXGLViewer::ID_LIGHT_DIFFUSE,
|
116
|
-
COLORWELL_OPAQUEONLY|LAYOUT_TOP|LAYOUT_LEFT,
|
114
|
+
COLORWELL_OPAQUEONLY|LAYOUT_TOP|LAYOUT_LEFT, :padding => 0)
|
117
115
|
FXLabel.new(colors, "Light Spec:", nil,
|
118
116
|
LAYOUT_RIGHT|LAYOUT_CENTER_Y|JUSTIFY_RIGHT)
|
119
117
|
FXColorWell.new(colors, 0, mdiclient, FXGLViewer::ID_LIGHT_SPECULAR,
|
120
|
-
COLORWELL_OPAQUEONLY|LAYOUT_TOP|LAYOUT_LEFT,
|
118
|
+
COLORWELL_OPAQUEONLY|LAYOUT_TOP|LAYOUT_LEFT, :padding => 0)
|
121
119
|
end
|
122
120
|
|
123
121
|
def createSwitchesPage(panels, mdiclient)
|
@@ -125,12 +123,9 @@ class TabBook < FXTabBook
|
|
125
123
|
FXTabItem.new(panels, "Settings\tSettings\tSwitche to settings panel.")
|
126
124
|
|
127
125
|
# Settings page
|
128
|
-
settings = FXVerticalFrame.new(panels,
|
129
|
-
LAYOUT_FILL_Y|LAYOUT_CENTER_X|LAYOUT_TOP|LAYOUT_LEFT
|
130
|
-
|
131
|
-
settings.padRight = 10
|
132
|
-
settings.padTop = 10
|
133
|
-
settings.padBottom = 10
|
126
|
+
settings = FXVerticalFrame.new(panels,
|
127
|
+
FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_Y|LAYOUT_CENTER_X|LAYOUT_TOP|LAYOUT_LEFT,
|
128
|
+
:padding => 10)
|
134
129
|
FXCheckButton.new(settings, "Lighting", mdiclient, FXGLViewer::ID_LIGHTING,
|
135
130
|
ICON_BEFORE_TEXT)
|
136
131
|
FXCheckButton.new(settings, "Fog", mdiclient, FXGLViewer::ID_FOG,
|
@@ -161,9 +156,9 @@ class GLViewWindow < FXMainWindow
|
|
161
156
|
begin
|
162
157
|
filename = File.join("icons", filename) + ".png"
|
163
158
|
icon = nil
|
164
|
-
File.open(filename, "rb")
|
159
|
+
File.open(filename, "rb") do |f|
|
165
160
|
icon = FXPNGIcon.new(getApp(), f.read)
|
166
|
-
|
161
|
+
end
|
167
162
|
icon
|
168
163
|
rescue
|
169
164
|
raise RuntimeError, "Couldn't load icon: #{filename}"
|
@@ -172,7 +167,7 @@ class GLViewWindow < FXMainWindow
|
|
172
167
|
|
173
168
|
def initialize(app)
|
174
169
|
# Initialize base class first
|
175
|
-
super(app, "OpenGL Example Application",
|
170
|
+
super(app, "OpenGL Example Application", :opts => DECOR_ALL, :width => 800, :height => 600)
|
176
171
|
|
177
172
|
# Define message identifiers for this class
|
178
173
|
|
@@ -194,22 +189,25 @@ class GLViewWindow < FXMainWindow
|
|
194
189
|
FXHorizontalSeparator.new(self,
|
195
190
|
LAYOUT_SIDE_TOP|SEPARATOR_GROOVE|LAYOUT_FILL_X);
|
196
191
|
toolbar = FXToolBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X,
|
197
|
-
|
192
|
+
:padLeft => 4, :padRight => 4, :padTop => 0, :padBottom => 0,
|
193
|
+
:hSpacing => 0, :vSpacing => 0)
|
198
194
|
|
199
195
|
# Make status bar
|
200
196
|
statusbar = FXStatusBar.new(self,
|
201
197
|
LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|STATUSBAR_WITH_DRAGCORNER)
|
202
198
|
|
203
199
|
# The good old penguin, what would we be without it?
|
204
|
-
FXButton.new(statusbar,
|
200
|
+
FXButton.new(statusbar,
|
201
|
+
"\tHello, I'm Tux...\nThe symbol for the Linux Operating System.\nAnd all it stands for.",
|
202
|
+
:icon => peng, :opts => LAYOUT_RIGHT)
|
205
203
|
|
206
204
|
# Contents
|
207
205
|
frame = FXHorizontalFrame.new(self,
|
208
|
-
LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y,
|
206
|
+
LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0, :hSpacing => 0, :vSpacing => 0)
|
209
207
|
|
210
208
|
# Nice sunken box around GL viewer
|
211
209
|
box = FXVerticalFrame.new(frame,
|
212
|
-
FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y,
|
210
|
+
FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0)
|
213
211
|
|
214
212
|
# MDI Client
|
215
213
|
@mdiclient = FXMDIClient.new(box, LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
@@ -299,14 +297,14 @@ class GLViewWindow < FXMainWindow
|
|
299
297
|
|
300
298
|
# Print
|
301
299
|
FXFrame.new(toolbar,
|
302
|
-
LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT,
|
300
|
+
LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, :width => 4, :height => 20)
|
303
301
|
FXButton.new(toolbar, "\tPrint Image\tPrint shapshot image.",
|
304
302
|
loadIcon("printicon"), @mdiclient, FXGLViewer::ID_PRINT_IMAGE,
|
305
303
|
BUTTON_AUTOGRAY|FRAME_THICK|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT)
|
306
304
|
|
307
305
|
# Editing
|
308
306
|
FXFrame.new(toolbar,
|
309
|
-
LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT,
|
307
|
+
LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, :width => 4, :height => 20)
|
310
308
|
FXButton.new(toolbar, "\tCut", loadIcon("cut"), @mdiclient,
|
311
309
|
FXGLViewer::ID_CUT_SEL, (BUTTON_AUTOGRAY|FRAME_THICK|FRAME_RAISED|
|
312
310
|
LAYOUT_TOP|LAYOUT_LEFT))
|
@@ -319,7 +317,7 @@ class GLViewWindow < FXMainWindow
|
|
319
317
|
|
320
318
|
# Projections
|
321
319
|
FXFrame.new(toolbar, (LAYOUT_TOP|LAYOUT_LEFT|
|
322
|
-
LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT),
|
320
|
+
LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT), :width => 8, :height => 20)
|
323
321
|
FXButton.new(toolbar, "\tPerspective\tSwitch to perspective projection.",
|
324
322
|
loadIcon("perspective"), @mdiclient, FXGLViewer::ID_PERSPECTIVE,
|
325
323
|
BUTTON_AUTOGRAY|FRAME_THICK|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT)
|
@@ -329,7 +327,7 @@ class GLViewWindow < FXMainWindow
|
|
329
327
|
|
330
328
|
# Shading model
|
331
329
|
FXFrame.new(toolbar, (LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|
|
332
|
-
LAYOUT_FIX_HEIGHT),
|
330
|
+
LAYOUT_FIX_HEIGHT), :width => 8, :height => 20)
|
333
331
|
FXButton.new(toolbar, "\tNo shading\tTurn light sources off.",
|
334
332
|
loadIcon("nolight"), @mdiclient, FXGLShape::ID_SHADEOFF,
|
335
333
|
BUTTON_AUTOGRAY|FRAME_THICK|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT)
|
@@ -340,14 +338,14 @@ class GLViewWindow < FXMainWindow
|
|
340
338
|
loadIcon("smoothlight"), @mdiclient, FXGLShape::ID_SHADESMOOTH,
|
341
339
|
BUTTON_AUTOGRAY|FRAME_THICK|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT)
|
342
340
|
FXFrame.new(toolbar, (LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|
|
343
|
-
LAYOUT_FIX_HEIGHT),
|
341
|
+
LAYOUT_FIX_HEIGHT), :width => 8, :height => 20)
|
344
342
|
FXToggleButton.new(toolbar, "\tToggle Light\tToggle light source.", nil,
|
345
343
|
loadIcon("nolight"), loadIcon("light"), nil, 0,
|
346
344
|
FRAME_THICK|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT)
|
347
345
|
|
348
346
|
# View orientation
|
349
347
|
FXFrame.new(toolbar, (LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|
|
350
|
-
LAYOUT_FIX_HEIGHT),
|
348
|
+
LAYOUT_FIX_HEIGHT), :width => 8, :height => 20)
|
351
349
|
FXButton.new(toolbar, "\tFront View\tView objects from the front.",
|
352
350
|
loadIcon("frontview"), @mdiclient, FXGLViewer::ID_FRONT,
|
353
351
|
BUTTON_AUTOGRAY|FRAME_THICK|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT)
|
@@ -369,7 +367,7 @@ class GLViewWindow < FXMainWindow
|
|
369
367
|
|
370
368
|
# Miscellaneous buttons
|
371
369
|
FXFrame.new(toolbar, (LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|
|
372
|
-
LAYOUT_FIX_HEIGHT),
|
370
|
+
LAYOUT_FIX_HEIGHT), :width => 8, :height => 20)
|
373
371
|
FXButton.new(toolbar, nil, loadIcon("zoom"), nil, 0,
|
374
372
|
FRAME_THICK|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT)
|
375
373
|
FXButton.new(toolbar, "\tColors\tDisplay color dialog.",
|
@@ -382,7 +380,7 @@ class GLViewWindow < FXMainWindow
|
|
382
380
|
|
383
381
|
# Dangerous delete a bit on the side
|
384
382
|
FXFrame.new(toolbar, (LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|
|
385
|
-
LAYOUT_FIX_HEIGHT),
|
383
|
+
LAYOUT_FIX_HEIGHT), :width => 10, :height => 20)
|
386
384
|
FXButton.new(toolbar, "\tDelete\tDelete the selected object.",
|
387
385
|
loadIcon("kill"), @mdiclient, FXGLViewer::ID_DELETE_SEL,
|
388
386
|
BUTTON_AUTOGRAY|FRAME_THICK|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT)
|