fxruby-enhancement 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.semver +2 -2
- data/Gemfile.lock +1 -1
- data/README.org +250 -27
- data/examples/data_target.rb +60 -0
- data/examples/dialog_box.rb +54 -0
- data/examples/hello.rb +1 -4
- data/fxruby-enhancement.gemspec +5 -3
- data/lib/fxruby-enhancement/api-mapper.rb +688 -688
- data/lib/fxruby-enhancement/api-mapper.rb.erb +3 -3
- data/lib/fxruby-enhancement/enhancement.rb +1 -0
- data/lib/fxruby-enhancement/ostruct-monkey.rb +33 -3
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee35871b37b12dab95f43e9e0efe47c4eef62ae9
|
4
|
+
data.tar.gz: 23dad1cd5a49af520b2af586ea7fb11105c73966
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0f580dbe88affcab84a81b8c8ffc669d8a5f46e21c6dc5b59a95bb8d6c28ac4b45f3079dff633caddbeab5a101629b3ee0f76327a8a1702259279e4fef6b6c2
|
7
|
+
data.tar.gz: 8fa2425ff455205357d1cfc8e07073223dcda195a6205b6d953205f4e3a68a3120fc847af4781efcbd58335adc17dce9e0ec258bcf06f4172766ec96fd5cfade
|
data/.semver
CHANGED
data/Gemfile.lock
CHANGED
data/README.org
CHANGED
@@ -13,12 +13,15 @@
|
|
13
13
|
- [[#the-queue_ding-queues][The Queue_Ding Queues]]
|
14
14
|
- [[#enhancementingress][Enhancement.ingress]]
|
15
15
|
- [[#enhancementegress][Enhancement.egress]]
|
16
|
+
- [[#reusable-components-and-dynamic-creation-and-the-reuse-flag][Reusable components and dynamic creation, and the 'reuse' flag]]
|
16
17
|
- [[#api--dsl][API & DSL]]
|
17
18
|
- [[#ref-refc-and-tagging-your-objects][ref(), refc() and tagging your objects]]
|
18
19
|
- [[#fox_component-and-fox_instance][fox_component and fox_instance]]
|
19
20
|
- [[#fx_app][fx_app]]
|
21
|
+
- [[#fx_data_target][fx_data_target]]
|
20
22
|
- [[#instance][instance]]
|
21
23
|
- [[#ingress_handler][ingress_handler]]
|
24
|
+
- [[#starten-and-stoppen-with-resuable-components][#starten and #stoppen with resuable components]]
|
22
25
|
- [[#deferred_setup][deferred_setup]]
|
23
26
|
- [[#mapping-between-fx_-declarations-and-the-fx-fxruby-objects][Mapping between fx_* declarations and the FX* FXRuby objects]]
|
24
27
|
- [[#bindingfx][binding.fx]]
|
@@ -27,12 +30,15 @@
|
|
27
30
|
- [[#hello-world-the-old-fxruby-way][Hello World the old fxruby way:]]
|
28
31
|
- [[#bouncing-ball-example-full][Bouncing Ball example (full):]]
|
29
32
|
- [[#bouncing-ball-the-old-fxruby-way][Bouncing Ball the old fxruby way:]]
|
33
|
+
- [[#datatarget-example][DataTarget Example]]
|
30
34
|
- [[#release-notes][Release Notes]]
|
31
35
|
- [[#known-issues][Known Issues]]
|
32
36
|
- [[#contributing-to-fxruby-enhancement][Contributing to fxruby-enhancement]]
|
33
37
|
- [[#copyright-and-licensing][Copyright and Licensing]]
|
34
38
|
- [[#the-junkyard--scratchpad][The Junkyard / Scratchpad]]
|
35
|
-
- [[#genesis-of-the-meta-meta-programming-whereby-brain-goes-boom][Genesis of the meta-meta programming, whereby brain goes boom]]
|
39
|
+
- [[#junkyard-genesis-of-the-meta-meta-programming-whereby-brain-goes-boom][JUNKYARD Genesis of the meta-meta programming, whereby brain goes boom]]
|
40
|
+
- [[#junkyard-resuable-components-and-data-targets][JUNKYARD Resuable components and data targets]]
|
41
|
+
- [[#junkyard-data-targets][JUNKYARD Data Targets]]
|
36
42
|
|
37
43
|
* fxruby-enhancement
|
38
44
|
** Introduction
|
@@ -49,14 +55,23 @@
|
|
49
55
|
fxruby-enhancement makes this a snap to do. You simply declare
|
50
56
|
your GUI arrangement in a nested fashion. fxruby-enhancement will
|
51
57
|
take care of passing parents to the nested children, and other issues
|
52
|
-
as well. You can now focus on creating
|
58
|
+
as well. You can now focus on creating your great GUI layout that you
|
53
59
|
can change on the fly without much fuss and bother.
|
54
60
|
|
55
|
-
fxruby-enhancement
|
56
|
-
been taken to make it intuitive to
|
57
|
-
you should be able to look at the
|
58
|
-
the DSL construct for fxruby-enhancement.
|
59
|
-
[[file:examples][examples]].
|
61
|
+
fxruby-enhancement (also referred to as "Enhancement") is basically a
|
62
|
+
DSL of sorts, and every effort has been taken to make it intuitive to
|
63
|
+
use. Once you get the hang of it, you should be able to look at the
|
64
|
+
FXRuby API documentation and infer the DSL construct for fxruby-enhancement.
|
65
|
+
Please also see the many [[file:examples][examples]].
|
66
|
+
|
67
|
+
Enhancement basically leverages Ruby's singleton feature, and eliminates
|
68
|
+
the need to "subclass" the FXRuby objects and the like. In fact, you might
|
69
|
+
even consider this Enhancement's own "paradigm" for doing GUI programming.
|
70
|
+
|
71
|
+
Your input and criticisms are more than welcome. Feel free to raise
|
72
|
+
issues on GitHub. I have not anticipated all the ways someone might try
|
73
|
+
to use Enhancement. I am making heavy use of Enhancement in my RubyNEAT
|
74
|
+
project -- which is why I created it.
|
60
75
|
|
61
76
|
** Installation
|
62
77
|
To install the gem from commandline:
|
@@ -196,7 +211,7 @@
|
|
196
211
|
And so your handler will most likely act as a dispatcher
|
197
212
|
for the payloads received. For example:
|
198
213
|
#+begin_src ruby
|
199
|
-
ingress_handler :
|
214
|
+
ingress_handler :log_info, :log_error do |tag, logline|
|
200
215
|
puts "received #{tag} => #{payload}"
|
201
216
|
case tag
|
202
217
|
when :log_info
|
@@ -207,6 +222,14 @@
|
|
207
222
|
end
|
208
223
|
#+end_src
|
209
224
|
|
225
|
+
Note that this ingress handler is responding to two tags. You can have
|
226
|
+
as many tags as you like for your ingress handler, and as many
|
227
|
+
ingress handlers as you like.
|
228
|
+
|
229
|
+
Currently, all the tags should be unique. Later we may support having
|
230
|
+
multiple blocks associated with the same tag. Please feel free to generate
|
231
|
+
an issue if you want this!!!
|
232
|
+
|
210
233
|
***** Enhancement.egress
|
211
234
|
Wnen your Fox application needs to send a message to other
|
212
235
|
listening threads, You simply push your payload onto the egress queue
|
@@ -216,9 +239,56 @@
|
|
216
239
|
#+end_src
|
217
240
|
|
218
241
|
and your Ruby thread external to Fox would simply do:
|
219
|
-
#+begin_src
|
242
|
+
#+begin_src ruby
|
243
|
+
...
|
244
|
+
message = Enhancement.egress.next
|
245
|
+
...
|
246
|
+
#+end_src
|
247
|
+
|
248
|
+
where you'll block pending the arrival of the next message. If you
|
249
|
+
do not wish to block, you may do:
|
250
|
+
#+begin_src ruby
|
251
|
+
...
|
252
|
+
unless Enhancement.egress.empty?
|
253
|
+
message = Enhancement.egress.next
|
254
|
+
else
|
255
|
+
# some action to take
|
256
|
+
end
|
257
|
+
...
|
220
258
|
#+end_src
|
221
259
|
|
260
|
+
*** Reusable components and dynamic creation, and the 'reuse' flag
|
261
|
+
There are times you may want to be able to create, and popup, say, a dialog
|
262
|
+
box, or perhaps you want to create on the fly child components on an
|
263
|
+
existing window.
|
264
|
+
|
265
|
+
This is made possible with the "reuse: true" flag. For example:
|
266
|
+
#+begin_src ruby
|
267
|
+
fx_dialog_box(:dialog, reuse: true) {
|
268
|
+
title "I am a Dialog!"
|
269
|
+
opts DECOR_ALL
|
270
|
+
|
271
|
+
fx_button {
|
272
|
+
text "&It Works!"
|
273
|
+
instance { |dia|
|
274
|
+
dia.sel_command {
|
275
|
+
refc(:dialog).stoppen
|
276
|
+
}
|
277
|
+
}
|
278
|
+
}
|
279
|
+
instance { |dia| dia.show PLACEMENT_OWNER }
|
280
|
+
}
|
281
|
+
#+end_src
|
282
|
+
|
283
|
+
This code snippet can be run in the context of the app or a window.
|
284
|
+
If you do it in a window context, that window will become the "owner",
|
285
|
+
and will initially be placed hovering over it.
|
286
|
+
|
287
|
+
With reusable components, you will use the #starten and #stoppen methods
|
288
|
+
to create and destroy the component. Please see
|
289
|
+
the [[file:examples/dialog_box.rb][Dialog Box]] for a full example, and also
|
290
|
+
the docs for #starten and #stoppen.
|
291
|
+
|
222
292
|
*** API & DSL
|
223
293
|
**** ref(), refc() and tagging your objects
|
224
294
|
In an effort to eliminate the fuss and bother with
|
@@ -237,12 +307,25 @@
|
|
237
307
|
refc(:some_tag).inst
|
238
308
|
#+end_src
|
239
309
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
310
|
+
Where might you want to use refc() instead of ref()? In cases
|
311
|
+
where the underlying FXRuby object have not been instantiated yet,
|
312
|
+
you'd use refc() instead of ref(), almost always during the component
|
313
|
+
configuration. For example:
|
314
|
+
#+begin_src ruby
|
315
|
+
fx_app :app do
|
316
|
+
...
|
317
|
+
fx_button {
|
318
|
+
text "&See Ya!"
|
319
|
+
selector FXApp::ID_QUIT
|
320
|
+
target refc(:app)
|
321
|
+
}
|
322
|
+
...
|
323
|
+
#+end_src
|
324
|
+
|
325
|
+
Here, we set the button to exit the application by sending the FXApp object the ID_QUIT
|
326
|
+
message. But at the time we set the configuration, the FXApp object has not been instantiated
|
327
|
+
yet. So we use refc() instead of ref().
|
328
|
+
|
246
329
|
Underlying, the component object is really a subclass of OpenScript.
|
247
330
|
While you may like to stuff some additional data there,
|
248
331
|
this is frowned upon because it might conflict with Enhancement.
|
@@ -293,6 +376,37 @@
|
|
293
376
|
Typeically you'd do this inside of a module, but you could do it also
|
294
377
|
in a class body. Please see the examples.
|
295
378
|
|
379
|
+
**** fx_data_target
|
380
|
+
FOX (and therefor FXRuby) supports data synchronization among components.
|
381
|
+
fx_data_target encapsulates the FXDataTarget class, just like all the
|
382
|
+
other fx_* directives do. However, in this case, some special treatment
|
383
|
+
is necessary since it is referenced at a time the underlying FXRuby
|
384
|
+
object has not been created yet.
|
385
|
+
|
386
|
+
Enter refc(). You use refc(), instead of ref(), to use it when you are
|
387
|
+
configuring the component (really, specifying the initial parameters
|
388
|
+
to the underlying FXRuby class!) We illustrate here:
|
389
|
+
#+begin_src ruby
|
390
|
+
...
|
391
|
+
fx_data_target (:mydata) { value "initial value" }
|
392
|
+
...
|
393
|
+
fx_text (:text_3) {
|
394
|
+
target refc(:mydata)
|
395
|
+
selector FXDataTarget::ID_VALUE
|
396
|
+
}
|
397
|
+
fx_text (:text_4) {
|
398
|
+
target refc(:mydata)
|
399
|
+
selector FXDataTarget::ID_VALUE
|
400
|
+
}
|
401
|
+
#+end_src
|
402
|
+
|
403
|
+
And so the two text components -- or widgets -- are initially
|
404
|
+
set to the value of "initial value", and when one changes, the
|
405
|
+
other is instantly updated.
|
406
|
+
|
407
|
+
Otherwise, you can deal with fx_data_target as expected. See
|
408
|
+
the [[#datatarget-example][DataTarget Example]].
|
409
|
+
|
296
410
|
**** instance
|
297
411
|
Inside of your component declaration, you will undoubtly
|
298
412
|
want to specify what you want to do once the FXRuby object
|
@@ -379,6 +493,30 @@
|
|
379
493
|
|
380
494
|
The same block is assigned to all the given tags of :warn, :info, and :error.
|
381
495
|
|
496
|
+
**** #starten and #stoppen with resuable components
|
497
|
+
To designate a component as reusable, declare it with "reuse: true"
|
498
|
+
as in the example:
|
499
|
+
#+begin_src ruby
|
500
|
+
fx_dialog_box(:dialog, reuse: true) { ... }
|
501
|
+
#+end_src
|
502
|
+
|
503
|
+
Then in the instance clause or to the response to an event,
|
504
|
+
you would do:
|
505
|
+
#+begin_src ruby
|
506
|
+
refc(:dialog).starten
|
507
|
+
#+end_src
|
508
|
+
|
509
|
+
to activate it, and
|
510
|
+
#+begin_src ruby
|
511
|
+
refc(:dialog).stoppen
|
512
|
+
#+end_src
|
513
|
+
|
514
|
+
to deactive it (and remove the 'server'-side FOX components!)
|
515
|
+
|
516
|
+
Note that you call refc(), not ref() in this case, because the
|
517
|
+
functionality lies in the component object holder for the actual
|
518
|
+
FOX component, not within the FXRuby object itself.
|
519
|
+
|
382
520
|
**** TODO deferred_setup
|
383
521
|
**** TODO Mapping between fx_* declarations and the FX* FXRuby objects
|
384
522
|
**** binding.fx
|
@@ -418,7 +556,7 @@
|
|
418
556
|
|
419
557
|
https://github.com/flajann2/rubyneat-panel/tree/master/lib/rubyneat-panel
|
420
558
|
|
421
|
-
Class-based
|
559
|
+
Class-based Enhancement (this is currently not supported!!!):
|
422
560
|
#+begin_src ruby
|
423
561
|
class Main < FXMainWindow
|
424
562
|
compose :my_window do
|
@@ -451,7 +589,7 @@
|
|
451
589
|
end
|
452
590
|
#+end_src
|
453
591
|
|
454
|
-
Class-free
|
592
|
+
Class-free Enhancement (strongly recommended):
|
455
593
|
#+begin_src ruby
|
456
594
|
mw = fx_main_window :my_window do
|
457
595
|
title "RubyNEAT Panel"
|
@@ -886,18 +1024,87 @@ end
|
|
886
1024
|
|
887
1025
|
More examples can be found [[file:examples][HERE]].
|
888
1026
|
|
1027
|
+
**** DataTarget Example
|
1028
|
+
fx_data_target (:some_name) must be referenced as refc(:some_name) and
|
1029
|
+
not ref(...). See the example below.
|
1030
|
+
|
1031
|
+
#+begin_src ruby
|
1032
|
+
#!/usr/bin/env ruby
|
1033
|
+
require 'fxruby-enhancement'
|
1034
|
+
|
1035
|
+
include Fox
|
1036
|
+
include Fox::Enhancement::Mapper
|
1037
|
+
|
1038
|
+
fx_app :app do
|
1039
|
+
app_name "DataTarget"
|
1040
|
+
vendor_name "Example"
|
1041
|
+
|
1042
|
+
fx_data_target (:textx) { value "x marks the spot!" }
|
1043
|
+
fx_data_target (:texty) { value "y do it?" }
|
1044
|
+
|
1045
|
+
fx_main_window(:main) {
|
1046
|
+
title "fx_data_target example"
|
1047
|
+
opts DECOR_ALL
|
1048
|
+
width 300
|
1049
|
+
x 100
|
1050
|
+
y 200
|
1051
|
+
|
1052
|
+
fx_text_field (:text_1) {
|
1053
|
+
ncols 40
|
1054
|
+
target refc(:textx)
|
1055
|
+
selector FXDataTarget::ID_VALUE
|
1056
|
+
}
|
1057
|
+
fx_text_field (:text_2) {
|
1058
|
+
ncols 40
|
1059
|
+
target refc(:textx)
|
1060
|
+
selector FXDataTarget::ID_VALUE
|
1061
|
+
}
|
1062
|
+
fx_text (:text_3) {
|
1063
|
+
opts LAYOUT_FILL_X
|
1064
|
+
target refc(:texty)
|
1065
|
+
selector FXDataTarget::ID_VALUE
|
1066
|
+
}
|
1067
|
+
fx_text (:text_4) {
|
1068
|
+
opts LAYOUT_FILL_X
|
1069
|
+
target refc(:texty)
|
1070
|
+
selector FXDataTarget::ID_VALUE
|
1071
|
+
}
|
1072
|
+
fx_button {
|
1073
|
+
text "&See ya!"
|
1074
|
+
selector FXApp::ID_QUIT
|
1075
|
+
opts BUTTON_NORMAL|LAYOUT_CENTER_X
|
1076
|
+
|
1077
|
+
instance { |b|
|
1078
|
+
b.target = ref(:app)
|
1079
|
+
}
|
1080
|
+
}
|
1081
|
+
|
1082
|
+
instance { |w|
|
1083
|
+
w.show PLACEMENT_SCREEN
|
1084
|
+
}
|
1085
|
+
}
|
1086
|
+
end
|
1087
|
+
|
1088
|
+
# alias for fox_component is fxc
|
1089
|
+
fox_component :app do |app|
|
1090
|
+
app.launch
|
1091
|
+
end
|
1092
|
+
#+end_src
|
1093
|
+
|
889
1094
|
** Release Notes
|
890
|
-
| Version | Date | Notes
|
891
|
-
|
892
|
-
| 0.0.2 | 2017-01-11 | Initial release
|
893
|
-
| 0.0.3 | 2017-01-15 | Needed to require fox16/colors for FXColor to be loaded
|
894
|
-
| 0.0.4 | 2017-01-16 | ingress_handler now handles multiple tags.
|
1095
|
+
| Version | Date | Notes |
|
1096
|
+
|---------+------------+-------------------------------------------------------------|
|
1097
|
+
| 0.0.2 | 2017-01-11 | Initial release |
|
1098
|
+
| 0.0.3 | 2017-01-15 | Needed to require fox16/colors for FXColor to be loaded |
|
1099
|
+
| 0.0.4 | 2017-01-16 | ingress_handler now handles multiple tags. |
|
1100
|
+
| 0.1.0 | 2017-01-18 | special handling for fx_data_target and resuable components |
|
895
1101
|
|
896
1102
|
** Known Issues
|
897
|
-
| Version |
|
898
|
-
|
899
|
-
| 0.0.2 |
|
900
|
-
|
1103
|
+
| Version | Date | Issues |
|
1104
|
+
|---------+------------------------+--------------------------------------------------------------------|
|
1105
|
+
| 0.0.2 | 2017-01-11 | Not enough example code!!! Need more documentation!!! |
|
1106
|
+
| 0.1.0 | Trump Inaguration Day, | deferred_setup not fully implemented, and may go away. |
|
1107
|
+
| | 2017-01-20 | compose is not really needed, and is not fully implemented anyway. |
|
901
1108
|
|
902
1109
|
** Contributing to fxruby-enhancement
|
903
1110
|
|
@@ -917,7 +1124,7 @@ end
|
|
917
1124
|
You may see some interesting tidbits here, but I am not
|
918
1125
|
gauranteeing anything to be useful or reliable in this
|
919
1126
|
section. YOU HAVE BEEN WARNED.
|
920
|
-
*** Genesis of the meta-meta programming, whereby brain goes boom
|
1127
|
+
*** JUNKYARD Genesis of the meta-meta programming, whereby brain goes boom
|
921
1128
|
#+begin_src ruby
|
922
1129
|
class FXToolBar # monkey patch
|
923
1130
|
include Enhancement
|
@@ -953,3 +1160,19 @@ end
|
|
953
1160
|
#+end_src
|
954
1161
|
|
955
1162
|
|
1163
|
+
*** JUNKYARD Resuable components and data targets
|
1164
|
+
We have an issue with needing to have reusable components
|
1165
|
+
(dialog boxes, say), and ṕroperly handling data targets designations.
|
1166
|
+
**** JUNKYARD Data Targets
|
1167
|
+
Data targets cannot be done the same way we are doing the other
|
1168
|
+
fxruby components, because they have a different workflow. Basically,
|
1169
|
+
they need to be instantiated before the other comonents that uses
|
1170
|
+
them, and they are not really "child" objects, either. Referring to them
|
1171
|
+
using the ref() or refc() approach simply fails, because they won't
|
1172
|
+
be instantiated in time.
|
1173
|
+
|
1174
|
+
We have ameroliated this problem by checking in the parameter list
|
1175
|
+
for an OpenStruct object, and calling #inst on it to pass in the instance,
|
1176
|
+
rather than the object itself. So now you simply use refc()
|
1177
|
+
in those cases.
|
1178
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'fxruby-enhancement'
|
3
|
+
|
4
|
+
include Fox
|
5
|
+
include Fox::Enhancement::Mapper
|
6
|
+
|
7
|
+
fx_app :app do
|
8
|
+
app_name "DataTarget"
|
9
|
+
vendor_name "Example"
|
10
|
+
|
11
|
+
fx_data_target (:textx) { value "x marks the spot!" }
|
12
|
+
fx_data_target (:texty) { value "y do it?" }
|
13
|
+
|
14
|
+
fx_main_window(:main) {
|
15
|
+
title "fx_data_target example"
|
16
|
+
opts DECOR_ALL
|
17
|
+
width 300
|
18
|
+
x 100
|
19
|
+
y 200
|
20
|
+
|
21
|
+
fx_text_field (:text_1) {
|
22
|
+
ncols 40
|
23
|
+
target refc(:textx)
|
24
|
+
selector FXDataTarget::ID_VALUE
|
25
|
+
}
|
26
|
+
fx_text_field (:text_2) {
|
27
|
+
ncols 40
|
28
|
+
target refc(:textx)
|
29
|
+
selector FXDataTarget::ID_VALUE
|
30
|
+
}
|
31
|
+
fx_text (:text_3) {
|
32
|
+
opts LAYOUT_FILL_X
|
33
|
+
target refc(:texty)
|
34
|
+
selector FXDataTarget::ID_VALUE
|
35
|
+
}
|
36
|
+
fx_text (:text_4) {
|
37
|
+
opts LAYOUT_FILL_X
|
38
|
+
target refc(:texty)
|
39
|
+
selector FXDataTarget::ID_VALUE
|
40
|
+
}
|
41
|
+
fx_button {
|
42
|
+
text "&See ya!"
|
43
|
+
selector FXApp::ID_QUIT
|
44
|
+
opts BUTTON_NORMAL|LAYOUT_CENTER_X
|
45
|
+
|
46
|
+
instance { |b|
|
47
|
+
b.target = ref(:app)
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
instance { |w|
|
52
|
+
w.show PLACEMENT_SCREEN
|
53
|
+
}
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
# alias for fox_component is fxc
|
58
|
+
fox_component :app do |app|
|
59
|
+
app.launch
|
60
|
+
end
|