README.org in fxruby-enhancement-0.1.0 vs README.org in fxruby-enhancement-0.2.0
- old
+ new
@@ -1,12 +1,14 @@
#+OPTIONS: broken-links:mark
* FXRuby Enhancement Table of Contents :TOC_5_gh:
- [[#fxruby-enhancement][fxruby-enhancement]]
+ - [[#showcase][Showcase]]
- [[#introduction][Introduction]]
- [[#installation][Installation]]
- [[#documentation][Documentation]]
- [[#in-general][In General]]
+ - [[#the-use-of--vs-doend-to-define-your-blocks][The use of {...} vs do...end to define your blocks]]
- [[#execution-phases-of-fxruby-enhancement][Execution Phases of fxruby-enhancement]]
- [[#declarative][Declarative]]
- [[#fxruby-instantiation][FXRuby Instantiation]]
- [[#fox-toolkit-instantiation][FOX Toolkit instantiation]]
- [[#events-from-other-threads][Events from other Threads]]
@@ -14,13 +16,17 @@
- [[#enhancementingress][Enhancement.ingress]]
- [[#enhancementegress][Enhancement.egress]]
- [[#reusable-components-and-dynamic-creation-and-the-reuse-flag][Reusable components and dynamic creation, and the 'reuse' flag]]
- [[#api--dsl][API & DSL]]
- [[#ref-refc-and-tagging-your-objects][ref(), refc() and tagging your objects]]
+ - [[#as----adding-new-child-components-to-already-declared-ones][as -- adding new child components to already declared ones]]
- [[#fox_component-and-fox_instance][fox_component and fox_instance]]
- [[#fx_app][fx_app]]
+ - [[#fx_chart----not-implemented-yet-still-in-development][fx_chart -- NOT IMPLEMENTED YET! STILL IN DEVELOPMENT!]]
+ - [[#data-format-and-labeling----not-implemented-yet][Data Format and Labeling -- NOT IMPLEMENTED YET!]]
- [[#fx_data_target][fx_data_target]]
+ - [[#fx_dc][fx_dc]]
- [[#instance][instance]]
- [[#ingress_handler][ingress_handler]]
- [[#starten-and-stoppen-with-resuable-components][#starten and #stoppen with resuable components]]
- [[#deferred_setup][deferred_setup]]
- [[#mapping-between-fx_-declarations-and-the-fx-fxruby-objects][Mapping between fx_* declarations and the FX* FXRuby objects]]
@@ -37,12 +43,33 @@
- [[#copyright-and-licensing][Copyright and Licensing]]
- [[#the-junkyard--scratchpad][The Junkyard / Scratchpad]]
- [[#junkyard-genesis-of-the-meta-meta-programming-whereby-brain-goes-boom][JUNKYARD Genesis of the meta-meta programming, whereby brain goes boom]]
- [[#junkyard-resuable-components-and-data-targets][JUNKYARD Resuable components and data targets]]
- [[#junkyard-data-targets][JUNKYARD Data Targets]]
+ - [[#junkyard-subtle-ruby-bug-detected-chartrb-ruby-240][JUNKYARD Subtle Ruby Bug detected. (chart.rb) Ruby 2.4.0]]
+ - [[#junkyard-as-execution-issue-debugging-code][JUNKYARD 'as' execution issue DEBUGGING CODE]]
+ - [[#scratchpad-fxdcwindow][SCRATCHPAD FXDCWindow]]
+ - [[#junkyard-thoughs-on-doing-the-layout][JUNKYARD Thoughs on doing the layout]]
+ - [[#junkyard-superior-layout-calculations][JUNKYARD Superior layout calculations]]
+ - [[#junkyard-debug-layout-dump][JUNKYARD Debug layout dump]]
* fxruby-enhancement
+ #+caption: Enhancement vs. FXRuby versions of Hello World.
+ #+name: fig:hello-world
+ [[./examples/images/hello-world-new-and-old.png]]
+ - On the left: Enhancement version of hello world.
+ - On the right: FXRuby version.
+** Showcase
+ | Screenshot | Code Links |
+ |--------------------------------------+----------------|
+ | [[./examples/images/hello.rb.png]] | [[file:./examples/hello.rb][Hello World]] |
+ | [[./examples/images/dialog_box.rb.png]] | [[file:,/examples/dialog_box.rb][Dialog Box]] |
+ | [[./examples/images/bounce.rb.png]] | [[file:./examples/bounce.rb][Bounce]] |
+ | [[./examples/images/scribble.rb.png]] | [[file:./examples/scribble.rb][Scribble]] |
+ | [[./examples/images/chart.rb.png]] | [[file:./examples/chart.rb][Chart]] |
+ | [[./examples/images/rubyneat-panel.png]] | [[https://github.com/flajann2/rubyneat-panel/tree/master/lib/rubyneat-panel][RubyNEAT Panel]] |
+
** Introduction
The fxruby library is an excellent wrapper for the FOX Toolkit.
However, it reflects the C++-ness of FOX, rather than being more
Ruby-like. As such, creating composed objects with it tends to be
rather cumbersome, given its C++ roots. For every new component you create with
@@ -70,11 +97,13 @@
Your input and criticisms are more than welcome. Feel free to raise
issues on GitHub. I have not anticipated all the ways someone might try
to use Enhancement. I am making heavy use of Enhancement in my RubyNEAT
project -- which is why I created it.
-
+
+ [[https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=4AZLVF9WH9J3C&lc=US&item_name=FXRuby%20Enhancement&item_number=enhancement¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted][Donations are appreciated.]]
+
** Installation
To install the gem from commandline:
#+begin_src bash
gem install fxruby-enhancement
@@ -142,10 +171,48 @@
#+end_src
So when the actual FXImage object is instantiated, it is associated to
the :back_buffer tag, which then is found by ref() and can be used
anywhere in the instantiation phase.
+**** The use of {...} vs do...end to define your blocks
+ This is something to be aware of, depending on
+ how you'd like to style your code for Enhancement.
+ I prefer the use of the braces {}, but others
+ might prefer the use of do...end.
+
+ Even though Ehnancement is a bit "opionated", I don't
+ wish to impose a coding style on you. But I do wish
+ to alert you to the subtle difference in syntax
+ that Ruby expects.
+
+ If you use the braces, you must enclose the
+ parameters to the directive in parens (). If
+ you use do...end, you have no such requirement.
+ for example, to use do...end:
+ #+begin_src ruby
+ fx_app :app do
+ ...
+ end
+ #+end_src
+
+ is perfectly OK, whereas:
+ #+begin_src ruby
+ fx_app :app {
+ ...
+ }
+ #+end_src
+
+ would generate a syntax error. You must, in this case:
+ #+begin_src ruby
+ fx_app (:app) {
+ ...
+ }
+ #+end_src
+
+ And that won't get your hands slapped by the Ruby
+ parser.
+
*** Execution Phases of fxruby-enhancement
This represents the work flow, in the order stated:
| State | Description |
|---------------------------+------------------------------------------------------------------------------------------------------------------------------|
| Declarative | The basic GUI layout is declared by the DSL, but it is not instantiated yet. |
@@ -329,10 +396,41 @@
Underlying, the component object is really a subclass of OpenScript.
While you may like to stuff some additional data there,
this is frowned upon because it might conflict with Enhancement.
If you have a need for this, please do a issue in GitHub.
+**** as -- adding new child components to already declared ones
+ The 'as' clause allow you to shift context back
+ to a previously defined component, so that you
+ can factor your code in a way to promote
+ encapsulation.
+
+ This is especially useful in large projects
+ where you are making heavy use of binding.fx
+ to modularize your GUI layout. It helps
+ you keep everything related in one place.
+
+ For example, deep within a
+ window definition, you made need to define
+ an image to be used by a widget. However,
+ the image needs to be defined in the fx_app
+ context, taking it far away from where
+ it is actially needed. Here's an example of how
+ you would do that:
+ #+begin_src ruby
+ fx_main_window(:bounce_window) {
+ title "Bounce Demo"
+ ...
+ as (:app) {
+ fx_image(:back_buffer) { opts IMAGE_KEEP }
+ }
+ ...
+ #+end_src
+
+ As you can see, your components will need to be tagged
+ to be referenced by 'as'.
+
**** fox_component and fox_instance
fox_component and fox_instance are roughly the
equivalent of refc() and ref(), respecively. The
difference mainly being that fox_component does no
sanity checking, and is therefore slightly faster.
@@ -374,10 +472,81 @@
#+end_src
Typeically you'd do this inside of a module, but you could do it also
in a class body. Please see the examples.
+**** TODO fx_chart -- NOT IMPLEMENTED YET! STILL IN DEVELOPMENT!
+ - NOTE WELL: fx_chart is still under development, and
+ has not been released yet for general usage. The
+ documentation in this section will change, I promise,
+ so please be aware of that. I am open to your suggestions
+ and input diring development, so feel free to raise
+ issues.
+
+ fx_chart is a custom widget supplied by Enhancement,
+ and provides very simple charting abilities. We have mainly created
+ this with the needs of RubyNEAT in mind, but hopefully we will
+ eventually grow the scope of what fx_chart can do.
+
+ Initally, we provide basic x-y Cartesian charting suitable for
+ representing time series, etc.
+***** Data Format and Labeling -- NOT IMPLEMENTED YET!
+ Data is in the format of an array of vectors,
+ with each update adding a new vector to the array. For example:
+ #+begin_src ruby
+ [
+ [1, 22.1, 34.2, 11],
+ [2, 23.4, 25.0, 14],
+ [3, 25.2, 35.2, 12],
+ [4, 21.9, 63.3, 11],
+ [5, 11.4, 50.1, 20],
+ ]
+ #+end_src
+
+ Even though the "vectors" are themselves arrays, we shall refer
+ to them as such for the sake of this discussion.
+
+ You may specify the first entry in the vector as the range,
+ in which case it will be used to plot the rest of the vector
+ as the "range" on the chart.
+****** Labeling Series Data -- NOT IMPLEMENTED YET!!!
+ Each entry in the vectors must have some sort of
+ designation to describe how the chart will display them.
+ So we represent this as an association of labels, and each
+ label will define how the data from that position in the
+ vector will be drawn and labeled. For example:
+ #+begin_src ruby
+ {
+ 0 => {
+ label: 'x-axis',
+ type: :range
+ },
+ 1 => {
+ label: 'Germany',
+ type: :data,
+ color: :yellow,
+ thickness: 3
+ },
+ 2 => {
+ label: 'Poland',
+ type: :data,
+ color: :blue,
+ thickness: 1
+ },
+ 3 => {
+ label: 'Östereich',
+ type: :data,
+ color: :green,
+ thickness: 2
+ },
+ }
+ #+end_src
+
+ Specifying the position of the vector as keys in the hash
+ will allow us to "leave gaps" in the specification, particulary
+ when the number of entries in that vector become large.
+
**** fx_data_target
FOX (and therefor FXRuby) supports data synchronization among components.
fx_data_target encapsulates the FXDataTarget class, just like all the
other fx_* directives do. However, in this case, some special treatment
is necessary since it is referenced at a time the underlying FXRuby
@@ -405,10 +574,37 @@
other is instantly updated.
Otherwise, you can deal with fx_data_target as expected. See
the [[#datatarget-example][DataTarget Example]].
+**** fx_dc
+ For canvas work, you typically have to create and
+ destory the FXDCWindow object. To ease this, use the
+ fx_dc instead. For example:
+ #+begin_src ruby
+ button.sel_command {
+ fx_dc :canvas do |dc|
+ dc.foreground = ref(:canvas).backColor
+ dc.fillRectangle(0, 0, ref(:canvas).width, ref(:canvas).height)
+ @dirty = false
+ end
+ }
+ #+end_src
+
+ instead of:
+ #+begin_src ruby
+ button.sel_command {
+ FXDCWindow.new(ref(:canvas)) do |dc|
+ dc.foreground = ref(:canvas).backColor
+ dc.fillRectangle(0, 0, ref(:canvas).width, ref(:canvas).height)
+ @dirty = false
+ end
+ }
+ #+end_src
+
+ This example has been borrowed from [[file:./examples/scribble.rb][Scribble]].
+
**** instance
Inside of your component declaration, you will undoubtly
want to specify what you want to do once the FXRuby object
is actually instantiated. This is what the instance clause
will allow you to do. Your code block there will be passed
@@ -516,11 +712,13 @@
Note that you call refc(), not ref() in this case, because the
functionality lies in the component object holder for the actual
FOX component, not within the FXRuby object itself.
**** TODO deferred_setup
+ This feature is still under development, and is not fully implemented yet.
**** TODO Mapping between fx_* declarations and the FX* FXRuby objects
+ To be documented.
**** binding.fx
This is a way to split up your layouts into different .fx "modules", purely for
organizational reasons. For example,
#+begin_src ruby
@@ -1090,23 +1288,27 @@
app.launch
end
#+end_src
** Release Notes
- | Version | Date | Notes |
- |---------+------------+-------------------------------------------------------------|
- | 0.0.2 | 2017-01-11 | Initial release |
- | 0.0.3 | 2017-01-15 | Needed to require fox16/colors for FXColor to be loaded |
- | 0.0.4 | 2017-01-16 | ingress_handler now handles multiple tags. |
- | 0.1.0 | 2017-01-18 | special handling for fx_data_target and resuable components |
+ | Version | Date | Notes |
+ |---------+------------+------------------------------------------------------------------------------------------------|
+ | 0.2.0 | 2017-02-16 | Releasing xtras without charting, which is still in progress. Many bug fixes and enhancements. |
+ | 0.1.0 | 2017-01-18 | special handling for fx_data_target and resuable components |
+ | 0.0.3 | 2017-01-15 | Needed to require fox16/colors for FXColor to be loaded |
+ | 0.0.4 | 2017-01-16 | ingress_handler now handles multiple tags. |
+ | 0.0.2 | 2017-01-11 | Initial release |
** Known Issues
- | Version | Date | Issues |
- |---------+------------------------+--------------------------------------------------------------------|
- | 0.0.2 | 2017-01-11 | Not enough example code!!! Need more documentation!!! |
- | 0.1.0 | Trump Inaguration Day, | deferred_setup not fully implemented, and may go away. |
- | | 2017-01-20 | compose is not really needed, and is not fully implemented anyway. |
+ | Version | Date | Issues |
+ |---------+-----------------------------------------+--------------------------------------------------------------------------|
+ | 0.2.0 | Shudown of a window, dialog box example | Seems to pop the same window to the middle of the screen first. |
+ | 0.2.0 | Subtle Ruby Bug | There are TODO notes in chart.rb, and there is something in The Junkyard |
+ | | | Bug moved into bug/ruby240 branch. Workaround now in place here. |
+ | 0.1.0 | Trump Inaguration Day, | deferred_setup not fully implemented, and may go away. |
+ | | 2017-01-20 | compose is not really needed, and is not fully implemented anyway. |
+ | 0.0.2 | 2017-01-11 | Not enough example code!!! Need more documentation!!! |
** Contributing to fxruby-enhancement
- Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
- Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
@@ -1157,11 +1359,10 @@
#No initializer
<% end %>
<% end %>
#+end_src
-
*** JUNKYARD Resuable components and data targets
We have an issue with needing to have reusable components
(dialog boxes, say), and ṕroperly handling data targets designations.
**** JUNKYARD Data Targets
Data targets cannot be done the same way we are doing the other
@@ -1174,5 +1375,283 @@
We have ameroliated this problem by checking in the parameter list
for an OpenStruct object, and calling #inst on it to pass in the instance,
rather than the object itself. So now you simply use refc()
in those cases.
+*** JUNKYARD Subtle Ruby Bug detected. (chart.rb) Ruby 2.4.0
+ This bug is a bit difficult to describe, but want to capture it here. It
+ has to do with my "pushing the limits" of Ruby's metaprogramming features.
+ #+begin_src ruby
+module Fox
+ module Enhancement
+ module Mapper
+ def fx_chart name = nil, ii: 0, pos: Enhancement.stack.last, reuse: nil, &block
+ Enhancement.stack << (@os = os =
+ OpenStruct.new(klass: FXCanvas,
+ op: [],
+ ii: ii,
+ fx: nil,
+ kinder: [],
+ inst: nil,
+ instance_result: nil,
+ reusable: reuse,
+ type: :cartesian,
+ axial: OpenStruct.new, #TODO: name changed to protect the innocent
+ background: OpenStruct.new))
+ Enhancement.components[name] = os unless name.nil?
+ unless pos.nil?
+ pos.kinder << os
+ else
+ Enhancement.base = os
+ end
+
+ @os.op[0] = OpenStruct.new(:parent => :required,
+ :target => nil,
+ :selector => 0,
+ :opts => FRAME_NORMAL,
+ :x => 0,
+ :y => 0,
+ :width => 0,
+ :height => 0)
+
+ # Initializers for the underlying
+ def target var; @os.op[@os.ii].target = var; end
+ def selector var; @os.op[@os.ii].selector = var; end
+ def opts var; @os.op[@os.ii].opts = var; end
+ def x var; @os.op[@os.ii].x = var; end
+ def y var; @os.op[@os.ii].y = var; end
+ def width var; @os.op[@os.ii].width = var; end
+ def height var; @os.op[@os.ii].height = var; end
+
+ # Chart specific
+ def type var; @os.type = var; end
+
+ #TODO: Subtle bug in Ruby 2.4.0 tripped over here with
+ #TODO: the name of this funcion being the same as the
+ #TODO: initialized variable in the OS, so I had to make
+ #TODO: them different, hence the "axial".
+ def axis ax, **kv
+ ap @os.axial[ax] = OpenStruct.new(**kv)
+ end
+
+ def background **kv; kv.each{ |k,v| @os.background[k] = v }; end
+
+ # What will be executed after FXCanvas is created.
+ def instance a=nil, &block
+ @os.instance_name = a
+ @os.instance_block ||= []
+ @os.instance_block << [a, block]
+ end
+
+ self.instance_eval &block
+
+ os.fx = ->(){
+ FXCanvas.new(*([pos.inst] + os.op[os.ii].to_h.values[1..-1]
+ .map{ |v| (v.is_a?(OpenStruct) ? v.inst : v)
+ } ))
+ }
+
+ Enhancement.stack.pop
+ @os = Enhancement.stack.last
+ return os
+ end
+ end
+ end
+end
+ #+end_src
+
+ Change "axial" to "axis" to recrystalize this bug. I suspect that the parser
+ or some aspect of the intepreter is confusing the "axis" function with
+ the "axis" variable on the OpenStruct object, and it has to do with the
+ exact way I am doing the parameters for the axis function that trips it up.
+ A similar approach with the background function works perfectly fine:
+ #+begin_src ruby
+ def axis ax, **kv
+ ap @os.axis[ax] = OpenStruct.new(**kv)
+ end
+
+ def background **kv; kv.each{ |k,v| @os.background[k] = v }; end
+ #+end_src
+
+ Which results in the error of:
+ #+begin_src
+ ArgumentError: wrong number of arguments (given 0, expected 1)
+ from /home/alveric/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/fxruby-enhancement-0.2.0/lib/fxruby-enhancement/xtras/chart.rb:46:in `axis'
+ #+end_src
+
+ A simple workaround was to rename the variable to "axial" or anything different
+ from the function "axis".
+
+ I need to investigate if this bug also exists in prior releases of Ruby, and
+ also produce a single-file scaled down example of this bug, so it can be reported
+ back to Matz.
+
+ Oh, the time...
+*** JUNKYARD 'as' execution issue DEBUGGING CODE
+ It is critical where the 'as' clause is executed, and we
+ need to alter that, because the fx_data_target instance
+ is not established at the time it's needed.
+
+ It is thought that the execution must take place before
+ kinder create_fox_components, but I need to think about this.
+ It's execution time is critical to the proper flow of Enhancement.
+
+ The following debug code allows you to specify
+ not only which files to trace, but also a line
+ range. And colored to. Massively useful. Maybe should
+ be a gem in its own right?
+ #+begin_src ruby
+### debugging
+TRACE_FILES = %w{
+api-mapper.rb:1832-1887
+enhancement.rb
+scribble.rb
+ostruct-monkey.rb:16-29
+}
+
+TFILES = TRACE_FILES.map{ |s| s.split(':').first }
+
+set_trace_func proc { |event, file, line, id, binding, classname|
+ base, srange = File.basename(file).split(':')
+ stnum, endnum = srange.split('-') unless srange.nil?
+ stnum = srange.nil? ? nil : stnum.to_i
+ endnum = srange.nil? && endnum.nil? ? nil : endnum.to_i
+ if TFILES.member?(base) && (srange.nil? ||
+ (endnum.nil? && line == stnum) ||
+ (stnum <= line && line <= endnum))
+ printf "%8s \033[32m%s:%-2d\033[0m %10s \033[33m%.50s\033[0m \033[36m%.50s\033[0m\n",
+ event,
+ base, #green
+ line, #green
+ id,
+ classname, #yellow
+ binding.receiver #cyan
+ end
+}
+### end debugging
+ #+end_src
+
+ It is now indeed clear that the 'as' must stick its
+ kinder in the kinder list of 'as'es parent component,
+ NOT the referred 'as' component itself. This is conceptually
+ tricky from the code point of view, BUT it is the intuitive
+ assumption from the programmer's point of view. From his
+ perspective, 'as' "executes" at the place he put it.
+
+ And so let us do the "hard" thing here to make the lives
+ of our users happy. :D
+
+ We have solution. We simply will put the kinder parent
+ in a hash with the Enhancement.stack level that
+ this kinder parent as opposed to the "real" parent is to be
+ used. When the owner 'as' completes, it removes that entry
+ from the hash.
+
+ This will allow for nesting of 'as' declerations as well,
+ with the intituively expected result. I do not recommend
+ nesting 'as' declarations, but at the same time I do not
+ wish to restrict our users from doing so. I simply cannot
+ conceive of all the possible ways Enhancement will be
+ leveraged.
+
+*** SCRATCHPAD FXDCWindow
+ Passing in a nil for the event is not the same
+ as passing in nothing at all. Probably has to
+ do with how the C interface is implemented or works.
+
+*** JUNKYARD Thoughs on doing the layout
+ As such, we have the components of the chart laid out
+ as boxes linking to each other to represent their relative
+ positions to each other. As such:
+
+ | | | Null Top -0 | | | |
+ | | | Title F-1 | | | |
+ | | | Top Ruler -2 | | | |
+ | Null Left-0 | Left Ruler -2 | Graph F-3 | Right Ruler -2 | Legend F-1 | Null Right -0 |
+ | | | Bottom Ruler -2 | | | |
+ | | | Caption F-1 | | | |
+ | | | Null Bottom -0 | | | |
+
+ And so, given the initial width and height of the
+ canvas, we work to determine everything else. For
+ those boxes that contain text, we know what the
+ text will be, and therefore how long and tall -- minimum --
+ they will need to be. And thusly we use the hints.
+
+ Boxes can define their margins, and therefore, coupled
+ with the float factor, determine their relationship
+ with their neighors. a dominance score as shown
+ in the diagram above determins how the layout will
+ proceed.
+
+ Since the chart will have the same basic layout, with
+ some components enabled and disabled and like, we shall
+ work our way from the outside in.
+
+ Some boxes, like the Rulers, will take their width
+ and height based on the dominate they are connected to.
+ Others, like the title and caption and legend boxes,
+ are floating.
+
+ We have come up with the splendid idea of creating
+ the "NullBox" -- basically the equivalent of having
+ zero or the empty set. It will simplify the layout
+ algorithm
+
+ The layout algorithm shall procede as follows:
+ - nil out all x,y, with, and heigts of all boxes
+ - set up the NullBox with the intitals
+ - work from the null box to its superiors, and so on,
+ setting what can be set, leaving the rest for later.
+ - when you reach the most dominant box (with no
+ superiors of its own), you should be able to fully
+ determine its dimensions.
+ - work back down the chain and fill in anything that's
+ missing.
+
+ For the float layout:
+ - We really want to keep this simple (for now), so
+ its with and height is already set by the hints.
+ - for the most superior, it will have no superiors, just
+ subordinates only, so its dimensions will be determined
+ thusly.
+
+ In all of this, this layout will take place everytime the application
+ window is resized, so be aware of this. The computaitons shall be swift,
+ just basic MDAS arithemtic. Nothing heavy-duty or fancy.
+
+**** JUNKYARD Superior layout calculations
+ For the superior layout, we calculate the x and height,
+ or the y and width respectively, for the boxes. Floating
+ status becomes critical here, for the above will only
+ need to be determined thusly for the non-floating cases,
+ where there is dependency on the superior's dimensions
+ and position.
+**** JUNKYARD Debug layout dump
+ #+begin_src
+-->PureText unresolved: comparison of NilClass with 20 failed
+-->Graph: unresolved: undefined method `-' for nil:NilClass
+ left dom=0 xywh=[0,0,0,300] LRTB=[0,0,0,0]
+ right dom=0 xywh=[400,0,0,300] LRTB=[0,0,0,0]
+ top dom=0 xywh=[0,0,400,0] LRTB=[0,0,0,0]
+ bottom dom=0 xywh=[0,300,400,0] LRTB=[0,0,0,0]
+ Fox::Enhancement::Xtras::Charting::Title dom=1 xywh=[190,0,20,10] LRTB=[0,0,0,0] floater
+ Fox::Enhancement::Xtras::Charting::Caption dom=1 xywh=[190,290,20,10] LRTB=[0,0,0,0] floater
+ Fox::Enhancement::Xtras::Charting::Legend dom=1 xywh=[350,135,50,30] LRTB=[0,0,0,0] floater
+
+ Fox::Enhancement::Xtras::Charting::TopRuler dom=2 xywh=[NIL,10,20,10] LRTB=[0,0,0,0]
+ Fox::Enhancement::Xtras::Charting::BottomRuler dom=2 xywh=[NIL,280,20,10] LRTB=[0,0,0,0]
+ Fox::Enhancement::Xtras::Charting::LeftRuler dom=2 xywh=[0,NIL,20,10] LRTB=[0,0,0,0]
+ Fox::Enhancement::Xtras::Charting::RightRuler dom=2 xywh=[330,NIL,20,10] LRTB=[0,0,0,0]
+
+ Fox::Enhancement::Xtras::Charting::Graph dom=3 xywh=[-20,0,350,280] LRTB=[0,0,0,0]
+ Fox::Enhancement::Xtras::Charting::Graph dom=3 xywh=[-20,0,350,280] LRTB=[0,0,0,0]
+
+ Fox::Enhancement::Xtras::Charting::TopRuler dom=2 xywh=[-20,10,350,10] LRTB=[0,0,0,0]
+ Fox::Enhancement::Xtras::Charting::BottomRuler dom=2 xywh=[-20,280,350,10] LRTB=[0,0,0,0]
+ Fox::Enhancement::Xtras::Charting::LeftRuler dom=2 xywh=[0,0,20,280] LRTB=[0,0,0,0]
+ Fox::Enhancement::Xtras::Charting::RightRuler dom=2 xywh=[330,0,20,280] LRTB=[0,0,0,0]
+
+ Fox::Enhancement::Xtras::Charting::Title dom=1 xywh=[190,0,20,10] LRTB=[0,0,0,0] floater
+ Fox::Enhancement::Xtras::Charting::Caption dom=1 xywh=[190,290,20,10] LRTB=[0,0,0,0] floater
+ Fox::Enhancement::Xtras::Charting::Legend dom=1 xywh=[350,135,50,30] LRTB=[0,0,0,0] floater
+ #+end_src