libguib 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/libGUIb16.rb ADDED
@@ -0,0 +1,1613 @@
1
+ # libGUIb: Copyright (c) by Meinrad Recheis aka Henon, 2006
2
+ # THIS SOFTWARE IS PROVIDED IN THE HOPE THAT IT WILL BE USEFUL
3
+ # WITHOUT ANY IMPLIED WARRANTY OR FITNESS FOR ANY PURPOSE.
4
+ require "fox16"
5
+ def rel_path(a, b)
6
+ raise TypeError unless a.is_a?(String) && b.is_a?(String)
7
+ a.tr!("\\", "/")
8
+ b.tr!("\\", "/")
9
+ a = a.split("/")
10
+ b = b.split("/")
11
+ i = 0
12
+ while (a[i] == b[i]) && (i < a.size)
13
+ i += 1
14
+ end
15
+ "../" * (a.size - i) + b[i..].join("/")
16
+ end
17
+
18
+ module FX
19
+ class App < Fox::FXApp
20
+ def initialize a = "", b = ""
21
+ super
22
+ @created = false
23
+ $app = $fxapp = self
24
+ end
25
+
26
+ def create(*args)
27
+ super
28
+ @created = true
29
+ end
30
+
31
+ def created?
32
+ @created
33
+ end
34
+ end
35
+ end # FX
36
+
37
+ module MiddleBtn
38
+ def handleMMB_Events
39
+ FXMAPFUNC(Fox::SEL_MIDDLEBUTTONPRESS, 0, :onMiddleBtnPress)
40
+ FXMAPFUNC(Fox::SEL_MIDDLEBUTTONRELEASE, 0, :onMiddleBtnRelease)
41
+ end
42
+
43
+ def onMiddleBtnPress(sender, sel, evt)
44
+ if enabled?
45
+ if !target.nil? && (target.handle(self, MKUINT(selector, Fox::SEL_MIDDLEBUTTONPRESS), evt) != 0)
46
+ return 1
47
+ end
48
+ end
49
+ 0
50
+ end
51
+
52
+ def onMiddleBtnRelease(sender, sel, evt)
53
+ if enabled?
54
+ if !target.nil? && (target.handle(self, MKUINT(selector, Fox::SEL_MIDDLEBUTTONRELEASE), evt) != 0)
55
+ return 1
56
+ end
57
+ end
58
+ 0
59
+ end
60
+ end
61
+
62
+ module RightBtn
63
+ def handleRMB_Events
64
+ FXMAPFUNC(Fox::SEL_MIDDLEBUTTONPRESS, 0, :onMiddleBtnPress)
65
+ FXMAPFUNC(Fox::SEL_MIDDLEBUTTONRELEASE, 0, :onMiddleBtnRelease)
66
+ end
67
+
68
+ def onRightBtnPress(sender, sel, evt)
69
+ if enabled?
70
+ if !target.nil? && (target.handle(self, MKUINT(selector, Fox::SEL_RIGHTBUTTONPRESS), evt) != 0)
71
+ return 1
72
+ end
73
+ end
74
+ 0
75
+ end
76
+
77
+ def onRightBtnRelease(sender, sel, evt)
78
+ if enabled?
79
+ if !target.nil? && (target.handle(self, MKUINT(selector, Fox::SEL_RIGHTBUTTONRELEASE), evt) != 0)
80
+ return 1
81
+ end
82
+ end
83
+ 0
84
+ end
85
+ end
86
+
87
+ def loadImageToString filename
88
+ data = nil
89
+ File.open(filename, "rb") { |f| data = f.read }
90
+ data.unpack1("h#{data.size * 2}")
91
+ end
92
+
93
+ def loadImageFromString s, icon_class = Fox::FXPNGIcon
94
+ raise TypeError unless $fxapp
95
+ imgdata = [s].pack("h#{s.size * 2}")
96
+ img = icon_class.new($fxapp, imgdata, Fox::IMAGE_KEEP | Fox::IMAGE_SHMI | Fox::IMAGE_SHMP)
97
+ img.create
98
+ img
99
+ end
100
+
101
+ def load_dummy
102
+ raise TypeError unless $fxapp
103
+ imgdata = "9805e474d0a0a1a0000000d0948444250000000100000001803000000082d2f035000000a247548547342756164796f6e6024596d65600d4f60293026456260223030343021363a33363a3133302b2031303037c63ded4000000704794d454704d2090f0627041559b9c00000090078495370000b0210000b021102ddde7cf000000407614d41400001bf8b0cf16500000003305c44554000000ffefeffff0f0ffc1c1ffcbcbff7878ff5b5bffc5c5ff7979ff9292ffadadff2f2fff7171ff4747ffb4b4ff6e6eff8383bfe98b0d000000104725e43500046e8d66000000b59444144587ad58ec1ee008028040069333b223d7ff7adec6a39c5b57f38d8f406a3992ea61d0508294b382bda9d373840c595953630f0c1c930ece73e940ee8506f8dc0446f14600fddfa260877711b0c50971c4f5ff898f7819b1678020e2a25402a2000000009454e444ea240628"
104
+ imgdata = [imgdata].pack("h#{imgdata.size * 2}")
105
+ $dummy_img = img = Fox::FXPNGIcon.new($fxapp, imgdata, Fox::IMAGE_KEEP | Fox::IMAGE_SHMI | Fox::IMAGE_SHMP)
106
+ img.create
107
+ img
108
+ end
109
+
110
+ def hasExtension(filename, ext)
111
+ File.basename(filename, ext) != File.basename(filename)
112
+ end
113
+
114
+ def loadImage(file)
115
+ img = load_dummy unless $dummy_img
116
+ unless File.exist? file
117
+ return img
118
+ end
119
+ begin
120
+ opts = Fox::IMAGE_KEEP | Fox::IMAGE_SHMI | Fox::IMAGE_SHMP
121
+ if hasExtension(file, ".gif")
122
+ img = Fox::FXGIFIcon.new($fxapp, nil, opts)
123
+ elsif hasExtension(file, ".bmp")
124
+ img = Fox::FXBMPIcon.new($fxapp, nil, opts)
125
+ elsif hasExtension(file, ".xpm")
126
+ img = Fox::FXXPMIcon.new($fxapp, nil, opts)
127
+ elsif hasExtension(file, ".png")
128
+ img = Fox::FXPNGIcon.new($fxapp, nil, opts)
129
+ elsif hasExtension(file, ".jpg")
130
+ img = Fox::FXJPGIcon.new($fxapp, nil, opts)
131
+ elsif hasExtension(file, ".pcx")
132
+ img = Fox::FXPCXIcon.new($fxapp, nil, opts)
133
+ elsif hasExtension(file, ".tif")
134
+ img = Fox::FXTIFIcon.new($fxapp, nil, opts)
135
+ elsif hasExtension(file, ".tga")
136
+ img = Fox::FXTGAIcon.new($fxapp, nil, opts)
137
+ elsif hasExtension(file, ".ico")
138
+ img = Fox::FXICOIcon.new($fxapp, nil, opts)
139
+ end
140
+ unless img
141
+ puts("Unsupported image type: #{file}")
142
+ return img
143
+ end
144
+ Fox::FXFileStream.open(file, Fox::FXStreamLoad) { |stream| img.loadPixels(stream) }
145
+ img.filename = file
146
+ img.create
147
+ rescue Exception
148
+ puts "load Image: #{$!}"
149
+ end
150
+ img
151
+ end
152
+
153
+ module FX
154
+ class Icon
155
+ def initialize filename
156
+ if filename
157
+ @filename = filename
158
+ @img = loadImage(filename)
159
+ end
160
+ end
161
+ attr_accessor :img
162
+ def to_s
163
+ @filename
164
+ end
165
+
166
+ def self.LoadFromString s, icon_class = Fox::FXPNGIcon
167
+ icon = Icon.new nil
168
+ icon.img = loadImageFromString s, icon_class
169
+ icon
170
+ end
171
+ end
172
+
173
+ class Color
174
+ attr_accessor :r, :g, :b, :a
175
+ def initialize r = 0, g = 0, b = 0, a = nil
176
+ @r, @g, @b, @a = r, g, b, a
177
+ end
178
+
179
+ def to_FXColor
180
+ @a ? Fox::FXRGBA(@r, @g, @b, @a) : Fox::FXRGB(@r, @g, @b)
181
+ end
182
+
183
+ def from_FXColor c
184
+ @r = Fox::FXREDVAL(c)
185
+ @g = Fox::FXGREENVAL(c)
186
+ @b = Fox::FXBLUEVAL(c)
187
+ @a = Fox::FXALPHAVAL(c)
188
+ self
189
+ end
190
+
191
+ def from_name(name)
192
+ from_FXColor(Fox.fxcolorfromname(name))
193
+ self
194
+ end
195
+
196
+ def serialize
197
+ Fox.fxencodeColorData(to_FXColor)
198
+ end
199
+
200
+ def deserialize(data)
201
+ from_FXColor(Fox.fxdecodeColorData(data))
202
+ self
203
+ end
204
+
205
+ def to_s
206
+ (@a ? [@r, @g, @b, @a] : [@r, @g, @b]).join(", ")
207
+ end
208
+
209
+ def from_s s
210
+ s = "0, 0, 0, 0" if s.size < 5
211
+ @r, @g, @b, @a = s.split(",").collect { |c| c.to_i }
212
+ self
213
+ end
214
+ end
215
+
216
+ class Font
217
+ def initialize
218
+ @fd = Fox::FXFontDesc.new
219
+ end
220
+ attr_accessor :fd
221
+ def to_s
222
+ @fd.to_s
223
+ end
224
+
225
+ def from_s s
226
+ @fd.from_s s
227
+ self
228
+ end
229
+
230
+ def to_FXFont
231
+ f = Fox::FXFont.new $fxapp, @fd
232
+ f.create
233
+ f
234
+ end
235
+
236
+ def from_FXFont f
237
+ @fd = f.fontDesc
238
+ self
239
+ end
240
+ end
241
+ end # module
242
+
243
+ class Fox::FXIcon
244
+ attr_accessor :filename
245
+ def to_s
246
+ filename || ""
247
+ end
248
+ end
249
+
250
+ class Fox::FXFontDesc
251
+ def to_s
252
+ [face,
253
+ size,
254
+ weight,
255
+ slant,
256
+ encoding,
257
+ setwidth,
258
+ flags].join("|")
259
+ end
260
+
261
+ def from_s(s)
262
+ a = s.split("|")
263
+ self.face = a[0]
264
+ self.size = a[1].to_i
265
+ self.weight = a[2].to_i
266
+ self.slant = a[3].to_i
267
+ self.encoding = a[4].to_i
268
+ self.setwidth = a[5].to_i
269
+ self.flags = a[6].to_i
270
+ self
271
+ end
272
+
273
+ def init fd
274
+ if fd.is_a? Fox::FXFontDesc
275
+ self.face = fd.face
276
+ self.size = fd.size
277
+ self.weight = fd.weight
278
+ self.slant = fd.slant
279
+ self.encoding = fd.encoding
280
+ self.setwidth = fd.setwidth
281
+ self.flags = fd.flags
282
+ elsif fd.is_a? String
283
+ from_s fd
284
+ end
285
+ end
286
+ end
287
+
288
+ class Fox::FXFont
289
+ def to_s
290
+ fontDesc.to_s
291
+ end
292
+ end
293
+
294
+ class Fox::FXIcon
295
+ attr_accessor :filename
296
+ def to_s
297
+ filename || ""
298
+ end
299
+ end
300
+
301
+ class Module
302
+ def __sends__ *args
303
+ args.each { |arg|
304
+ class_eval <<-CEEND, __FILE__, __LINE__ + 1
305
+ def on_#{arg}(&callback)
306
+ @#{arg}_observers ||= {}
307
+ @#{arg}_observers[caller[0]]=callback
308
+ return caller[0]
309
+ end
310
+ def del_#{arg}(id)
311
+ @#{arg}_observers ||= {}
312
+ return @#{arg}_observers.delete( id)
313
+ end
314
+ private
315
+ def #{arg} *the_args
316
+ @#{arg}_observers ||= {}
317
+ @#{arg}_observers.each { |caller, cb|
318
+ cb.call *the_args
319
+ }
320
+ end
321
+ CEEND
322
+ }
323
+ end
324
+ end
325
+
326
+ module FX
327
+ class RadioGroup
328
+ __sends__ :event_selected
329
+ def initialize
330
+ @radio_widgets = []
331
+ @selected = nil
332
+ end
333
+ attr_reader :radio_widgets
334
+ def add_radio(radio_widget, &block)
335
+ @radio_widgets << radio_widget
336
+ radio_widget.connect(Fox::SEL_COMMAND) {
337
+ select(radio_widget)
338
+ yield if block
339
+ }
340
+ end
341
+ alias_method :<<, :add_radio
342
+ def select radio_widget
343
+ @selected = radio_widget
344
+ event_selected @selected
345
+ @radio_widgets.each do |w|
346
+ w.state = (w == @selected) # only the selected widget is checked.
347
+ rescue Exception
348
+ puts $!
349
+ end
350
+ end
351
+
352
+ attr_reader :selected
353
+ end
354
+ end # fx
355
+ if Fox.fxrubyversion == "1.4.4"
356
+ class Fox::FXMenuCaption
357
+ def text= text
358
+ @text = text
359
+ setText(text)
360
+ end
361
+
362
+ attr_reader :text
363
+ end
364
+ end
365
+ module FX
366
+ module CheckState
367
+ def state=(x)
368
+ setCheck(x ? Fox::TRUE : Fox::FALSE)
369
+ end
370
+
371
+ def state
372
+ getCheckState == Fox::TRUE
373
+ end
374
+ end
375
+
376
+ module RangeAccessor
377
+ def range= val
378
+ val = val.last..val.first if val.last < val.first
379
+ setRange val
380
+ end
381
+
382
+ def range
383
+ getRange
384
+ end
385
+ end
386
+
387
+ module RadioMutexInterface
388
+ def init_radio_mutex
389
+ @radioGroup = RadioGroup.new
390
+ @radioGroup.on_event_selected { |r| event_selected(r) }
391
+ end
392
+
393
+ def add_radio_option widget
394
+ @radioGroup << widget
395
+ end
396
+
397
+ def selected_radio
398
+ @radioGroup.selected
399
+ end
400
+ end
401
+
402
+ class ArrowButton < Fox::FXArrowButton
403
+ def initialize(p, opts = 0)
404
+ super(p, nil, 0, opts | Fox::ARROW_NORMAL)
405
+ end
406
+ end
407
+
408
+ class Button < Fox::FXButton
409
+ include Responder
410
+ include RightBtn
411
+ include MiddleBtn
412
+ def initialize(p, opts = 0)
413
+ super(p, "Button", nil, nil, 0, Fox::BUTTON_NORMAL | opts)
414
+ handleMMB_Events
415
+ handleRMB_Events
416
+ end
417
+
418
+ def state=(x)
419
+ if x == true
420
+ setState(Fox::STATE_DOWN)
421
+ elsif x == false
422
+ setState(Fox::STATE_UP)
423
+ elsif x.instance_of?(Integer)
424
+ setState(x)
425
+ end
426
+ end
427
+
428
+ def state
429
+ if getState == Fox::STATE_DOWN then return true
430
+ elsif getState == Fox::STATE_CHECKED then return true
431
+ end
432
+ false
433
+ end
434
+ alias_method :buttonButtonStyle=, :buttonStyle=
435
+ alias_method :buttonButtonStyle, :buttonStyle
436
+ end
437
+
438
+ class Canvas < Fox::FXCanvas
439
+ def initialize(p, opts = 0)
440
+ super(p)
441
+ end
442
+ end
443
+
444
+ class CheckButton < Fox::FXCheckButton
445
+ def initialize(p, opts = 0)
446
+ super(p, "CheckButton")
447
+ end
448
+ include CheckState
449
+ end
450
+
451
+ class ComboBox < Fox::FXComboBox
452
+ def initialize(p, opts = 0)
453
+ super(p, 10, nil, 0, opts | Fox::FRAME_SUNKEN)
454
+ end
455
+
456
+ def comboItems= string
457
+ c = currentItem
458
+ clearItems
459
+ array = string.split(/\r?\n/)
460
+ array.each { |s|
461
+ appendItem s
462
+ }
463
+ self.numVisible = array.size
464
+ begin
465
+ self.currentItem = c
466
+ rescue Exception
467
+ end
468
+ end
469
+
470
+ def comboItems
471
+ array = []
472
+ each { |text, d|
473
+ array << text
474
+ }
475
+ array.join("\n")
476
+ end
477
+
478
+ def auto_resize
479
+ size = 0
480
+ each { |text, d|
481
+ size = text.size if size < text.size
482
+ }
483
+ self.numColumns = size
484
+ self.numVisible = numItems
485
+ end
486
+ end
487
+
488
+ class Dial < Fox::FXDial
489
+ def initialize(p, opts = 0)
490
+ super(p, nil, 0, opts | Fox::DIAL_NORMAL)
491
+ end
492
+ end
493
+
494
+ class DialogBox < Fox::FXDialogBox
495
+ def initialize(p, opts = 0)
496
+ super(p, "title", Fox::DECOR_ALL)
497
+ pad(0, 0, 0, 0)
498
+ handleMMB_Events
499
+ end
500
+ include Responder
501
+ include MiddleBtn
502
+ end
503
+
504
+ class DirBox < Fox::FXDirBox
505
+ def initialize(p, opts = 0)
506
+ super(p, nil, 0, opts | Fox::FRAME_SUNKEN | Fox::TREELISTBOX_NORMAL)
507
+ end
508
+ end
509
+
510
+ class DirList < Fox::FXDirList
511
+ def initialize(p, opts = 0)
512
+ super(p, nil, 0, opts)
513
+ end
514
+ end
515
+
516
+ class DriveBox < Fox::FXDriveBox
517
+ def initialize(p, opts = 0)
518
+ super(p, nil, 0, opts | Fox::FRAME_SUNKEN | Fox::LISTBOX_NORMAL)
519
+ end
520
+ end
521
+
522
+ class FileList < Fox::FXFileList
523
+ def initialize(p, opts = 0)
524
+ super(p, nil, 0, opts | Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y)
525
+ end
526
+ end
527
+
528
+ class Header < Fox::FXHeader
529
+ def initialize(p, opts = 0)
530
+ super(p, nil, 0, opts | Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y | Fox::HEADER_NORMAL)
531
+ end
532
+ end
533
+
534
+ class GroupBox < Fox::FXGroupBox
535
+ def initialize(p, opts = 0)
536
+ super(p, "GroupBox", opts | Fox::FRAME_GROOVE, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4)
537
+ end
538
+ end
539
+
540
+ class HorizontalFrame < Fox::FXHorizontalFrame
541
+ def initialize(p, opts = 0)
542
+ super(p, opts | Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
543
+ end
544
+ end
545
+
546
+ class HorizontalSeparator < Fox::FXHorizontalSeparator
547
+ def initialize(p, opts = Fox::SEPARATOR_GROOVE)
548
+ super(p, Fox::LAYOUT_FILL_X | opts)
549
+ end
550
+ end
551
+
552
+ class IconList < Fox::FXIconList
553
+ def initialize(p, opts = 0)
554
+ super(p, nil, 0, opts | Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y | Fox::HEADER_NORMAL)
555
+ end
556
+ alias_method :iconListStyle=, :listStyle=
557
+ alias_method :iconListStyle, :listStyle
558
+ def addItems names, imagefiles
559
+ names.size.times do |i|
560
+ img = loadImage(imagefiles[i])
561
+ appendItem(names[i], nil, img)
562
+ end
563
+ end
564
+ end
565
+
566
+ class Label < Fox::FXLabel
567
+ def initialize(p, opts = 0)
568
+ super(p, "Label")
569
+ end
570
+ end
571
+
572
+ class List < Fox::FXList
573
+ def initialize(p, opts = 0)
574
+ super(p, nil, 0, opts | Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y | Fox::LIST_NORMAL)
575
+ end
576
+ alias_method :listListStyle=, :listStyle=
577
+ alias_method :listListStyle, :listStyle
578
+ end
579
+
580
+ class ListBox < Fox::FXListBox
581
+ def initialize(p, opts = 0)
582
+ super(p, nil, 0, opts | Fox::FRAME_SUNKEN | Fox::LISTBOX_NORMAL)
583
+ end
584
+ end
585
+
586
+ class MainWindow < Fox::FXMainWindow
587
+ def initialize(p, opts = 0)
588
+ p = p.app if p.is_a? Fox::FXId
589
+ super(p, "MainWindow", nil, nil, Fox::DECOR_ALL)
590
+ end
591
+ end
592
+
593
+ class Matrix < Fox::FXMatrix
594
+ def initialize(p, opts = 0)
595
+ super(p, 1, opts | Fox::MATRIX_BY_ROWS | Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y)
596
+ end
597
+
598
+ def matrixStyle=code
599
+ super
600
+ self.numColumns = @cols
601
+ self.numRows = @rows
602
+ end
603
+
604
+ def numColumns=(int)
605
+ super(@cols = dim_check(int))
606
+ end
607
+
608
+ def numRows=(int)
609
+ super(@rows = dim_check(int))
610
+ end
611
+
612
+ def dim_check int
613
+ return 1 unless int.is_a?(Numeric)
614
+ return 1 if int < 1
615
+ int
616
+ end
617
+ end
618
+
619
+ class MDIClient < Fox::FXMDIClient
620
+ def initialize(p, opts = 0)
621
+ super(p, opts | Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y)
622
+ end
623
+ end
624
+
625
+ class MenuButton < Fox::FXMenuButton
626
+ include Responder
627
+ include MiddleBtn
628
+ def initialize(p, opts = 0)
629
+ super(p, "MenuButton", nil, nil, opts | Fox::JUSTIFY_NORMAL | Fox::ICON_BEFORE_TEXT | Fox::MENUBUTTON_DOWN)
630
+ handleMMB_Events
631
+ end
632
+ alias_method :menuButtonStyle=, :buttonStyle=
633
+ alias_method :menuButtonStyle, :buttonStyle
634
+ end
635
+
636
+ class MenuCaption < Fox::FXMenuCaption
637
+ include Responder
638
+ include MiddleBtn
639
+ def initialize(p, opts = 0)
640
+ @text = text if Fox.fxrubyversion == "1.4.4"
641
+ super(p, "MenuCaption")
642
+ handleMMB_Events
643
+ end
644
+ end
645
+
646
+ class MenuCascade < Fox::FXMenuCascade
647
+ include Responder
648
+ include MiddleBtn
649
+ def initialize(p, text = "MenuCascade")
650
+ @text = text if Fox.fxrubyversion == "1.4.4"
651
+ super
652
+ handleMMB_Events
653
+ end
654
+ end
655
+
656
+ class MenuCheck < Fox::FXMenuCheck
657
+ include Responder
658
+ include MiddleBtn
659
+ include CheckState
660
+ def initialize(p, text = "MenuCheck")
661
+ @text = text if Fox.fxrubyversion == "1.4.4"
662
+ super
663
+ end
664
+ end
665
+
666
+ class MenuCommand < Fox::FXMenuCommand
667
+ include Responder
668
+ include MiddleBtn
669
+ def initialize(p, text = "MenuCommand")
670
+ @text = text if Fox.fxrubyversion == "1.4.4"
671
+ super
672
+ handleMMB_Events
673
+ end
674
+ end
675
+
676
+ class MenuPane < Fox::FXMenuPane
677
+ include Responder
678
+ include MiddleBtn
679
+ include RadioMutexInterface
680
+ def initialize(p, opts = 0)
681
+ init_radio_mutex
682
+ super(p)
683
+ p.menu = self
684
+ handleMMB_Events
685
+ end
686
+ end
687
+
688
+ class MenuRadio < Fox::FXMenuRadio
689
+ include Responder
690
+ include MiddleBtn
691
+ include CheckState
692
+ def initialize(p, text = "MenuRadio")
693
+ @text = text if Fox.fxrubyversion == "1.4.4"
694
+ super
695
+ parent.add_radio_option self if parent.respond_to? :add_radio_option
696
+ end
697
+ end
698
+
699
+ class MenuTitle < Fox::FXMenuTitle
700
+ include Responder
701
+ include MiddleBtn
702
+ def initialize(p, text = "MenuTitle")
703
+ @text = text if Fox.fxrubyversion == "1.4.4"
704
+ super
705
+ handleMMB_Events
706
+ end
707
+ end
708
+
709
+ class MenuBar < Fox::FXMenuBar
710
+ def initialize(p, opts = 0)
711
+ super(p, opts | Fox::LAYOUT_FILL_X)
712
+ handleMMB_Events
713
+ end
714
+ include Responder
715
+ include MiddleBtn
716
+ end
717
+
718
+ class MenuSeparator < Fox::FXMenuSeparator
719
+ def initialize(p, opts = 0)
720
+ super
721
+ handleMMB_Events
722
+ end
723
+ include Responder
724
+ include MiddleBtn
725
+ end
726
+
727
+ class Option < Fox::FXOption
728
+ def initialize(p, opts = 0)
729
+ super(p, "Option", nil, nil, 0, opts | Fox::JUSTIFY_NORMAL | Fox::ICON_BEFORE_TEXT)
730
+ handleMMB_Events
731
+ end
732
+ include Responder
733
+ include MiddleBtn
734
+ end
735
+
736
+ class OptionMenu < Fox::FXOptionMenu
737
+ def initialize(p, opts = 0)
738
+ super(p, nil, opts | Fox::JUSTIFY_NORMAL | Fox::ICON_BEFORE_TEXT)
739
+ handleMMB_Events
740
+ end
741
+ include Responder
742
+ include MiddleBtn
743
+ end
744
+
745
+ class Packer < Fox::FXPacker
746
+ def initialize(p, opts = 0)
747
+ super(p, opts | Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0)
748
+ end
749
+ end
750
+
751
+ class Popup < Fox::FXPopup
752
+ def initialize(p, opts = 0)
753
+ init_radio_mutex
754
+ super(p, opts | Fox::POPUP_VERTICAL | Fox::FRAME_RAISED | Fox::FRAME_THICK)
755
+ handleMMB_Events
756
+ end
757
+ include Responder
758
+ include MiddleBtn
759
+ include RadioMutexInterface
760
+ end
761
+
762
+ class ProgressBar < Fox::FXProgressBar
763
+ def initialize(p, opts = 0)
764
+ super(p, nil, 0, opts | Fox::LAYOUT_FILL_X)
765
+ self.displayText = Fox::TRUE
766
+ end
767
+
768
+ def displayText=bool
769
+ @displaysText = bool
770
+ bool ? showNumber : hideNumber
771
+ end
772
+
773
+ def displayText
774
+ @displaysText = Fox::FALSE if @displaysText.nil?
775
+ @displaysText
776
+ end
777
+ end
778
+
779
+ class RadioButton < Fox::FXRadioButton
780
+ def initialize(p, opts = 0)
781
+ super(p, "RadioButton", nil, 0, opts | Fox::ICON_BEFORE_TEXT)
782
+ parent.add_radio_option self if parent.respond_to? :add_radio_option
783
+ end
784
+ include CheckState
785
+ end
786
+
787
+ class ScrollArea < Fox::FXScrollArea
788
+ def initialize(p, opts = 0)
789
+ super(p)
790
+ self.layoutHints = Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y
791
+ end
792
+ end
793
+
794
+ class ScrollBar < Fox::FXScrollBar
795
+ def initialize(p, opts = 0)
796
+ super(p)
797
+ end
798
+ alias_method :contentSize, :range
799
+ alias_method :contentSize=, :range=
800
+ end
801
+
802
+ class ScrollWindow < Fox::FXScrollWindow
803
+ def initialize(p, opts = 0)
804
+ super(p)
805
+ self.layoutHints = Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y
806
+ end
807
+ end
808
+
809
+ class Shutter < Fox::FXShutter
810
+ def initialize(p, opts = 0)
811
+ super(p, nil, 0, opts | Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y | Fox::LAYOUT_TOP | Fox::LAYOUT_LEFT | Fox::FRAME_SUNKEN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
812
+ handleMMB_Events
813
+ end
814
+ include Responder
815
+ include MiddleBtn
816
+ end
817
+
818
+ class ShutterItem < Fox::FXShutterItem
819
+ def initialize(p, opts = 0)
820
+ super(p, "ShutterItem", nil, opts | Fox::LAYOUT_FILL_X | Fox::LAYOUT_TOP | Fox::LAYOUT_LEFT, 0, 0, 0, 0, 2, 2, 4, 4, 4, 4)
821
+ button.padBottom = 3
822
+ button.padTop = 3
823
+ button.padLeft = 5
824
+ button.padRight = 5
825
+ handleMMB_Events
826
+ end
827
+
828
+ def text=(text)
829
+ button.text = text
830
+ end
831
+
832
+ def text
833
+ button.text
834
+ end
835
+ include Responder
836
+ include MiddleBtn
837
+ end
838
+
839
+ class Slider < Fox::FXSlider
840
+ def initialize(p, opts = 0)
841
+ super(p, nil, 0, opts | Fox::SLIDER_NORMAL | Fox::LAYOUT_FILL_X)
842
+ end
843
+ include RangeAccessor
844
+ end
845
+
846
+ class Spinner < Fox::FXSpinner
847
+ def initialize(p, opts = 0)
848
+ super(p, 3, nil, 0, opts | Fox::FRAME_SUNKEN)
849
+ end
850
+ include RangeAccessor
851
+ end
852
+
853
+ class Splitter < Fox::FXSplitter
854
+ def initialize(p, opts = 0)
855
+ super(p)
856
+ self.layoutHints = Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y
857
+ end
858
+ end
859
+
860
+ class Switcher < Fox::FXSwitcher
861
+ def initialize(p, opts = 0)
862
+ super
863
+ end
864
+
865
+ def current=(*args)
866
+ super
867
+ rescue Exception
868
+ end
869
+ end
870
+
871
+ class StatusBar < Fox::FXStatusBar
872
+ def initialize(p, opts = 0)
873
+ super(p, opts | Fox::LAYOUT_FILL_X)
874
+ end
875
+ end
876
+
877
+ class StatusLine < Fox::FXStatusLine
878
+ def initialize(p, opts = 0)
879
+ super(p)
880
+ end
881
+ end
882
+
883
+ module TabBarInterface
884
+ attr_reader :tabs
885
+ def create_tab(text = "TabItem")
886
+ @tabs ||= []
887
+ TabItem.new(self) { |i|
888
+ @tabs << i
889
+ i.text = text
890
+ }
891
+ end
892
+
893
+ def remove_tab tab
894
+ @tabs.delete tab
895
+ removeChild(tab)
896
+ end
897
+ end
898
+
899
+ class TabBar < Fox::FXTabBar
900
+ include TabBarInterface
901
+ def initialize(p, opts = 0)
902
+ super(p, nil, 0, opts | Fox::LAYOUT_FILL_X)
903
+ end
904
+ end
905
+
906
+ class TabBook < Fox::FXTabBook
907
+ include TabBarInterface
908
+ def initialize(p, opts = 0)
909
+ super(p, nil, 0, opts | Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y)
910
+ end
911
+ end
912
+
913
+ class TabItem < Fox::FXTabItem
914
+ def initialize(p, opts = 0)
915
+ super(p, "TabItem")
916
+ end
917
+
918
+ def index
919
+ parent.tabs.index(self)
920
+ end
921
+ end
922
+
923
+ class Text < Fox::FXText
924
+ def initialize(p, opts = 0)
925
+ super(p, nil, 0, opts | Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y)
926
+ text = "Text"
927
+ end
928
+ alias_method :textTextStyle=, :textStyle=
929
+ alias_method :textTextStyle, :textStyle
930
+ end
931
+
932
+ class TextField < Fox::FXTextField
933
+ def initialize(p, opts = 0)
934
+ super(p, 10, nil, 0, opts | Fox::FRAME_SUNKEN)
935
+ text = "TextField"
936
+ end
937
+
938
+ def text=(*args)
939
+ args.collect! { |a| a.to_s }
940
+ super
941
+ end
942
+ alias_method :textFieldTextStyle=, :textStyle=
943
+ alias_method :textFieldTextStyle, :textStyle
944
+ end
945
+
946
+ class ToggleButton < Fox::FXToggleButton
947
+ def initialize p, opts = 0
948
+ super(p, "Toggle", "Button", nil, nil, nil, 0, opts | Fox::TOGGLEBUTTON_KEEPSTATE)
949
+ end
950
+
951
+ def altImg= filename
952
+ if filename.size > 0
953
+ setAltIcon loadImage(filename)
954
+ @alt_icon_filename = filename
955
+ end
956
+ end
957
+
958
+ def altImg
959
+ @alt_icon_filename.to_s
960
+ end
961
+ end
962
+
963
+ class ToolBar < Fox::FXToolBar
964
+ def initialize(p, opts = 0)
965
+ super(p, opts | Fox::LAYOUT_FILL_X)
966
+ end
967
+ end
968
+
969
+ class TreeList < Fox::FXTreeList
970
+ def initialize(p, opts = 0)
971
+ super(p, nil, 0, opts | Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y)
972
+ end
973
+ alias_method :treeListStyle=, :listStyle=
974
+ alias_method :treeListStyle, :listStyle
975
+ def initialize_language_ids
976
+ each { |ti|
977
+ ti.initialize_language_ids
978
+ }
979
+ end
980
+ end
981
+
982
+ class VerticalFrame < Fox::FXVerticalFrame
983
+ def initialize(p, opts = 0)
984
+ super(p, opts | Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
985
+ end
986
+ end
987
+
988
+ class VerticalSeparator < Fox::FXVerticalSeparator
989
+ def initialize(p, opts = Fox::SEPARATOR_GROOVE)
990
+ super(p, Fox::LAYOUT_FILL_Y | opts)
991
+ end
992
+ end
993
+
994
+ class WidgetTable < GroupBox
995
+ def initialize(p, opts = 0)
996
+ @c = {}
997
+ @r = []
998
+ @nc = 0
999
+ super
1000
+ self.text = ""
1001
+ self.vSpacing = 0
1002
+ self.frameStyle = FRAME_NONE
1003
+ pad 2, 2, 2, 2
1004
+ end
1005
+
1006
+ def rows
1007
+ @r.size
1008
+ end
1009
+
1010
+ def cols
1011
+ @nc
1012
+ end
1013
+
1014
+ def size=(w, h)
1015
+ end
1016
+
1017
+ def add_col
1018
+ @nc += 1
1019
+ @r.each_with_index { |r, y|
1020
+ VerticalFrame.new(r) { |f|
1021
+ @c[[@nc - 1, y]] = f
1022
+ f.pad 0, 0, 0, 0
1023
+ }
1024
+ }
1025
+ end
1026
+
1027
+ def add_row
1028
+ HorizontalFrame.new(self) { |h|
1029
+ h.frameStyle = FRAME_NONE
1030
+ h.pad 0, 0, 0, 0
1031
+ h.layoutHints = Fox::LAYOUT_FILL_X # |Fox::LAYOUT_FILL_Y
1032
+ @r << h
1033
+ @nc.times { |x|
1034
+ VerticalFrame.new(h) { |f|
1035
+ @c[[x, rows - 1]] = f
1036
+ f.pad 0, 0, 0, 0
1037
+ }
1038
+ }
1039
+ }
1040
+ end
1041
+
1042
+ def cell(x, y)
1043
+ @c[[x, y]]
1044
+ end
1045
+ end
1046
+
1047
+ class RadioMutex < FX::VerticalFrame
1048
+ __sends__ :event_selected
1049
+ def initialize(p)
1050
+ init_radio_mutex
1051
+ super
1052
+ self.layoutHints = 0
1053
+ end
1054
+ include RadioMutexInterface
1055
+ end
1056
+ Menubar = MenuBar
1057
+ Toolbar = ToolBar
1058
+ Scrollbar = ScrollBar
1059
+ Statusbar = StatusBar
1060
+ Statusline = StatusLine
1061
+ end # module FX
1062
+
1063
+ class Fox::FXId
1064
+ attr_accessor :wdg_name # a user-given name to identify the wdg
1065
+ def app
1066
+ $fxapp
1067
+ end
1068
+ end
1069
+
1070
+ class Fox::FXWindow
1071
+ def enabled=bool
1072
+ bool ? enable : disable
1073
+ end
1074
+ alias_method :enabled, :enabled?
1075
+ def visible=bool
1076
+ bool ? show : hide
1077
+ end
1078
+ alias_method :visible?, :shown
1079
+ alias_method :visible, :shown
1080
+ def pad(*args)
1081
+ args[0] ? self.padLeft = args[0] : nil
1082
+ args[1] ? self.padRight = args[1] : nil
1083
+ args[2] ? self.padTop = args[2] : nil
1084
+ args[3] ? self.padBottom = args[3] : nil
1085
+ end
1086
+
1087
+ def padding
1088
+ [padLeft, padRight, padTop, padBottom]
1089
+ end
1090
+
1091
+ def recursive(&block) # {|wdg| ... }
1092
+ if block
1093
+ yield(self)
1094
+ children.each { |child| child.recursive(&block) }
1095
+ end
1096
+ end
1097
+ end
1098
+
1099
+ module ImgAccessors
1100
+ def img= filename
1101
+ raise TypeError unless filename.is_a? String
1102
+ if filename.size > 0
1103
+ setIcon loadImage(filename)
1104
+ @icon_filename = filename
1105
+ end
1106
+ end
1107
+
1108
+ def img
1109
+ @icon_filename.to_s
1110
+ end
1111
+ end
1112
+
1113
+ class Fox::FXLabel
1114
+ include ImgAccessors
1115
+ end
1116
+
1117
+ class Fox::FXMenuCaption
1118
+ include ImgAccessors
1119
+ end
1120
+
1121
+ class FileSelector
1122
+ def initialize(parent)
1123
+ construct_widget_tree(parent)
1124
+ init if respond_to? :init
1125
+ end
1126
+
1127
+ def construct_widget_tree(parent)
1128
+ @topwin =
1129
+ FX::HorizontalFrame.new(parent) { |w|
1130
+ @FileSelector = w
1131
+ w.padLeft = 0
1132
+ w.frameStyle = 0
1133
+ w.padRight = 0
1134
+ w.hSpacing = 2
1135
+ w.height = 21
1136
+ w.layoutHints = 1024
1137
+ FX::Label.new(@FileSelector) { |w|
1138
+ @label = w
1139
+ w.text = "File:"
1140
+ w.width = 24
1141
+ w.x = 0
1142
+ }
1143
+ FX::TextField.new(@FileSelector) { |w|
1144
+ @textfield = w
1145
+ w.width = 297
1146
+ w.y = 0
1147
+ w.layoutHints = 1024
1148
+ w.x = 26
1149
+ }
1150
+ FX::Button.new(@FileSelector) { |w|
1151
+ @browse = w
1152
+ w.text = "Browse..."
1153
+ w.padLeft = 4
1154
+ w.width = 59
1155
+ w.padRight = 4
1156
+ w.y = 0
1157
+ w.x = 325
1158
+ }
1159
+ }
1160
+ end
1161
+ attr_accessor :topwin,
1162
+ :FileSelector,
1163
+ :label,
1164
+ :textfield,
1165
+ :browse,
1166
+ :__foxGUIb__last__
1167
+ end
1168
+
1169
+ class FileSelector
1170
+ def init
1171
+ @title = "File Dialog"
1172
+ @relative_path = false
1173
+ @filename = ""
1174
+ @directory = Dir.getwd
1175
+ @dialog = Fox::FXFileDialog.new(@topwin, @title)
1176
+ @patterns = ["All Files (*)"]
1177
+ @currentPattern = 0
1178
+ @browse.connect(Fox::SEL_COMMAND, method(:onBrowse))
1179
+ end
1180
+ attr_accessor :directory, :patterns, :currentPattern, :title, :filename, :relative_path
1181
+ attr_accessor :onNewFilenameBlock
1182
+ def description=text
1183
+ @label.text = text
1184
+ end
1185
+
1186
+ def description
1187
+ @label.text
1188
+ end
1189
+
1190
+ def onBrowse(*args)
1191
+ @dialog.title = @title
1192
+ @dialog.directory = @directory
1193
+ @dialog.patternList = @patterns
1194
+ @currentPattern = 0 if @currentPattern >= @patterns.size
1195
+ @dialog.currentPattern = @currentPattern
1196
+ @dialog.filename = filename.to_s
1197
+ if @dialog.execute != 0
1198
+ @filename = @textfield.text = if @relative_path
1199
+ rel_path(Dir.getwd, @dialog.filename)
1200
+ else
1201
+ @dialog.filename
1202
+ end
1203
+ @onNewFilenameBlock.call if @onNewFilenameBlock.respond_to? :call
1204
+ end
1205
+ end
1206
+ end
1207
+
1208
+ class PathSelector
1209
+ def initialize(parent)
1210
+ construct_widget_tree(parent)
1211
+ init if respond_to? :init
1212
+ end
1213
+
1214
+ def construct_widget_tree(parent)
1215
+ @topwin =
1216
+ FX::HorizontalFrame.new(parent) { |w|
1217
+ @PathSelector = w
1218
+ w.padLeft = 0
1219
+ w.frameStyle = 0
1220
+ w.padRight = 0
1221
+ w.hSpacing = 2
1222
+ w.height = 21
1223
+ w.layoutHints = 1024
1224
+ FX::Label.new(@PathSelector) { |w|
1225
+ @label = w
1226
+ w.text = "Path:"
1227
+ w.width = 30
1228
+ w.x = 0
1229
+ }
1230
+ FX::TextField.new(@PathSelector) { |w|
1231
+ @textfield = w
1232
+ w.width = 291
1233
+ w.y = 0
1234
+ w.layoutHints = 1024
1235
+ w.x = 32
1236
+ }
1237
+ FX::Button.new(@PathSelector) { |w|
1238
+ @browse = w
1239
+ w.text = "Browse..."
1240
+ w.padLeft = 4
1241
+ w.width = 59
1242
+ w.padRight = 4
1243
+ w.y = 0
1244
+ w.x = 325
1245
+ }
1246
+ }
1247
+ end
1248
+ attr_accessor :topwin,
1249
+ :PathSelector,
1250
+ :label,
1251
+ :textfield,
1252
+ :browse,
1253
+ :__foxGUIb__last__
1254
+ end
1255
+ s = "PathSelector-extension.rb"
1256
+ require s if File.exist?(s)
1257
+ module FX
1258
+ class Container < FX::VerticalFrame
1259
+ attr_reader :header, :hsep
1260
+ def initialize(parent)
1261
+ super
1262
+ boxMinusPNG_Str =
1263
+ "9805e474d0a0a1a0000000d09484442500000090000000904030000010568bb25b000000704794d4" \
1264
+ "54704d50016041822c41f2b600000090078495370000b0210000b021102ddde7cf000000407614d4" \
1265
+ "1400001bf8b0cf16500000009005c44554484848ffffff0000003e75793f000000229444144587ad" \
1266
+ "3606082062011a404cc82801c0402828c024a80221c2c28288584000525c10091d50980600000000" \
1267
+ "9454e444ea240628"
1268
+ boxPlusPNG_Str =
1269
+ "9805e474d0a0a1a0000000d09484442500000090000000904030000010568bb25b000000704794d4" \
1270
+ "54704d50016041c0ef71bcab00000090078495370000b0210000b021102ddde7cf000000407614d4" \
1271
+ "1400001bf8b0cf16500000009005c44554484848ffffff0000003e75793f000000729444144587ad" \
1272
+ "3606082062011a404cc8a801c0402828c024a8022142c2802a91505119840a8000c25a100daa1682" \
1273
+ "d9000000009454e444ea240628"
1274
+ self.padLeft = 0
1275
+ self.frameStyle = 12288
1276
+ self.layoutHints = Fox::LAYOUT_FILL_X
1277
+ self.padRight = 0
1278
+ @openIcon = Icon.LoadFromString boxMinusPNG_Str
1279
+ @closedIcon = Icon.LoadFromString boxPlusPNG_Str
1280
+ FX::Label.new(self) { |w|
1281
+ @header = w
1282
+ w.layoutHints = Fox::LAYOUT_FILL_X
1283
+ w.iconPosition = Fox::ICON_BEFORE_TEXT
1284
+ w.justify = Fox::JUSTIFY_LEFT
1285
+ w.icon = @openIcon.img
1286
+ @open = true
1287
+ }
1288
+ FX::HorizontalSeparator.new(self) { |w|
1289
+ @hsep = w
1290
+ w.padLeft = 0
1291
+ w.padRight = 0
1292
+ }
1293
+ @header.connect(SEL_LEFTBUTTONPRESS) {
1294
+ if @open
1295
+ close_body
1296
+ else
1297
+ open_body
1298
+ end
1299
+ }
1300
+ end
1301
+
1302
+ def close_body
1303
+ @open = false
1304
+ @header.icon = @closedIcon.img
1305
+ children.each { |ch|
1306
+ next if ch == @header
1307
+ ch.hide
1308
+ }
1309
+ if layoutHints & LAYOUT_FILL_Y == LAYOUT_FILL_Y
1310
+ self.layoutHints -= LAYOUT_FILL_Y
1311
+ @fill_y = true
1312
+ else
1313
+ @fill_y = false
1314
+ end
1315
+ recalc
1316
+ end
1317
+
1318
+ def open_body
1319
+ @open = true
1320
+ @header.icon = @openIcon.img
1321
+ children.each { |ch|
1322
+ next if ch == @header
1323
+ ch.show
1324
+ }
1325
+ self.layoutHints |= LAYOUT_FILL_Y if @fill_y
1326
+ recalc
1327
+ end
1328
+
1329
+ def title=(text)
1330
+ @header.text = text
1331
+ end
1332
+
1333
+ def title
1334
+ @header.text
1335
+ end
1336
+ end
1337
+ end
1338
+
1339
+ module RadioGroup1
1340
+ def RadioGroup1_initialize
1341
+ @RadioGroup1_initialized = true
1342
+ @RadioGroup1_listeners ||= []
1343
+ end
1344
+
1345
+ def radio_command w
1346
+ RadioGroup1_initialize unless @RadioGroup1_initialized
1347
+ return if @selected_radio_widget == w
1348
+ @selected_radio_widget&.set_radio_state false
1349
+ @selected_radio_widget = w
1350
+ @RadioGroup1_listeners.each { |l|
1351
+ l.on_event(@selected_radio_widget)
1352
+ }
1353
+ end
1354
+ attr_accessor :selected_radio_widget, :RadioGroup1_listeners
1355
+ end
1356
+
1357
+ module RadioWidget
1358
+ def radio_initialize col = FX::Color.new(255, 255, 255)
1359
+ @radio_initialized = true
1360
+ @radioBackColor = FX::Color.new.from_FXColor(backColor)
1361
+ @radioSelectColor ||= col
1362
+ @state = false
1363
+ connect(SEL_LEFTBUTTONPRESS, method(:lmb_press))
1364
+ end
1365
+ attr_accessor :radioSelectColor, :radioSelectColor
1366
+ def set_radio_state state
1367
+ @state = state
1368
+ change_radio_selection
1369
+ end
1370
+
1371
+ def change_radio_selection
1372
+ self.backColor = @state ? @radioSelectColor.to_FXColor : @radioBackColor.to_FXColor
1373
+ end
1374
+ attr_accessor :state, :group, :lmbdown
1375
+ def lmb_press(*args)
1376
+ if @group&.respond_to?(:radio_command)
1377
+ set_radio_state true
1378
+ @group.radio_command(self)
1379
+ else
1380
+ set_radio_state(!@state)
1381
+ end
1382
+ @lmbdown = true
1383
+ 0
1384
+ end
1385
+ end
1386
+
1387
+ module FX
1388
+ class RadioMatrix < Fox::FXMatrix
1389
+ include RadioGroup1
1390
+ def initialize(p)
1391
+ super
1392
+ end
1393
+ end
1394
+
1395
+ class RadioLabel < Label
1396
+ include RadioWidget
1397
+ def initialize(p)
1398
+ super
1399
+ radio_initialize
1400
+ end
1401
+ end
1402
+ end
1403
+
1404
+ module FX
1405
+ class TableWidget < FX::VerticalFrame
1406
+ HEADER_COLOR = Fox::FXRGB(200, 200, 200)
1407
+ def initialize(*args)
1408
+ super
1409
+ @autoresize_titles = true
1410
+ Header.new(self) { |w|
1411
+ @header = w
1412
+ w.headerStyle = HEADER_HORIZONTAL | HEADER_TRACKING
1413
+ w.frameStyle = 0
1414
+ w.backColor = HEADER_COLOR
1415
+ w.connect(SEL_CONFIGURE) {
1416
+ set_title_widths
1417
+ }
1418
+ w.layoutHints = LAYOUT_FILL_X | LAYOUT_FIX_HEIGHT
1419
+ w.height = 20
1420
+ }
1421
+ FXMatrix.new(self, 1) { |w|
1422
+ @matrix = w
1423
+ }
1424
+ end
1425
+ attr_accessor :autoresize_titles
1426
+ def create
1427
+ super
1428
+ end
1429
+
1430
+ def set_titles stringarr
1431
+ stringarr.each { |str|
1432
+ @header.appendItem(" " + str)
1433
+ }
1434
+ set_cols stringarr.size
1435
+ set_title_widths
1436
+ end
1437
+
1438
+ def set_title_widths numarray = nil
1439
+ if numarray
1440
+ else # ok, calculate the item widths from their titles
1441
+ total = 0
1442
+ totalsize = 0
1443
+ i = 0
1444
+ @header.each { |item|
1445
+ total += item.text.size
1446
+ totalsize += item.size
1447
+ item.data = i
1448
+ i += 1
1449
+ }
1450
+ if @autoresize_titles || (totalsize == 0)
1451
+ quant = (@header.width / total.to_f)
1452
+ offset = 0
1453
+ @header.each { |item|
1454
+ i = item.data
1455
+ size = (item.text.size * quant).to_i
1456
+ @header.setItemSize i, size
1457
+ offset += size
1458
+ }
1459
+ end
1460
+ end
1461
+ end
1462
+
1463
+ def set_cols n
1464
+ end
1465
+
1466
+ def set_rows n
1467
+ end
1468
+ end
1469
+ end
1470
+
1471
+ class StyleVisitor
1472
+ def apply_to(widget, recursive = true)
1473
+ widget.recursive { |w|
1474
+ identifier = "#{w.class.to_s.gsub(/Fox|::|FX/, "")}_style"
1475
+ send identifier, w # if respond_to? identifier
1476
+ break unless recursive
1477
+ }
1478
+ end
1479
+ end
1480
+
1481
+ class FlatStyle < StyleVisitor
1482
+ attr_accessor :frameColor
1483
+ def initialize
1484
+ @frameColor = Fox::FXRGB 0, 0, 0
1485
+ @backColor = Fox::FXRGB 230, 230, 230
1486
+ end
1487
+
1488
+ def Button_style w
1489
+ w.frameStyle = Fox::FRAME_LINE
1490
+ w.hiliteColor = @frameColor
1491
+ w.shadowColor = @frameColor
1492
+ w.backColor = @backColor
1493
+ end
1494
+
1495
+ def TextField_style w
1496
+ w.frameStyle = Fox::FRAME_LINE
1497
+ w.borderColor = Fox::FXRGB 168, 168, 168
1498
+ end
1499
+
1500
+ def method_missing(*args)
1501
+ identifier, w = args
1502
+ unless /style/.match?(identifier.to_s)
1503
+ raise args.join(",")
1504
+ end
1505
+ w.backColor = @backColor
1506
+ w
1507
+ end
1508
+ end
1509
+
1510
+ module FX
1511
+ class DCWindow < Fox::FXDCWindow
1512
+ def initialize(*args)
1513
+ super
1514
+ setOrigin(0, 0)
1515
+ end
1516
+
1517
+ def getOrigin
1518
+ [@xOrigin, @yOrigin]
1519
+ end
1520
+
1521
+ def setOrigin x = 0, y = 0
1522
+ @xOrigin = x
1523
+ @yOrigin = y
1524
+ @originStack = [x, y]
1525
+ end
1526
+
1527
+ def pushOrigin x = 0, y = 0
1528
+ @xOrigin += x
1529
+ @yOrigin += y
1530
+ @originStack.push [@xOrigin, @yOrigin]
1531
+ end
1532
+
1533
+ def popOrigin
1534
+ @originStack.pop if @originStack.size > 1
1535
+ @xOrigin, @yOrigin = @originStack.last
1536
+ end
1537
+
1538
+ def drawText x, y, text, bg = false
1539
+ if bg
1540
+ drawImageText(@xOrigin + x, @yOrigin + y, text)
1541
+ else
1542
+ super(@xOrigin + x, @yOrigin + y, text)
1543
+ end
1544
+ end
1545
+
1546
+ def drawImageText x, y, text
1547
+ super(@xOrigin + x, @yOrigin + y, text)
1548
+ end
1549
+
1550
+ def drawLine x, y, x1, y1
1551
+ super(@xOrigin + x, @yOrigin + y, @xOrigin + x1, @yOrigin + y1)
1552
+ end
1553
+
1554
+ def fillRectangle x, y, w, h
1555
+ super(@xOrigin + x, @yOrigin + y, w, h)
1556
+ end
1557
+
1558
+ def drawRectangle x, y, w, h
1559
+ super(@xOrigin + x, @yOrigin + y, w, h)
1560
+ end
1561
+ end
1562
+
1563
+ class DrawingCanvas < Canvas
1564
+ __sends__ :event_draw
1565
+ def initialize parent
1566
+ super(parent, Fox::LAYOUT_FILL_X | Fox::LAYOUT_FILL_Y)
1567
+ @stdFont = Fox::FXFont.new($fxapp, "[helvetica] 90 700 1 1 0 0")
1568
+ @stdFont.create
1569
+ connect(Fox::SEL_PAINT) { |sender, sel, event|
1570
+ resize parent.width, parent.height if (width != parent.width) || (height != parent.height)
1571
+ dc = DCWindow.new self
1572
+ dc.font = @stdFont
1573
+ event_draw(dc, event, self)
1574
+ dc.end
1575
+ }
1576
+ end
1577
+ end
1578
+ end
1579
+
1580
+ class PathSelector
1581
+ def init
1582
+ @title = "Directory Dialog"
1583
+ @relative_path = false
1584
+ @directory = Dir.getwd
1585
+ update(@directory)
1586
+ @dialog = FXDirDialog.new(@topwin, @title)
1587
+ @browse.connect(SEL_COMMAND, method(:onBrowse))
1588
+ end
1589
+ attr_accessor :directory, :title, :filename, :relative_path
1590
+ def description=text
1591
+ @label.text = text
1592
+ end
1593
+
1594
+ def description
1595
+ @label.text
1596
+ end
1597
+
1598
+ def onBrowse(*args)
1599
+ @dialog.title = @title
1600
+ @dialog.directory = @directory
1601
+ if @dialog.execute != 0
1602
+ update(@dialog.directory)
1603
+ end
1604
+ end
1605
+
1606
+ def update(path)
1607
+ @directory = @textfield.text = if @relative_path
1608
+ rel_path(Dir.getwd, path)
1609
+ else
1610
+ path
1611
+ end
1612
+ end
1613
+ end