fxruby-enhancement 0.0.4 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|