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