New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

fxruby-enhancement

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fxruby-enhancement

  • 0.2.3
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

#+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]]
        • [[#the-queue_ding-queues][The Queue_Ding Queues]]
          • [[#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]]
        • [[#bindingfx][binding.fx]]
      • [[#examples][Examples]]
        • [[#hello-world-example-full-the-enhancement-way][Hello World example (full) the Enhancement Way]]
        • [[#hello-world-the-old-fxruby-way][Hello World the old fxruby way:]]
        • [[#bouncing-ball-example-full][Bouncing Ball example (full):]]
        • [[#bouncing-ball-the-old-fxruby-way][Bouncing Ball the old fxruby way:]]
        • [[#datatarget-example][DataTarget Example]]
    • [[#release-notes][Release Notes]]
    • [[#known-issues][Known Issues]]
    • [[#contributing-to-fxruby-enhancement][Contributing to fxruby-enhancement]]
    • [[#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 fxruby, you are handed back a reference to that object, which you'll need to store somewhere. And then all the subsequent child objects will need to be passed pointers to the parent objects.

So, if you need to redo a layout, it becomes a messy exercise.

fxruby-enhancement makes this a snap to do. You simply declare your GUI arrangement in a nested fashion. fxruby-enhancement will take care of passing parents to the nested children, and other issues as well. You can now focus on creating your great GUI layout that you can change on the fly without much fuss and bother.

fxruby-enhancement (also referred to as "Enhancement") is basically a DSL of sorts, and every effort has been taken to make it intuitive to use. Once you get the hang of it, you should be able to look at the FXRuby API documentation and infer the DSL construct for fxruby-enhancement. Please also see the many [[file:examples][examples]].

Enhancement basically leverages Ruby's singleton feature, and eliminates the need to "subclass" the FXRuby objects and the like. In fact, you might even consider this Enhancement's own "paradigm" for doing GUI programming.

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&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted][Donations are appreciated.]]

** Installation Requirements: You must have Fox16 installed on your system. Depending on your operating system, the details will vary. And currently on MacOSX you will also need to install X-Windows. Here, we link you to the details provided by FXRuby for your particular environment:

OS Details | Linux | https://github.com/lylejohnson/fxruby/wiki/Setting-Up-a-Linux-Build-Environment | | Mac OSX | https://github.com/lylejohnson/fxruby/wiki/Setting-Up-a-Mac-OS-X-Development-Environment | | Windows | https://github.com/lylejohnson/fxruby/wiki/Setting-Up-a-Windows-Build-Environment |

To install the gem from commandline:

#+begin_src bash gem install fxruby-enhancement #+end_src

In your Gemfile:

#+begin_src ruby gem "fxruby-enhancement", "~> 0" #+end_src

fxruby-enhacement depends on fxruby version 1.6, and will automatically include it. However fxruby has a c-extension that must compile properly on your system. Normally, this is not a concern, but it is something to be aware of.

** Documentation *** In General fxruby-enhancement (which we will refer to as "Enhancement" from time to time) makes use of the singleton pattern in Ruby. There is basically no need to declare subclases off of most FXRuby classes. This is a very C++ish way, and the way the C++ Fox Toolkit works. It will make most hard-core Rubyists gnash their teeth.

Here, we do away with all of it. Also, the SEL_x variables -- which maps
to the C++ #defines of the same -- is replaced with method declarations
of the nature of sel_x -- just the lowercase version of the same. For instance,
in the straight fxruby, you would have to do something like:

#+begin_src ruby
@canvas.connect(SEL_PAINT) { |sender, sel, evt|
  FXDCWindow.new(sender, evt) { |dc|
    dc.drawImage(@backBuffer, 0, 0)
  }
#+end_srcv

but with Enhancement, you do it thusly:

#+begin_src ruby
instance { |c|
  c.sel_paint { |sender, sel, event|
    FXDCWindow.new(sender, event) { |dc|
      dc.drawImage(ref(:back_buffer), 0, 0)
    }
  }
}
#+end_src

And here we illustrate something else, the instance declaration. Why do
we do it this way? Because Enhancement is multi-phase. First, we declare
the GUI layout with Enhancement. At this time, none of the underlying
FXRuby objects exist yet, but need to be referenced anyway. So we defer
that part where references need to be resolved to the instance claus,
which, as you can well imagine, means the FXRuby object instances have
been instantiated.

You will also note the use of the ref clause, as in:
#+begin_src ruby
dc.drawImage(ref(:back_buffer), 0, 0)
#+end_src

When the :back_buffer object was declared, it was done thusly:
#+begin_src ruby
fx_image(:back_buffer) { opts IMAGE_KEEP }
#+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. | | FXRuby instantiation | All the basic underlying FXRuby object are instantiatied, but the foundational FOX Toolkit Objects are not instantiated yet. | | FOX Toolkit instantiation | The FOX Toolkit C++-level objects are now alive and kicking. |

**** Declarative This phase, under the proverbial hood, ceates the component objects, which are just place-holders for the underlying FXRuby objects.

 When the FXRuby object is created, it is assigned to its place holder
 component object, and can be references as comp.inst. In most cases,
 you will almost never need to touch the component objects directly.

**** FXRuby Instantiation During the FXRuby instantiantion stage, all of the FXRuby objects are instantiated and stored in their respective component objects. If they are tagged, the instantiated object may be referenced with ref(), and the component object itself may be referenced via refc(). There is almost never a case where you would need to go after the component object directly. **** FOX Toolkit instantiation All of the FOX Toolkit C++ objects, resources, etc. that correspond to the FXRuby objects are now set up, and activated. With the all-important "show PLACEMENT_SCREEN" command, the FOX GUI should now be visible. *** Events from other Threads In handling interfacing to databases, AMQPs like RabbitMQ, network connections, or just about anything else that might otherwise slow down the GUI (Fox) thread and make it non-responsive, there needs to be a clean way to get data into and out of the GUI thread.

Fox provides some mechanisms specifically for sockets or system-level IO,
but these are too specific, and would require some awkard workarounds to
make them work in the general context.

And so we provide a means to accomplish that in a clean -- to you, anyway --
manner. We make use of queue_ding queues for passing messages into and out of
the FXRuby (and therefore FXRuby Enhancement) space. This will allow you to
keep the GUI thread responsive and also to maintain a seperation of concerns.

**** The Queue_Ding Queues [[ttps://github.com/flajann2/queue_ding][Queue Ding]] is an enhancement for doing queing across threads in Ruby, and we offer it here to allow external events to be funneled into and out of the Fox GUI thread. Usage is easy and straightforard. When removing entries from Queue Ding using #next, the queue will block until the next entry arrives. Since Queue Ding is really derived from ::Array, you may also do thing like #empty? to check to see if entries are availabe to avoid blocking. ***** Enhancement.ingress To get messages objects into fxruby_enhacement, simply #push or #<< it into the queue as shown: #+begin_src ruby Enhancement.ingress << [:some_tag, some_payload] #+end_src

  In the DSL, you must set up a handler for the ingress,
  #+begin_src ruby
  ingress_handler :status do |tag, payload|
    puts "received #{tag} => #{payload}"
  end
  #+end_src

  And so your handler will most likely act as a dispatcher
  for the payloads received. For example:
  #+begin_src ruby
  ingress_handler :log_info, :log_error do |tag, logline|
    puts "received #{tag} => #{payload}"
    case tag
    when :log_info
      ref(:logging_info).appendItem logline
    when :log_error
      ref(:logging_error).appendItem logline
    end
  end
  #+end_src

  Note that this ingress handler is responding to two tags. You can have
  as many tags as you like for your ingress handler, and as many
  ingress handlers as you like. 
  
  Currently, all the tags should be unique. Later we may support having 
  multiple blocks associated with the same tag. Please feel free to generate
  an issue if you want this!!!

***** Enhancement.egress Wnen your Fox application needs to send a message to other listening threads, You simply push your payload onto the egress queue thusly: #+begin_src ruby Enhancement.egress << [:button_clicked, "I was clicked!"] #+end_src

  and your Ruby thread external to Fox would simply do:
  #+begin_src ruby
  ...
  message = Enhancement.egress.next
  ...
  #+end_src
  
  where you'll block pending the arrival of the next message. If you
  do not wish to block, you may do:
  #+begin_src ruby
  ...
  unless Enhancement.egress.empty?
    message = Enhancement.egress.next 
  else
    # some action to take
  end
  ...
  #+end_src

*** Reusable components and dynamic creation, and the 'reuse' flag There are times you may want to be able to create, and popup, say, a dialog box, or perhaps you want to create on the fly child components on an existing window.

This is made possible with the "reuse: true" flag. For example:
#+begin_src ruby
fx_dialog_box(:dialog, reuse: true) {
  title "I am a Dialog!"
  opts DECOR_ALL
  
  fx_button {
    text "&It Works!"
    instance { |dia|
      dia.sel_command {
        refc(:dialog).stoppen
      }
    }
  }      
  instance { |dia| dia.show PLACEMENT_OWNER  }
}
#+end_src

This code snippet can be run in the context of the app or a window. 
If you do it in a window context, that window will become the "owner",
and will initially be placed hovering over it.

With reusable components, you will use the #starten and #stoppen methods
to create and destroy the component. Please see
the [[file:examples/dialog_box.rb][Dialog Box]] for a full example, and also
the docs for #starten and #stoppen.

*** API & DSL **** ref(), refc() and tagging your objects In an effort to eliminate the fuss and bother with scoping issues and object reference, ref(:some_tag) will retrive the FXRuby instance object so tagged with :some_tag.

 You may have anonymous, i.e., untagged objects, and those will
 not be findable by ref(). It is not necessary to tag all objects,
 either.

 refc() is similar to ref(), except it retrives the underlying 
 component object insted. Indeed, the following are equivalent
 operations:
 #+begin_src ruby
 ref(:some_tag)
 refc(:some_tag).inst
 #+end_src

 Where might you want to use refc() instead of ref()? In cases
 where the underlying FXRuby object have not been instantiated yet,
 you'd use refc() instead of ref(), almost always during the component
 configuration. For example:
 #+begin_src ruby
 fx_app :app do
 ...
   fx_button {
     text "&See Ya!"
     selector FXApp::ID_QUIT
     target refc(:app)
   }
 ...
 #+end_src
 
 Here, we set the button to exit the application by sending the FXApp object the ID_QUIT
 message. But at the time we set the configuration, the FXApp object has not been instantiated
 yet. So we use refc() instead of ref().
 
 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.

 At some point, they may be merged, but for now don't 
 count on it.

 To initialize and run your app, you customairly do the
 following:
 #+begin_src ruby
 fox_component :app do |app|
   app.launch
 end
 #+end_src

 Which presumes your fx_app declaration was tagged with
 :app as follows:
 #+begin_src ruby
 fx_app :app do
   app_name "Your Amazingly Cool Application"
   vendor_name "YouDaMan"
   ...
 end
 #+end_src

 This is the only time you will reference the component
 object directly for the obvious reason that you must start
 from someonere.

**** fx_app To begin the declaration of your app, you must do the following somewhere: #+begin_src ruby fx_app :app do app_name "The Forbin Project" vendor_name "Colossus" ... end #+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 during 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 object has not been created yet.

 Enter refc(). You use refc(), instead of ref(), to use it when you are
 configuring the component (really, specifying the initial parameters
 to the underlying FXRuby class!) We illustrate here:
 #+begin_src ruby
 ...
 fx_data_target (:mydata) { value "initial value"  }
 ...
 fx_text (:text_3) {
   target refc(:mydata)
   selector FXDataTarget::ID_VALUE
 }
 fx_text (:text_4) {
   target refc(:mydata)
   selector FXDataTarget::ID_VALUE
 }
 #+end_src

 And so the two text components  -- or widgets -- are initially
 set to the value of "initial value", and when one changes, the
 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 a reference to the FXRuby object, allowing you to set up connections, change the component state, etc.

 There are some added benefits as well. When making a connection,
 with the normal FXRuby, you would do something like this:
 #+begin_src ruby
 ...
 aButton.connect(SEL_COMMAND)  { |sender, selector, data|
   ... code to handle this event ...
 }
 #+end_src

 But with Enhancement, you would be able to do it thusly:
 #+begin_src ruby
 fx_button(:my_button) {
   ... configs for this FXButton object ...
   instance { |button|
     button.sel_command { |sender, selector, data|
       ... code to handle this event ...
     }
   }
 }
 #+end_src

 which will make it feel more Ruby-like and less C++-like.

**** ingress_handler ingress_handler will allow you to set up the handler for messages coming in from an external source to FXRuby thread, such as RabbitMQ, network connections, databases, or anything else. It allows you to do clean multhreaded Ruby without the normal worries of semaphores and synchronization and the like -- it is all handled for you "magically" behind the scenes!

 You may have as many ingress_handlers specified as you like, as
 each one needs to have a tag, and the tags are used to dispatch
 the messages.

 Here is an example taken from RubyNEAT Panel:
 #+begin_src ruby
 ingress_handler :status do |type, status|
   suc, st = status.response
  
   wlist = ref :ov_conn_neaters_widget_list
   wlist.clearItems
   st[:neaters].each { |neater| wlist.appendItem neater }

   nlist = ref :ov_conn_neurons_list
   nlist.clearItems
   st[:neurons].each { |neuron| nlist.appendItem neuron}
 end
 #+end_src
 
 Here you can see that a status message has been dispatched to 
 this ingress_handler, and that the message contains a list of
 'neaters' and 'neurons' that are being sent to the wlist
 and nlist list (:ov_conn_neaters_widget_list and :ov_conn:_neurons_list),
 respecively.

 You may declare your ingress_handler anywhere in your code and have 
 the expected happen.

 igress_handler may also be specified with more than one tag, for
 instance:
 #+begin_src ruby
 ingress_handler :warn, :info, :error do |type, log|
   case type
   when :warn
     ...
   when :info
     ...
   when :error
     ...
   else
     raise "Unknown log type"
   end
 end
 #+end_src

 The same block is assigned to all the given tags of :warn, :info, and :error.

**** #starten and #stoppen with resuable components To designate a component as reusable, declare it with "reuse: true" as in the example: #+begin_src ruby fx_dialog_box(:dialog, reuse: true) { ... } #+end_src

 Then in the instance clause or to the response to an event,
 you would do:
 #+begin_src ruby
 refc(:dialog).starten
 #+end_src

 to activate it, and
 #+begin_src ruby
 refc(:dialog).stoppen
 #+end_src

 to deactive it (and remove the 'server'-side FOX components!)

 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
 binding.fx "overview"
 #+end_src

 will load the overview.fx portion of the GUI, which happens to be a tab contents
 in the tab book, which in our case looks like:

 #+begin_src ruby
 # Overview Tab

 fx_tab_item { text "&Overview" }
 fx_horizontal_frame (:overview_info) {
   opts STD_FRAME|LAYOUT_FILL_Y

   fx_group_box (:ov_connections_group) {
     text "Connections"
     opts STD_GROUPBOX|LAYOUT_FILL_Y

     fx_vertical_frame {
       opts LAYOUT_FILL_Y|LAYOUT_FILL_X #|PACK_UNIFORM_HEIGHT
  
       fx_group_box (:ov_conn_rabbitmq) {
 ...
 #+end_src

*** Examples Because this is a spinoff project of the ongoing RubyNEAT effort, there is a splendid RubyNEAT Panel example, that is still in the works. However, you are free to look at the code that is there to get good ideas.

https://github.com/flajann2/rubyneat-panel/tree/master/lib/rubyneat-panel

Class-based Enhancement (this is currently not supported!!!):
#+begin_src ruby
class Main < FXMainWindow
  compose :my_window do
    title "RubyNEAT Panel"
    show PLACEMENT_SCREEN
    width 700
    height 400
    fx_tab_book :my_book do |tab_book_ob|
      x 0
      y 0
      width 500
      height 100
      pad_bottom 10
      fx_text :my_text1, :my_window { |text_ob|
        width 200
        height 100
        text_ob.target my_window: :on_click
      }
      fx_text :my_text2, :my_window { |text_ob|
        width 200
        height 100
        text_ob { |t| puts "called after object initialization" }
      }
    end
  end

  def on_click
    ...
  end
end    
#+end_src

Class-free Enhancement (strongly recommended):
#+begin_src ruby
mw = fx_main_window :my_window do 
    title "RubyNEAT Panel"
    width 700
    height 400
    opts DECOR_ALL
    x 10
    y 10
    instance { show PLACEMENT_SCREEN }
    fx_tab_book :my_book do |tab_book_ob|
      x 0
      y 0
      width 500
      height 100
      pad_bottom 10
      fx_text :my_text1, :my_window { |text_ob|
        width 200
        height 100
        instance my_window: :on_click
      }
      fx_text :my_text2, :my_window { 
        width 200
        height 100
        instance { |t| puts "called after object initialization" }
      }
    end
  end

  def mw.on_click
    ...
  end
end    
#+end_src

**** [[file:examples/hello.rb][Hello World]] example (full) the Enhancement Way #+begin_src ruby #!/usr/bin/env ruby require 'fxruby-enhancement'

include Fox include Fox::Enhancement::Mapper

fx_app :app do app_name "Hello" vendor_name "Example"

fx_main_window(:main) { title "Hello" opts DECOR_ALL

fx_button {
  text "&Hello, World"
  selector FXApp::ID_QUIT
  
  instance { |b|
    b.target = ref(:app)
  }
}

instance { |w|
  w.show PLACEMENT_SCREEN
}

} end

alias for fox_component is fxc

fox_component :app do |app| app.launch end #+end_src

**** Hello World the old fxruby way: #+begin_src ruby #!/usr/bin/env ruby

require 'fox16'

include Fox

application = FXApp.new("Hello", "FoxTest") main = FXMainWindow.new(application, "Hello", nil, nil, DECOR_ALL) FXButton.new(main, "&Hello, World!", nil, application, FXApp::ID_QUIT) application.create() main.show(PLACEMENT_SCREEN) application.run() #+end_src

Even though the old way has a slightly smaller line count, you can
see how messy it can be assigning each newly-created object to
a variable, and then having to pass that variable to the children.
Perhaps this example is too small, but perhaps the next one will
more illustrative.

**** [[file:examples/bounce.rb][Bouncing Ball]] example (full): #+begin_src ruby #!/usr/bin/env ruby require 'fxruby-enhancement'

include Fox include Fox::Enhancement::Mapper

ANIMATION_TIME = 20

class Ball attr_reader :color attr_reader :center attr_reader :radius attr_reader :dir attr_reader :x, :y attr_reader :w, :h attr_accessor :worldWidth attr_accessor :worldHeight

def initialize r @radius = r @w = 2*@radius @h = 2*@radius @center = FXPoint.new(50, 50) @x = @center.x - @radius @y = @center.y - @radius @color = FXRGB(255, 0, 0) # red @dir = FXPoint.new(-1, -1) setWorldSize(1000, 1000) end

Draw the ball into this device context

def draw(dc) dc.setForeground(color) dc.fillArc(x, y, w, h, 0, 6490) dc.fillArc(x, y, w, h, 6490, 64180) dc.fillArc(x, y, w, h, 64180, 64270) dc.fillArc(x, y, w, h, 64270, 64*360) end

def bounce_x @dir.x=-@dir.x end

def bounce_y @dir.y=-@dir.y end

def collision_y? (y<0 && dir.y<0) || (y+h>worldHeight && dir.y>0) end

def collision_x? (x<0 && dir.x<0) || (x+w>worldWidth && dir.x>0) end

def setWorldSize(ww, wh) @worldWidth = ww @worldHeight = wh end

def move(units) dx = dir.xunits dy = dir.yunits center.x += dx center.y += dy @x += dx @y += dy if collision_x? bounce_x move(units) end if collision_y? bounce_y move(units) end end end

fx_app :app do app_name "Bounce" vendor_name "Example"

fx_image(:back_buffer) { opts IMAGE_KEEP }

fx_main_window(:bounce_window) { title "Bounce Demo" opts DECOR_ALL width 400 height 300

instance { |w|
  def w.ball
    @ball ||= Ball.new(20)
  end
  
  def w.drawScene(drawable)
    FXDCWindow.new(drawable) { |dc|
      dc.setForeground(FXRGB(255, 255, 255))
      dc.fillRectangle(0, 0, drawable.width, drawable.height)
      ball.draw(dc)
    }
  end
  
  def w.updateCanvas
    ball.move(10)
    drawScene(ref(:back_buffer))
    ref(:canvas).update
  end
  
  #
  # Handle timeout events
  #
  def w.onTimeout(sender, sel, ptr)
    # Move the ball and re-draw the scene
    updateCanvas
    
    # Re-register the timeout
    ref(:app).addTimeout(ANIMATION_TIME, ref(:bounce_window).method(:onTimeout))
    
    # Done
    return 1
  end
  
  w.show PLACEMENT_SCREEN
  ref(:app).addTimeout(ANIMATION_TIME, w.method(:onTimeout))
}

fx_canvas(:canvas) {
  opts LAYOUT_FILL_X|LAYOUT_FILL_Y
  
  instance { |c|
    c.sel_paint { |sender, sel, event|
      FXDCWindow.new(sender, event) { |dc|
        dc.drawImage(ref(:back_buffer), 0, 0)
      }
    }

    c.sel_configure{ |sender, sel, event|
      bb = ref(:back_buffer)
      bb.create unless bb.created?
      bb.resize(sender.width, sender.height)
      ref(:bounce_window) do |bw|
        bw.ball.setWorldSize(sender.width, sender.height)
        bw.drawScene(bb)
      end
    }
  }
}

} end

if FILE == $0

alias for fox_component is fxc

fox_component :app do |app| app.launch end end #+end_src

**** Bouncing Ball the old fxruby way: #+begin_src ruby require 'fox16'

include Fox

How long to pause between updates (in milliseconds)

ANIMATION_TIME = 20

class Ball

attr_reader :color attr_reader :center attr_reader :radius attr_reader :dir attr_reader :x, :y attr_reader :w, :h attr_accessor :worldWidth attr_accessor :worldHeight

Returns an initialized ball

def initialize(r) @radius = r @w = 2*@radius @h = 2*@radius @center = FXPoint.new(50, 50) @x = @center.x - @radius @y = @center.y - @radius @color = FXRGB(255, 0, 0) # red @dir = FXPoint.new(-1, -1) setWorldSize(1000, 1000) end

Draw the ball into this device context

def draw(dc) dc.setForeground(color) dc.fillArc(x, y, w, h, 0, 6490) dc.fillArc(x, y, w, h, 6490, 64180) dc.fillArc(x, y, w, h, 64180, 64270) dc.fillArc(x, y, w, h, 64270, 64*360) end

def bounce_x @dir.x=-@dir.x end

def bounce_y @dir.y=-@dir.y end

def collision_y? (y<0 && dir.y<0) || (y+h>worldHeight && dir.y>0) end

def collision_x? (x<0 && dir.x<0) || (x+w>worldWidth && dir.x>0) end

def setWorldSize(ww, wh) @worldWidth = ww @worldHeight = wh end

def move(units) dx = dir.xunits dy = dir.yunits center.x += dx center.y += dy @x += dx @y += dy if collision_x? bounce_x move(units) end if collision_y? bounce_y move(units) end end end

class BounceWindow < FXMainWindow

include Responder

def initialize(app) # Initialize base class first super(app, "Bounce", :opts => DECOR_ALL, :width => 400, :height => 300)

# Set up the canvas
@canvas = FXCanvas.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)

# Set up the back buffer
@backBuffer = FXImage.new(app, nil, IMAGE_KEEP)

# Handle expose events (by blitting the image to the canvas)
@canvas.connect(SEL_PAINT) { |sender, sel, evt|
  FXDCWindow.new(sender, evt) { |dc|
    dc.drawImage(@backBuffer, 0, 0)
  }
}

# Handle resize events
@canvas.connect(SEL_CONFIGURE) { |sender, sel, evt|
  @backBuffer.create unless @backBuffer.created?
  @backBuffer.resize(sender.width, sender.height)
  @ball.setWorldSize(sender.width, sender.height)
  drawScene(@backBuffer)
}

@ball = Ball.new(20)

end

Draws the scene into the back buffer

def drawScene(drawable) FXDCWindow.new(drawable) { |dc| dc.setForeground(FXRGB(255, 255, 255)) dc.fillRectangle(0, 0, drawable.width, drawable.height) @ball.draw(dc) } end

def updateCanvas @ball.move(10) drawScene(@backBuffer) @canvas.update end

Handle timeout events

def onTimeout(sender, sel, ptr) # Move the ball and re-draw the scene updateCanvas

# Re-register the timeout
getApp().addTimeout(ANIMATION_TIME, method(:onTimeout))

# Done
return 1

end

Create server-side resources

def create # Create base class super

# Create the image used as the back-buffer
@backBuffer.create

# Draw the initial scene into the back-buffer
drawScene(@backBuffer)

# Register the timer used for animation
getApp().addTimeout(ANIMATION_TIME, method(:onTimeout))

# Show the main window
show(PLACEMENT_SCREEN)

end end

if FILE == $0 FXApp.new("Bounce", "FXRuby") do |theApp| BounceWindow.new(theApp) theApp.create theApp.run end end #+end_src

The Ball class is the same, but the actual Fox-related code
should clearly illustrate the power of Enhancement.

More examples can be found [[file:examples][HERE]].

**** DataTarget Example fx_data_target (:some_name) must be referenced as refc(:some_name) and not ref(...). See the example below.

 #+begin_src ruby

#!/usr/bin/env ruby require 'fxruby-enhancement'

include Fox include Fox::Enhancement::Mapper

fx_app :app do app_name "DataTarget" vendor_name "Example"

fx_data_target (:textx) { value "x marks the spot!" } fx_data_target (:texty) { value "y do it?" }

fx_main_window(:main) { title "fx_data_target example" opts DECOR_ALL width 300 x 100 y 200

fx_text_field (:text_1) {
  ncols 40
  target refc(:textx)
  selector FXDataTarget::ID_VALUE
}
fx_text_field (:text_2) {
  ncols 40
  target refc(:textx)
  selector FXDataTarget::ID_VALUE
}
fx_text (:text_3) {
  opts LAYOUT_FILL_X
  target refc(:texty)
  selector FXDataTarget::ID_VALUE
}
fx_text (:text_4) {
  opts LAYOUT_FILL_X
  target refc(:texty)
  selector FXDataTarget::ID_VALUE
}
fx_button {
  text "&See ya!"
  selector FXApp::ID_QUIT
  opts BUTTON_NORMAL|LAYOUT_CENTER_X
  
  instance { |b|
    b.target = ref(:app)
  }
}

instance { |w|
  w.show PLACEMENT_SCREEN
}

} end

alias for fox_component is fxc

fox_component :app do |app| app.launch end #+end_src

** Release Notes | 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.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.
  • Fork the project.
  • Start a feature/bugfix branch.
  • Commit and push until you are happy with your contribution.
  • Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

** Copyright and Licensing Copyright (c) 2016-2017 Fred Mitchell. See [[file:LICENSE.txt][MIT License]] for further details. ** The Junkyard / Scratchpad These are my personal notes, not meant for anyone else. You may see some interesting tidbits here, but I am not gauranteeing anything to be useful or reliable in this section. YOU HAVE BEEN WARNED. *** JUNKYARD Genesis of the meta-meta programming, whereby brain goes boom #+begin_src ruby class FXToolBar # monkey patch include Enhancement attr_accessor :_o end

def fx_tool_bar name, &block # DSL
  o = OStruct.new
  o.title = "default title"
  ...

  def o.title t 
    @title = t
  end    

  def o.instance a, &block
    o.instance_time_block = block
  end
  f = FXToolBar.new ...
  f._o = o
end

<% for @class, @details in @api %> #<%= @class %> < <%= @details[:class][1] %> <% unless @details[:initialize].nil? %> <% for @iniparams in @details[:initialize] %> #<%= @iniparams %>
<% end %> <% else %> #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 fxruby components, because they have a different workflow. Basically, they need to be instantiated before the other comonents that uses them, and they are not really "child" objects, either. Referring to them using the ref() or refc() approach simply fails, because they won't be instantiated in time.

 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

FAQs

Package last updated on 15 Dec 2017

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc