Friday, July 22, 2016

Friday Fun XXXIV


This is the last Friday Fun component before my vacation so I hope you like it :)
Tuesday I was skimming the web to get some inspiration and stumbled upon a nice little gauge at Dribbble. This is what it looks like...

The use case for such a control is really specific but I like how the designer did it and so I thought this might be an interesting control to create.
With most of the the controls I make again use of my Medusa library for the gauge model. The control itself is based on a JavaFX Region which is the easiest way to create custom controls. You just have to keep in mind that this approach is not very convenient when creating controls libraries because there is no separation of the model and the view.
For the colored areas I used the Medusa Sections and for the visualization of those sections I simply used JavaFX Path's.
The current quality indicator is just another path that will be translated, rotated and filled by the current section color.
To give you an idea how I create such controls let me show you the prototype that I created in an vector drawing prototype.

From this drawing I took all the parameters that I needed to create the control. And this is what the control looks like...

I'm not using the exact same colors as the original but I think it's close enough :)
For those of you who want to see it in action, here is a little video that shows the functionality...

This fits well where you have values that are good when they are small but not the way around which is the reason why I've added a property named reverseOrder which can be used to reverse the color scheme. Means if reverseOrder == true the colors will be from red (1) to green (10).

And that's all I have to say for today...and for at least the next 3 weeks because I will be on vacation...on Crete...yeah :)

If you would like to take a look at the code, feel free to fork it on github.

Enjoy the upcoming weekend and keep coding...

Friday, July 8, 2016

Friday Fun XXXIII


Today I just have a little control that I want to share with you, it's not really something special but sometimes could be useful, I named it ChargeControl. It could be used to visualize the charge of a battery, signal strength or goal reached etc.
The really nice thing about this control is that I wrote it in 30 minutes which simply shows how effective it can be to use JavaFX (if you know what you are doing ;) ).
So here is what it looks like...

As you can see it's not really amazing but it works which was the most important thing. Again I make use of Medusa for the model and one can set values from 0.0 - 1.0.
This control is really light-weight because it only contains Regions that are styled by CSS which makes the amount of code to realize it really small.

Well what should I say...I guess that's it already again and if you are interested in the code you will find it as always on github.

Enjoy the upcoming weekend and do never forget...keep coding ;)

Friday, July 1, 2016

Friday Fun XXXII - Old School Baby...

Hi there,

Two weeks ago someone pinged me on twitter and came up with an idea for another Friday Fun control and last weekend I've found some time to implement it.
We are talking about a DialPlate...I hope you are old enough to remember that, for those who is a little picture to give you an idea...

I liked the idea even if I have no clue for what it might be useful :)
So here is the control I came up with...

As you can see it's really just the dialplate and because I had no idea what it might be useful for it also fires events when you dial a number so that you could think about using it as a dialer to create numbers for whatever. Because I was running out of time I did not implement the correct behavior when rotating to the left (in which case it should not rotate at all) but feel free to fix it :)

To give you an idea what it looks like in action, here is a little video that I've recorded...

And as always if you are interested in the code, feel free to fork it on github.

That's it for today, short but better than nothing and don't forget...keep coding... :)

Friday, June 3, 2016

Friday Fun XXXI

Friday...finally :)

And again time for another Friday Fun Component...and yes it is a gauge again :)
This time I've stumbled upon a gauge that again has a neat effect which is not that easy to implement. But before I start let's take a look at it, here it is...

To be honest, I don't really like this gauge. There are two things that are really not that nice...

  • You can't see where the bar starts and where it ends
  • It always show this quarter which is filled...seems to be a special design feature

Well but there is also one thing that I really like about this gauge, it's the fact that it uses a gradient to fill the bar.
Seems trivial right...but it's not, you might want to try to fill a doughnut like structure with a gradient and you will see what I mean.
There is no easy way in JavaFX to realize this, except you use my more time :)
But because the ConicalGradient is not really made for dynamic changes the whole thing is not really optimal.
Just for the ones of you that don't know my ConicalGradient, you might want to read my blog post about it here.
The problem with this gradient is the fact that I create it by using the PixelWriter. This will create a new image everytime I need the gradient.

You can image that creating an image pixel by pixel could not be very fast and for that reason I restricted the animation duration to a minimum of 2 seconds for this gauge. And even with this you will see some flicker during the animation.

So please don't use this gauge for real-time data with lots of updates because you will be disappointed. But it's really nice for dashboards where the values normally don't change that often.

But now let's take a look at the result first...

And because it's fun I've add the ability to change the color...what else... :)
So it could also look like follows...

Or whatever color you like. Keep in mind that some colors fit better than others.

So what I do in the control is everytime the value changes I reset the gradient stops for the ConicalGradient and set the stroke of the bar with it. And to fix the problem with the missing start and end point of the original I've decided to simply set the angle range of the gauge to 320 degree instead of 360 degree.
With this approach you can see where the bar starts and where it stops.

To use this control you will need the medusa library version 5.+ that you can either find on github, bintray or maven central.

Well not a long post but better than nothing :)

If you are interested in the code you can find it as always on github.

As a reminder, please ping me if you would like to attend the Java(FX) BBQ :)

Enjoy the upcoming weekend and keep coding...

Friday, May 27, 2016

Java(FX) BBQ

Hello again...
Today I don't have any control for you but I would like to announce this years Java(FX) BBQ. It will happen as usual at my place and I will take care about the drinks, so the only thing you need to bring with you is the stuff that you would like to eat.
Well and it might be nice if one or the other could also bring some salad and/or sauce.

Here are the details for the BBQ:

Date      : Saturday, July 2nd  shifted to August 27th due to bad weather
Time     : 3 pm

And it's not all about meat and beer but if you have something interesting to say/show you are welcome to do a short presentation about your topic.

So if you have the time and if you are in the area, feel free to join and have some fun but please let me know up front if you will join so that I now how many people will show up :)

Enjoy the upcoming weekend...and keep coding... :)

Friday, May 20, 2016

Friday Fun XXX

Aloha to another Friday... :)
Today I have a little component for you which is not really tricky to do but it was on my list for a very long time. So finally I've decided to create it and this time it is a segmented control.
You might have seen this control on various car-park routing systems. In Germany this kind of displays are very common and you will find it in many cities, here are a few examples...

In all of the examples you can see the yellow number display and that is exactly the control I'm talking about.

It looks like the control is build out of 15 elements where each element can have different states. One can see a fully filled element, rounded elements and elements that contains triangles.
So as always the first thing to do is creating a prototype in a vector drawing program and here is what it looks like. This prototype contains most of the needed elements.

I've created an extra control that contains one element and this element can have the following states:

The Element contains a StackPane and within this StackPane it holds a SVGPath node. Dependent on the State of the Element the context of this SVGPath node is set. Therefore I've created an enum that not only contains the name of the State but also the SVG path string for each state.
Then I've create the real Segment control that contains a GridPane (3x5) where each position in the grid holds one Element. Now I only needed to create the appropriate states for each Element and each Character. I just implemented the numbers 0-9 which seems to be ok for this kind of display. Well I could not withstand and also implemented the characters A-Z and a "-" which means you could now use 0-9 and A-Z in the Segment control :)

And this is how the control looks like...

As I said this is not a really fancy control but something that I now can take from my todo list :)

Here is also a little video of the control in action...

If you are interested in the code you can find it on always :)

And that's it for enjoy the upcoming weekend and keep coding...

Friday, May 13, 2016

Friday Fun XXIX

Finally Friday again...and with that comes another Friday Fun Component.
This time I stumbled upon a control that doesn't really look that fancy and to make it short here is a picture of what I am talking about...

This control is used over at orangetheory fitness where you do your workout in a group and the trainer can see the individual data on a monitor like on the image. As you can see the control itself is not really fancy but I liked the colors and it has again a little thing which was not that easy to implement.
I just had this image and I have no idea how the control works in reality so the first thing I did was creating a prototype in Adobe Fireworks which looks like follows...

As you can see I've modified the control a bit because I wanted to see the current zone in the lower right and put the BPM label instead of the other number (I have no idea what it means).
With this vector drawing in place it was easy to create the control in JavaFX but there was one little thing that I was missing. There are these little colored trapezoids on the lower left side of the control and if you take a look at the upper image you will see that in whatever zone I'm at the moment the little trapezoid with the same color as the current background is bigger than the others. And exactly this little feature was the main reason to build this control.
This little trapezoids have no special meaning but they give the control a special touch and so I started thinking about how could they work.
The first idea that came to my mind was they should be animated. Means as soon as the heart rate zone changes the trapezoid with the same color should increase it's size using an animation.
Nice idea but it comes with a problem...
Because the trapezoids are all the same just with different colors I thought it should be easy to just create a path for the small and for the big version and morph them when needed. Unfortunately JavaFX doesn't offer a morphing transition by default BUT Tom Schindl (create of E(fx)clipse and on twitter under @tomsontom) has created an excellent PathMorphTransition which takes a source and a target path and animates the points from the source path to the target path. (you can find the PathMorphAnimation class in the Eclipse source code and also in the sources of this friday fun component).
So I've put the 5 trapezoids in an HBox container and I was ready to go...well not really.
The first problem comes with resizing...because the Path is a Shape it has no setPrefSize() method. Well the workaround is to use setScaleX() and setScaleY() on the Path. But this comes with another problem...placement. The problem is that when you scale a node in JavaFX you have to take care about the placement in a different way to make sure that the scaled node stays at the correct position.
Well even this was not a big deal but there was another problem...
When morphing a trapezoid from the small to the big state the layout bounds of the trapezoid will change because we increase the width and height.
And because I've put the trapezoids in an HBox with a spacing of 0 it leads to the following effect...

When the gray trapezoid will be transformed the increase in width will lead to a bigger gap between the gray and the blue trapezoid...BAM
And because I can't adjust the spacing for each child of the HBox this approach did not work. :(
Well there are ways to realize this but that felt like a workaround which I did not like.
So I was looking for another approach and decided that the easiest way would be to create a separate control for the trapezoid that encapsulates the Path object in a Region.
To make this work you have to make sure that the Region always has the size of the big trapezoid. So I can put the Regions in a HBox and because the Region won't change it's layout bounds when the trapezoids morphs from one to the other state the distance between the trapezoids stays the same.
To make sure that the trapezoids are not too far away from each other I've use a negative spacing (keep in mind that when resizing the control you also have to resize the spacing of the HBox).
Long story is the result of my JavaFX version...

To make the control work you have to initialize it with your age. I need that info to calculate the maximum heart rate for the control. The calculation of the maximum heart rate is based on the following equation which seems to be good enough...

    maxBpm = (207 - 0.7 * (age));

There are other equations but it seems this is more accurate (at least that's what I've found on the web).
If you initialize the control with an empty constructor it takes 30 as the default age.
Now you simply have to call the setBpm() method of the control to set the current heart rate and the control will react on it.
Because your heart can beat faster than the recommended max heart rate there is an indication that you are over 100% by blinking the text.
Means if your heart rate is higher than 100% it will still show 100% but the numbers will start to blink as long as your heart rate is higher than 100%.
Well maybe that was not a really fancy control but again it has a little feature that was interesting to implement.

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

If you are interested in the code you will find it as always on github.

That's it for today and even if I don't know if I will ever use this control I hope someone of you have learned something...enjoy the upcoming weekend...and keep coding... :)