Wednesday, February 17, 2016

Areas and Sections in Medusa

Today I will show you a feature that might be interesting for you, sections and areas in gauges and clocks.
Sometimes you want to visualize a special area in your gauge like the red area in a rpm gauge.
To realize this in Medusa you simply can add a so called Section object. 
A Section object has the following properties

  • start (defines the value where the section should start)
  • stop (defines the value where the section should stop)
  • text (defines a text that can/will be drawn in some gauges)
  • icon (defines an image that can be used in some gauges)
  • color (defines the color that will be used to colorize the section)
  • highlightColor (defines the color that will be used for highlighting the section)
  • textColor (defines the color that will be used to colorize the text)
Because the Section can also fire two events
  • Event when value entered the Section
  • Event when value left the Section
Therefore you will find methods to add EventHandlers to the Section
  • setOnSectionEntered(EventHandler<SectionEvent> handler)
  • setOnSectionLeft(EventHandler<SectionEvent> handler)
Those events will only be fired if you enable it in the Medusa gauge or clock. The method to enable the event handling is 
  • checkSectionsForValue(true/false)
If this property is enabled the final value of the gauge will be checked against each Section that was defined for the gauge and events will be fired if a value entered or left a Section.
This feature can be used to control stuff for example send MQTT messages etc. when a value entered and left a Section in a Medusa clock.


If you would like to add it in a more prominent way you could add this Section object as a so called area which will look as follows.


The code that you need to create this area looks like follows
Gauge gauge = GaugeBuilder.create()
                          .areasVisible(true)
                          .areas(new Section(75, 100, Color.RED))
                          .build();
If you prefer a more reserved visualization you might want to add the same Section object as a section instead of an area. In this case it would look like this...


For adding a section like seen on the image above you have to use the following code instead...
Gauge gauge = GaugeBuilder.create()
                          .sectionsVisible(true)
                          .sections(new Section(75, 100, Color.RED))
                          .build();
You could also use both, sections and areas at the same time where sections will always be drawn on top of areas. Here is a little example...

Adding a section and an area you simply combine both code snippets like this...
Gauge gauge = GaugeBuilder.create()
                          .areasVisible(true)
                          .areas(new Section(75, 100, Color.ORANGE))
                          .sectionsVisible(true)
                          .sections(new Section(75, 100, Color.RED))
                          .build();
That's nice so far but sometimes you don't want to have your UI look like a parrot but more clean. In this case you might want to show the section only if the current value is inside the section and otherwise the section should be dimmed or transparent.
For this scenario I've implemented the highlighting feature which is available for sections and areas in Medusa gauges and Medusa clocks.

As an example let's create a gauge with four sections. Each section should only be visible if the current value is inside the section. Here is the code you need for this scenario...
Gauge gauge = GaugeBuilder.create()
                          .sectionsVisible(true)
                          .checkSectionsForValue(true) 
                          .highlightSections(true)
                          .sections(new Section(0, 25, Color.TRANSPARENT, Color.rgb(0, 0, 222)),
                                    new Section(25, 50, Color.TRANSPARENT, Color.rgb(0, 222, 0)),
                                    new Section(50, 75, Color.TRANSPARENT, Color.rgb(222, 222, 0)),
                                    new Section(75, 100, Color.TRANSPARENT, Color.rgb(222, 0, 0)))
                          .animated(true)
                          .build();
As you can see we define the standard color for each section as Color.TRANSPARENT which means the sections are invisible by default. The highlight colors are defined as the real section color.
To make use of this feature we also have to set checkSectionsForValue(true) and highlightSections(true). The result would look like follows...


If this is too confusing for you it is also possible to use dimmed colors for the section colors instead. In that case the code might look like this...
Gauge gauge = GaugeBuilder.create()
                          .sectionsVisible(true)
                          .checkSectionsForValue(true)
                          .highlightSections(true)
                          .sections(new Section(0, 25, Color.rgb(0, 0, 222, 0.2), Color.rgb(0, 0, 222)), 
                                    new Section(25, 50, Color.rgb(0, 222, 0, 0.2), Color.rgb(0, 222, 0)),
                                    new Section(50, 75, Color.rgb(222, 222, 0, 0.2), Color.rgb(222, 222, 0)),
                                    new Section(75, 100, Color.rgb(222, 0, 0, 0.2), Color.rgb(222, 0, 0)))
                          .animated(true)
                          .build();
And the visual result of that code will look like this...


As you can see the current value is in the green section which is drawn with the full opaque version of the color where all other sections are drawn with the transparent colors.
The same feature is also available in the Medusa clock but here we use the TimeSection which has the same properties and functionality as the gauge section but uses LocalTime objects instead of double values for the start and stop values. Because it's very much the same as with the gauges I'll just give you a short example of a clock. 
Clock clock = ClockBuilder.create()
                          .sectionsVisible(true)
                          .checkSectionsForValue(true)
                          .highlightSections(true)
                          .sections(new TimeSection(LocalTime.now().plusSeconds(20), LocalTime.now().plusHours(1), Color.rgb(0, 100, 200, 0.2), Color.rgb(0, 100, 200)))
                          .running(true)
                          .build();
And when we run that code we first will see the following clock...


As you can see the section will be drawn with the transparent color because the current time has not reached the section yet.
After a couple of seconds the current time is "inside" of the section and therefore the section will be highlighted as follows...

With this you could visualize different things like for example appointments on your calendar etc.

That's it for today...keep coding... 

3 comments:

  1. Hi Gerrit,

    Firstly, congratulations on building such an awesome library of controls. You are definitely someone I look up to in awe as the guru of JavaFX controls!

    I am just curious why you decided to use the Builder concept in Medusa when it was removed from JavaFX itself some time ago.

    Personally, I think builders are a great idea and never really grasped why Oracle decided to abandon the pattern in core JavaFX.

    Can you offer some commentary on this issue?

    Blessings,

    Felix

    ReplyDelete
    Replies
    1. Hi Felix,
      The answer is very easy, I simply like the builder pattern and because of that I use it :)
      So I decided to create the builders for my controls for your convenience :)
      Cheers,
      Gerrit

      Delete
  2. Felix,
    The builder pattern is great! You should continue using the pattern in your own apis, but core JavaFX from 2.0 builders needed to be removed.
    The JavaFX team removed them due to a bug on backwards compatibility. http://mail.openjdk.java.net/pipermail/openjfx-dev/2013-March/006725.html

    Great work Gerrit!

    Carl

    ReplyDelete