Sunday, July 22, 2018

Rolling Gradient

Aloha,

Last week I've stumbled upon an old blogpost from 2011 where I implemented an animated progressbar in Java Swing. At that time I was fascinated by the animated progressbar in OS X.
And when I saw the animated gradient I thought by myself why not do that in JavaFX???
In Swing we have immediate mode rendering which makes these kind of animated gradients easy because you do the whole rendering on your own. In JavaFX where we have retained mode rendering (so the rendering is managed by JavaFX) you have to find a way to update the gradient fill for a node for each animation step.
My approach is as follows, the RollingGradient uses an AnimationTimer to calculate the gradient and on each modification it fires an UpdateEvent which can be used to fill a shape with the gradient. The gradient is part of the event.
If you simply would like to fill a JavaFX shape you can also set the shape in the RollingGradient and it will be filled from there.

So you could either use the event as follows:

Rectangle       rectangle = new Rectangle(200, 20);
RollingGradient gradient  = RollingGradientBuilder.create()
                                                  .firstColor(Color.rgb(250, 0, 0))
                                                  .secondColor(Color.rgb(180, 0, 0))
                                                  .smoothGradient(true)
                                                  .direction(Direction.LEFT)
                                                  .interval(Speed.NORMAL.getInterval())
                                                  .period(5)
                                                  .onUpdateEvent(e -> rectangle.setFill(e.getGradient()))
                                                  .start()
                                                  .build();

Or you can set the shape in the RollingGradient and let it do the fill as follows:


Rectangle       rectangle = new Rectangle(200, 20);
RollingGradient gradient  = RollingGradientBuilder.create()
                                                  .firstColor(Color.rgb(250, 0, 0))
                                                  .secondColor(Color.rgb(180, 0, 0))
                                                  .smoothGradient(true)
                                                  .direction(Direction.LEFT)
                                                  .interval(Speed.NORMAL.getInterval())
                                                  .shape(rect)
                                                  .period(5)
                                                  .start()
                                                  .build();

Both approaches will lead to the following output:


As you can see from the code there are some properties you can use to modify the gradient:

  • firstColor (set first color of gradient)
  • endColor (set second color of gradient)
  • smoothGradient
  • direction (rolling to left or right)
  • interval (defines the time in nanoseconds for the animation speed)
  • shape (a given shape that will be filled with the gradient)
  • period (defines the width for one color change)
  • start (when called will start the rolling gradient)

In the next example I've changed some parameters to give you an idea of what you can do:


Rectangle       rectangle = new Rectangle(200, 20);
RollingGradient gradient  = RollingGradientBuilder.create()
                                                  .firstColor(Color.rgb(88, 154, 227))
                                                  .secondColor(Color.rgb(50, 130, 222))
                                                  .smoothGradient(false)
                                                  .direction(Direction.RIGHT)
                                                  .interval(Speed.FAST.getInterval())
                                                  .shape(rect)
                                                  .period(15)
                                                  .start()
                                                  .build();

With this settings the gradient will look like follows:


And because images are boring I've recorded a short video for you that shows the rolling gradient in action...



Well that's it for today and as always you can find the source code on github.

So keep coding...

Tuesday, July 17, 2018

Anchor Selector control

Aloha,

Another control that I saw in Adobe Fireworks and other drawing programs is a control that is used to select an anchor. One can use it to select the origin or to define the position in a layout etc.
Here is a little screenshot of the control in Adobe Fireworks:


The original control is not very big which explains the blurry screenshot, so here is my version of that control implemented in JavaFX:


It's not very fancy that's for sure but sometimes you might need exactly such a control and then you know where to find it :)

The method getSelectedAnchor() will return a Pos object that you can use for whatever you need it.

Here is also a little video that shows the control in action...




In principle that's it and as always you can find the source code at github.

Keep coding...

Saturday, July 14, 2018

GradientPicker reloaded...

Aloha,

Because I worked a lot with Adobe Fireworks over the last 10 years I was using it's gradient tool very often. It is a handy tool to create color gradients where you can simply add new gradient stops and set the color and opacity for each stop either with a slider or by typing in the value.
This is how the Adobe Fireworks gradient tool looks like:



The functionality of the upper handles is to adjust the opacity of the selected stop where the lower handle is to set the color of the stop.
In 2013 I've already created a gradient picker in JavaFX but it was not a separate control but more part of a screen color picker.
So far so good but I always wanted to redo the gradient picker I've created at that time.
Well...after some night hacks I finally finished that gradient picker and so you can now also use it if you like. Here is what the current result looks like:



In principle it has the same functionality as the gradient tool in Adobe Fireworks. I've created a little video that demonstrates it's functionality:



And that's it for today, as always you can find the source code at github.

I hope this control will be useful for one or the other of you and don't forget...keep coding...

Friday, July 6, 2018

Tiles 1.6.4

Aloha,

During the last days and nights I've found some time to add some stuff to TilesFX.
First of all I've modified the calculation of the color gradient that is used in the SparkLineTileSkin and GaugeSparkLineTileSkin.
Because the spark lines only show the line between the low and high value that was measured in the given range it might happen that the color gradient has to be adjusted to the visible range of values.
This now works as expected (at least expected by me).

The code to define the following tile is:

Tile tile = TileBuilder.create()
                       .skinType(SkinType.SPARK_LINE)
                       .prefSize(400, 400)
                       .title("CO2")
                       .unit("ppm")
                       .minValue(400)
                       .maxValue(60000)
                       .decimals(0)
                       .tickLabelDecimals(0)
                       .time(ZonedDateTime.now(ZoneId.of("Europe/Berlin")))
                       .gradientStops(new Stop(0, Color.web("#1CAF4D")),
                                      new Stop(0.0075, Color.web("#1CAF4D")),
                                      new Stop(0.00751, Color.web("#91CA40")),
                                      new Stop(0.01166, Color.web("#91CA40")),
                                      new Stop(0.01167, Color.web("#F8C610")),
                                      new Stop(0.01666, Color.web("#F8C610")),
                                      new Stop(0.01667, Color.web("#F29222")),
                                      new Stop(0.025, Color.web("#F29222")),
                                      new Stop(0.02501, Color.web("#EC1D24")),
                                      new Stop(1.0, Color.web("#EC1D24")))
                       .strokeWithGradient(true)
                       .averagingPeriod(96)
                       .smoothing(true)

                       .build();

And the result when using TilesFX < 1.6.4 looks as follows:


As you can see the gradient used to color the spark line was just a linear gradient from the color calculated for the low value (here 400) to the high value (here 1036). There are no other colors in between even if the gradient stops in the builder contain more stops.
When using the same tile in TilesFX >= 1.6.4 the result will look as follows:


Based on the gradient stops defined in the builder we now see all levels for the different zones we defined.
Meaning to say the color gradient used to stroke the spark line will now always dynamically calculated dependent on the low and high value.
In addition I've added a  new skin named BarGaugeTileSkin which is another gauge visualization that you often can find in dashboards. It looks as follows...



As you can see it shows the current value, a bar with the min and max value and a threshold indicator with a text.
The color of the bar can be customized by

  • bar color property
  • sections
  • gradient stops

So if you would just simply change the color of the bar you just set the bar color by calling

setBarColor(YOUR COLOR) or .barColor(YOUR COLOR) in the TileBuilder.

If you would like to set the bar color dependent on sections (e.g. color the bar red if the value is higher than 80) you might want to define sections and enable them as follows:

Tile tile = TileBuilder.create()
                       .skinType(SkinType.BAR_GAUGE)
                       .prefSize(200, 200)
                       .minValue(0)
                       .maxValue(100)
                       .sectionsVisible(true)
                       .sections(new Section(80, 100, Color.RED))
                       .build();

And if you would like to set the bar color along a defined color gradient you have to define the gradient stops and enable them as follows:

Tile tile = TileBuilder.create()
                       .skinType(SkinType.BAR_GAUGE)
                       .prefSize(200, 200)
                       .minValue(0)
                       .maxValue(100)
                       .strokeWithGradient(true)
                       .gradientStops(new Stop(0.0, Bright.BLUE),
                                      new Stop(0.5, Bright.GREEN),
                                      new Stop(1.0, Bright.RED))
                       .build();

In principle that's all I did but I thought it was worth a new release, so as always please find the latest version here:

Source: github

Binary: bintray

Maven Central

That's it for today...so keep coding... :)

Thursday, July 5, 2018

TilesFX colors...

Aloha,

When working on my little dashboard at home I've figured out that I needed more colors to visualize some data. Because I've added already a color scheme (Bright) to TilesFX a while ago I decided to add more colors.
So in TilesFX 1.6.3 you will find 4 different color schemes, because I often need the same color at different brightness levels I've decided to add a Medium and Dark scheme to the lib. 
Here is a little table that shows the Bright, Medium and Dark scheme with their available color definitions:

The usage is pretty simple, let's assume you would like to make use of the color green from the medium scheme you simple type:

Medium.GREEN and you will get the color #32a539

So I hope these colors are as useful to you as they are to me :)

As always you can find the latest version of TilesFX here

Source: github

Binary: bintray

Maven Central

That's it for today...and do not forget to keep coding...

Friday, June 29, 2018

Some updates to TilesFX

Aloha,

Last week I've spend some time on TilesFX again. After skimming the web for dashboards I saw that it might be interesting to be able to have an image as a tile background.
For that reason I've added a backgroundImage property to the Tile class.
There are also methods to set the background image opacity and if the aspect ratio should be kept for the image.
With this you now can define a background image for each tile if you like :)
In addition I've also added another Region to the upper left corner of a tile.
Here is a little screenshot to give you an idea...


As you can see I used a background image in combination with a SkinType.GAUGE. The upper right yellow region was renamed to notifyRegion. So you can simply make it visible by calling showNotifyRegion(true )e.g. to grab the attention of the user.
On the upper left corner you see the newly added infoRegion. By calling showInfoRegion(true).
You can also attach an EventHandler<MouseEvent> to the infoRegion to trigger custom actions. To add an EventHandler you simply call the setInfoRegionEventHandler and pass in your EventHandler<MouseEvent>. The Tile will listen for MouseEvent.ANY so that you can react on whatever EventType you need in your handler.
The info region also comes with a specific tooltip that you can set which might be useful.
You might want to use this to configure tiles on your dashboard or show popups etc.
For both regions you can also define the background and foreground color as you can see on the next screenshot...


After playing around with my Raspberry Pi and my own dashboard I saw that the text in the WeatherTileSkin can become very long which could result in the text exceeding the width of the tile.
If the text will become to long and won't even fit within the width of the tile with a font size of 5px it won't be shown any longer.
Another thing that I've fixed is the vertical numbering in the SparkLineTileSkin which was wrong by the amount of 1.
On my Pi I saw that when I make use of the smoothing in the SparkLineTileSkin the initial load time tooks quite long. For that reason the smoothing of the initial values is now done in a task which fixed the long initialization of the SparkLineTileSkin.

At this point I would like to say THANK YOU to all of you using TilesFX, I saw that it was downloaded more than 10.000 times within the last year which means it seems to be useful for some of you :)

As always you can find the latest version (which is 1.6.2) here:

binary on bintray

source on github

maven central

or simply from the sidebar of this blog :)


Well that's it for today...so keep coding...

Friday, June 22, 2018

A status skin for TilesFX

Aloha,

Last week I've stumbled upon a new idea for a TilesFX skin and found some time to implement it. It can be used to visualize 3 values incl. a text and an additional node like an icon etc.
Because it is not that easy to describe I think I better show you a screenshot :)
So here you go...


As you can see it comes with the normal title, description and text labels as usual. In addition one can set the value for the left, middle and right side by using one of the following methods

  • setLeftValue(double)
  • setMiddleValue(double)
  • setRightValue(double)

 In this case I simply use it as a counter for notifications with their category (critical, warning, information) but you can use it for whatever you like.
The text below the value can be set with one of the following methods

  • setLeftText(String)
  • setMiddleText(String)
  • setRightText(String)

The icon on top of the value can be set by calling one of the following methods

  • setLeftGraphics(Node)
  • setMiddleGraphics(Node)
  • setRightGraphics(Node)

In this case I've simply used the Indicator control that is now also part of the TilesFX library and which can be found in the addons package.
Because these methods take a JavaFX Node object as a parameter you can take either Icons, ImageViews or Controls which again can be used to visualize something.

This new skin, the Switch and Indicator control can be found in the latest TilesFX release which is 1.6.0.

As usual you can find the source code on github or if you prefer the binary just go to bintray and download it from there.
And of course you can also find it on Maven central.

That's it for today...so keep coding... :)