Friday, February 5, 2016

Fun with Medusa Clocks...

Hi there,

Time for some fun again...
When I was searching the web for cool stuff I stumbled upon the following clock...



The idea is really great and I thought by myself that it might be nice to have that clock in JavaFX.

As you might have seen I was playing around with clocks anyway so why not use the Medusa Clock to create the Clock of Clocks...

First of all it was needed to create a new skin with really fat hands and so I've added the FatClockSkin to Medusa 3.1 which looks very similar to the clocks above, here it is...



With this visualization in place the next challenge was to get the right behavior of the clock which was not that easy. The problem is that in the real clock the hands are controlled separately which means you can place the minute hand to 45 minutes and the hour hand to 6 directly. Well with the Medusa clock that's not possible because I calculate the angle of the hands from the given time which means in the case of 5:45 my clock will look like follows...



As you can see the hour pointer is not pointing exactly to the 6 which would be needed for the Clock of Clocks. To emulate that behavior I've added a property named discreteHours(). If this property is enabled the hour hand will only jump to the next hour when the hour switches from e.g. 5 to 6. So to get the right behavior we need to set the time to 6:45 instead of 5:45 and the clock will look like follows...



That looks much better :)

The last thing that I needed to implement was the possibility to animate the hands from a given time to another time. Usually the clock just has a property named running which will let the clock run automatically with the given time. But in this case I needed the ability to set the clock to a time and animate it in a given duration to another time. Therefore I've implemented the same properties that are also part of the Medusa Gauge. Animated and animationDuration. 

ATTENTION:
If animated == true the clock can NOT be started by calling setRunning(true).

With these new features in place I could start to build the clock. It is too much code to show it all here, so let me try to explain shortly what I did.
The clock is made out of 4 numbers where each number contains 6 clocks. So I've created a GridPane for each number with the 6 clocks.
Each clock is created with the following method...
private Clock createClock() {
    Clock clock = ClockBuilder.create()
                              .skinType(ClockSkinType.FAT)
                              .backgroundPaint(Color.WHITE)
                              .prefSize(100, 100)
                              .animationDuration(7500)
                              .animated(true)
                              .discreteMinutes(false)
                              .discreteHours(true)
                              .hourTickMarkColor(Color.rgb(200, 200, 200))
                              .minuteTickMarkColor(Color.rgb(200, 200, 200))
                              .tickLabelColor(Color.rgb(200, 200, 200))
                              .build();
    clock.setEffect(new DropShadow(5, 0, 5, Color.rgb(0, 0, 0, 0.65)));
    return clock;
}
With this method I can easily create the GridPane with the following method...
private GridPane createNumberGrid() {
    GridPane grid = new GridPane();
    grid.add(createClock(), 0, 0);
    grid.add(createClock(), 1, 0);
    grid.add(createClock(), 0, 1);
    grid.add(createClock(), 1, 1);
    grid.add(createClock(), 0, 2);
    grid.add(createClock(), 1, 2);
    grid.setHgap(10);
    grid.setVgap(10);
    return grid;
}
The most work was needed to create a lookup table with the right time for each clock and for each number (0-9). Therefore I've simply created 6 LocalTime arrays that contains the correct time for each number and clock. This is the array for the upper left clock of each number...
private LocalTime[]    upperLeft  = { LocalTime.of(6, 15),   // 0 
                                      LocalTime.of(8, 40),   // 1 
                                      LocalTime.of(3, 15),   // 2
                                      LocalTime.of(3, 15),   // 3
                                      LocalTime.of(6, 30),   // 4
                                      LocalTime.of(6, 15),   // 5
                                      LocalTime.of(6, 15),   // 6
                                      LocalTime.of(3, 15),   // 7
                                      LocalTime.of(6, 15),   // 8
                                      LocalTime.of(6, 15) }; // 9
And so there is a similar array for the upper left, upper right, mid left, mid right, lower left and lower right clock.
Now I only have to run an AnimationTimer where I check the time every 10 seconds and set the right time for each clock.

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

The result of the work looks like this...



Because there are clocks that are not needed to visualize a number (like in 1 or 7) those not needed clocks will always be set to 7:40. This is the same as in the real clock.

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


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

Monday, February 1, 2016

Taking control by using the Medusa Clock

Hi there,

Last weekend I've got the idea that it might make sense to add sections and areas to the Medusa Clock control. The visualization looks like follows...



Sections and Areas
The orange part is the area and the green part the section. Sections will be drawn on top of areas. The same principle exists in the Medusa Gauge control. The Gauge uses instances of the Section class and the Clock of the TimeSection class. Both of these classes have a method named checkForValue(). This method takes a double (Gauge) or a LocalTime (Clock) as a parameter and checks if this value is inside of the section that is defined by a start and a stop value.
The Section and TimeSection class will fire events for the following cases

  • The current value entered the section
  • The current value left the section
With this approach you can attach a listener to the section and enable the setCheckSectionForValue(true) in either the Gauge or Clock control to activate this functionality.
In a clock control that can be really useful to control things like switching lights for example. Let's take a look at a simple example.
We will switch on a light in our garden from 7pm to 10pm by using the TimeSection in the Clock control.
The first thing we need to do is creating the TimeSection like follows:

TimeSection gardenLightOn =
    TimeSectionBuilder.create()
                      .start(LocalTime.of(19, 00, 00))
                      .stop(LocalTime.of(22, 00, 00))
                      .onTimeSectionEntered(event -> 
                          System.out.println("Garden light on"))
                      .onTimeSectionLeft(event -> 
                          System.out.println("Garden light off"))
                      .color(Color.rgb(255, 128, 0, 0.5))
                      .build();

As you can see we define the start and stop values by LocalTime instances and add an EventHandler with the onTimeSectionEntered() and onTimeSectionLeft() calls. Then we define a color for the section and that's it.
Now we have to create the Clock control and set the sections like follows:

Clock clock = ClockBuilder.create()
                          .sectionsVisible(true)
                          .sections(gardenLightOn)
                          .checkSectionsForValue(true)
                          .running(true)
                          .build();

The result of this will then look like this...


As soon as it will be 7pm you will see an output on the console with "Garden light on" and at 10pm it will say "Garden light off".
So in this case we only used a System.out.println command to show some action but you might want to send a MQTT message to your device that switches on or off the lights in the garden.
The area is in principle exactly the same just with a different visualization as you can see on the first image on this post. Oh and before I forget it...you can add multiple sections and areas to the Clock and also the Gauge control.
This was one way to use the Medusa Clock to control something but there is another one.

Alarms
You could also use Alarms to control things.
The Medusa Clock also takes a list of Alarm objects. You could either create a simple Alarm and react on the Alarm in the setOnAlarm() method with an EventHandler or you can create an Alarm that executes a so called Command. But let's take a look at the code to create a simple Alarm...

Alarm simpleAlarm =
    AlarmBuilder.create()
                .time(LocalDateTime.now().plusSeconds(2))
                .repetition(Repetition.ONCE)
                .text("Simple Alarm")
                .build();

As you can see it's really simple, you just define the time and the repetition, add a text and now we can add the Alarm to the Clock as follows...

Clock clock = ClockBuilder.create()
                    .alarmsEnabled(true)
                    .alarms(simpleAlarm)
                    .onAlarm(alarmEvent ->
                        System.out.println(alarmEvent.ALARM.getText()))
                    .running(true)
                    .build();

Two seconds after starting our code we will see the "Simple Alarm" message on the console...very easy right :)
In case you would like to create specific Alarms you will find the @FunctionalInterface called Command that only has one method named execute(). This method will be called when an Alarm is triggered and a Command is provided. So with this you could create a Command for switching on/off lights like follows...

class LightOn implements Command {
    @Override public void execute() {
        System.out.println("Switch light on");
    }
}
class LightOff implements Command {
    @Override public void execute() {
        System.out.println("Switch light off");
    }
}

LightOn  lightOn  = new LightOn();
LightOff lightOff = new LightOff();

Alarm alarmLightOn = 
    AlarmBuilder.create()
                .time(LocalDateTime.now().plusSeconds(5))
                .repetition(Repetition.ONCE)
                .text("Light On")
                .command(lightOn)
                .build();

Alarm alarmLightOff = 
    AlarmBuilder.create()
                .time(LocalDateTime.now().plusSeconds(10))
                .repetition(Repetition.ONCE)
                .text("Light off")
                .command(lightOff)
                .build();

So we created two classes that implement the Command interface and in this case we only output something on the console but you could implement whatever you want in that classes. Then we create two Alarms that take the created command classes.
Now we just have to create the clock control and add the alarms like this...

Clock clock = ClockBuilder.create()
                    .alarmsEnabled(true)
                    .alarms(alarmLightOn, alarmLightOff)
                    .onAlarm(event ->
                        System.out.println(LocalTime.now() +
                                           ":" +
                                           event.ALARM.getText()))
                    .running(true)
                    .build();

When you start that code you should see something like the following on your console...


So the first Alarm was triggered 5 sec after the program started and 10 sec after the program was started the second Alarm was triggered.

To be honest I was not sure if it makes sense to implement that functionality in a Clock control but this makes it very easy for me to use a JavaFX Clock control on e.g. a Raspberry Pi with a display and at the same time I'm able to control things with it without using extra code :)

The code can be found on github...

So that's it for today...keep coding... :)

Friday, January 29, 2016

Building a KPI dashboard using Medusa

Hi everyone,

Today I'll show you how to build a simple KPI (Key Performance Indicator) dashboard by using Medusa. If you google for "KPI Dashboard" images you will get an idea of what I'm talking about. When visualizing KPI's you usually have a value and either some colored sections that indicates something like poor, average and good or you have a threshold indicator that shows the target value. Or you have both :)
Interestingly the management prefers gauges where the analysts prefer bulletcharts to visualize KPI's. The problem with gauges is that they use a lot of space with no real benefit (except that they look good).
Let's take a look at some typical KPI's like

  • Revenue
  • Profit
  • Sales
For each of those KPI's we have a maximum value, a target value and three zones for
  • Poor (red)
  • Average (yellow)
  • Good (green)
If we visualize this using gauges we create a factory method getGauge() that could look like follows...

private Gauge getGauge(final String TITLE, final String UNIT, 
                       final double MAX_VALUE, final double THRESHOLD, 
                       final Section... SECTIONS) {
    return GaugeBuilder.create()
                       .skinType(HORIZONTAL)
                       .animated(true)
                       .thresholdColor(GRAY)
                       .title(TITLE)
                       .unit(UNIT)
                       .decimals(0)
                       .minorTickMarksVisible(false)
                       .mediumTickMarksVisible(false)
                       .majorTickMarksVisible(false)
                       .tickLabelLocation(TickLabelLocation.OUTSIDE)
                       .tickLabelOrientation(TickLabelOrientation.HORIZONTAL)
                       .maxValue(MAX_VALUE)
                       .threshold(THRESHOLD)
                       .areasVisible(true)
                       .areas(SECTIONS)
                       .knobColor(Color.BLACK)
                       .needleSize(NeedleSize.THICK)
                       .needleColor(Color.BLACK)
                       .thresholdVisible(true)
                       .thresholdColor(GRAY)
                       .build();
}

If we use this method to create the three gauges the result will look similar to this...

As you can see this takes a lot of space but it might look nice to one or the other.
Now that we saw the gauge approach let's take a look at the BulletChart approach. Therefore we create another factory method that will create the BulletCharts for us and it could look like follows...

private Gauge getBulletChart(final String TITLE, final String UNIT, 
                             final double MAX_VALUE, final double THRESHOLD, 
                             final Section... SECTIONS) {
    return GaugeBuilder.create()
                       .skinType(BULLET_CHART)
                       .animated(true)
                       .thresholdColor(GRAY)
                       .title(TITLE)
                       .unit(UNIT)
                       .maxValue(MAX_VALUE)
                       .threshold(THRESHOLD)
                       .sectionsVisible(true)
                       .sections(SECTIONS)
                       .build();
}

If we create the KPI dashboard using this method it will look similar to this...

As you can see we save some space by using the BulletChartSkin and it also doesn't look that fancy but simply shows the facts.

The demo code could be found over at github...

And that's it for today...keep coding...

Wednesday, January 27, 2016

Building a fuel gauge using Medusa

Hi there,

Today I will show you how you could build a simple fuel gauge with Medusa. To give you an idea on what I'm talking about, here is an image of a VDO fuel gauge that you can buy...



To get as close as possible to this design we'll use a horizontal gauge that comes with an angle range of 180 degrees. By using the GaugeBuilder it will look like this...

Gauge gauge = GaugeBuilder.create()
                          .skinType(SkinType.HORIZONTAL)
                          .prefSize(500, 250)
                          .build();
It will look as follows...



Because most of the car dashboards are colored dark we'll adjust the colors as follows...

Gauge gauge = GaugeBuilder.create()
                          .skinType(SkinType.HORIZONTAL)
                          .prefSize(500, 250)
                          .foregroundBaseColor(Color.rgb(249, 249, 249))
                          .knobColor(Color.BLACK)
                          .build();
To get a nice result we also have to set the background of our container (e.g. a StackPane) to a nice dark gradient. This will give us the following visualization...



In the next step we have to adjust the scale (from 0.0 to 1.0), hide the value text and add a section with a red color for the reserve (from 0.0 to 0.2). The code to realize this looks like this...
Gauge gauge = GaugeBuilder.create()
                          .skinType(SkinType.HORIZONTAL)
                          .prefSize(500, 250)
                          .foregroundBaseColor(Color.rgb(249, 249, 249))
                          .knobColor(Color.BLACK)
                          .maxValue(1.0)
                          .valueVisible(false)
                          .sectionsVisible(true)
                          .sections(new Section(0.0, 0.2, Color.rgb(255, 10, 1)))
                          .build();
which will make the gauge look like follows...



That's not bad but now let's get rid of the minor and medium tick marks, add a title ("FUEL") and set another tick mark type for the major tick marks (TickMarkType.BOX)
Gauge gauge = GaugeBuilder.create()
                          .skinType(SkinType.HORIZONTAL)
                          .prefSize(500, 250)
                          .foregroundBaseColor(Color.rgb(249, 249, 249))
                          .knobColor(Color.BLACK)
                          .maxValue(1.0)
                          .valueVisible(false)
                          .sectionsVisible(true)
                          .sections(new Section(0.0, 0.2, Color.rgb(255, 10, 1)))
                          .minorTickMarksVisible(false)
                          .mediumTickMarksVisible(false)
                          .majorTickMarkType(TickMarkType.BOX)
                          .title("FUEL")
                          .build();
So far so good, now it should look like this...



In principle this is ok except the tick labels that show only "0" and "1" because the tick label decimals are set to 0. If we set them to 1 like in the following code...
Gauge gauge = GaugeBuilder.create()
                          .skinType(SkinType.HORIZONTAL)
                          .prefSize(500, 250)
                          .foregroundBaseColor(Color.rgb(249, 249, 249))
                          .knobColor(Color.BLACK)
                          .maxValue(1.0)
                          .valueVisible(false)
                          .sectionsVisible(true)
                          .sections(new Section(0.0, 0.2, Color.rgb(255, 10, 1)))
                          .minorTickMarksVisible(false)
                          .mediumTickMarksVisible(false)
                          .majorTickMarkType(TickMarkType.BOX)
                          .title("FUEL")
                          .tickLabelDecimals(1)
                          .build();
we will get the following result...



So with this we are getting there, maybe the needle could be a bit bigger and with a more round look. Also the color of the needle could be more orange and a shadow would also be nice. So here you go...
Gauge gauge = GaugeBuilder.create()
                          .skinType(SkinType.HORIZONTAL)
                          .prefSize(500, 250)
                          .foregroundBaseColor(Color.rgb(249, 249, 249))
                          .knobColor(Color.BLACK)
                          .maxValue(1.0)
                          .valueVisible(false)
                          .sectionsVisible(true)
                          .sections(new Section(0.0, 0.2, Color.rgb(255, 10, 1)))
                          .minorTickMarksVisible(false)
                          .mediumTickMarksVisible(false)
                          .majorTickMarkType(TickMarkType.BOX)
                          .title("FUEL")
                          .tickLabelDecimals(1)
                          .needleSize(NeedleSize.THICK)
                          .needleShape(NeedleShape.ROUND)
                          .needleColor(Color.rgb(255, 61, 10))
                          .shadowsEnabled(true)
                          .build();
And the result will look like follows...



Well that is ok'ish but still the tick labels are a bit confusing. I would prefer something like "E" at the lower end of the scale, "F" at the upper end and "1/2" in the middle but how to realize that? I've added the ability to use custom tick labels and used a very simple implementation means it's a simple list of Strings. So we have 11 tick labels here which means we'll need a list of 11 Strings with the appropriate labels. To get it even closer to the original one we set the angle range to 90 degrees. So the final code will look like this...
Gauge gauge = GaugeBuilder.create()
                          .skinType(SkinType.HORIZONTAL)
                          .prefSize(500, 250)
                          .foregroundBaseColor(Color.rgb(249, 249, 249))
                          .knobColor(Color.BLACK)
                          .maxValue(1.0)
                          .valueVisible(false)
                          .sectionsVisible(true)
                          .sections(new Section(0.0, 0.2, Color.rgb(255, 10, 1)))
                          .minorTickMarksVisible(false)
                          .mediumTickMarksVisible(false)
                          .majorTickMarkType(TickMarkType.BOX)
                          .title("FUEL")
                          .needleSize(NeedleSize.THICK)
                          .needleShape(NeedleShape.ROUND)
                          .needleColor(Color.rgb(255, 61, 10))
                          .shadowsEnabled(true)
                          .angleRange(90)
                          .customTickLabelsEnabled(true)
                          .customTickLabels("E", "", "", "", "", "1/2", "", "", "", "", "F")
                          .build();
and this will give us the following result...



So that's nearly all you can do with Medusa but if you would like to replace the text "FUEL" with an icon you could easily put the icon (a JavaFX Region styled with CSS) and the gauge in a StackPane. And because the Medusa gauge comes with a transparent background you will see the icon. To do so you simply have to remove the .title("FUEL") line from the code above and add the following code to your start() method.
Region    fuelIcon = new Region();
fuelIcon.getStyleClass().setAll("icon");

StackPane pane = new StackPane(fuelIcon, gauge);
pane.setPadding(new Insets(10));
LinearGradient gradient = new LinearGradient(0, 0, 0, pane.getLayoutBounds().getHeight(),
                                             false, CycleMethod.NO_CYCLE,
                                             new Stop(0.0, Color.rgb(38, 38, 38)),
                                             new Stop(1.0, Color.rgb(15, 15, 15)));
pane.setBackground(new Background(new BackgroundFill(gradient, CornerRadii.EMPTY, Insets.EMPTY)));

Scene scene = new Scene(pane);
scene.getStylesheets().add(Test.class.getResource("styles.css").toExternalForm()); 
As you can see we add a css file named "styles.css" to the scene and the set the ".icon" style class for the fuelIcon region. The css file looks like this...
.icon {
    -fx-max-width        : 36px;
    -fx-max-height       : 41px;
    -fx-background-color : rgb(249, 249, 249);
    -fx-scale-shape      : true;
    -fx-shape            : "M 25.775 17.025 L 25.775 8.645 L 28.3633 11.2324 L 29.5547 17.6875
                            C 29.6035 18.0293 29.7988 18.332 30.0918 18.5273 L 33.2949 20.666
                            L 33.2949 30.6855 C 33.2754 31.2617 33.0508 31.9551 32.0449 31.9551
                            C 31.0293 31.9551 30.7949 31.2617 30.7754 30.6953 L 30.7754 23.166
                            C 30.7754 19.0669 27.9706 17.4574 25.775 17.025 ZM 25.7754 4.6699
                            C 25.7754 2.4141 23.9492 0.5879 21.6934 0.5879 L 9.7793 0.5879
                            C 7.5332 0.5879 5.6973 2.4141 5.6973 4.6699 L 5.6973 5.6074
                            L 5.6973 29.1328 L 5.6973 33.2148 L 9.7793 33.2148 L 21.6934 33.2148
                            L 25.7754 33.2148 L 25.7754 29.1328 L 25.775 19.605
                            C 26.8895 19.9367 28.2754 20.8192 28.2754 23.166 L 28.2754 30.6953
                            C 28.2754 32.209 29.2813 34.4648 32.0449 34.4648
                            C 34.7988 34.4648 35.8047 32.209 35.8047 30.6953 L 35.8047 20.7246
                            C 35.8145 20.7051 35.8145 20.6758 35.8145 20.666
                            C 35.8145 20.5488 35.7949 20.4414 35.7656 20.334 L 34.5352 12.9316
                            C 34.4766 12.5801 34.2813 12.2773 33.9883 12.0918 L 30.3262 9.6504
                            L 25.775 5.1 L 25.7754 4.6699 ZM 22.0156 5.8613 L 22.0156 12.1211
                            C 22.0156 13.166 21.166 14.0059 20.1309 14.0059 L 11.3516 14.0059
                            C 10.3066 14.0059 9.4668 13.166 9.4668 12.1211 L 9.4668 5.8613
                            C 9.4668 4.8164 10.3066 3.9766 11.3516 3.9766 L 20.1309 3.9766
                            C 21.166 3.9766 22.0156 4.8164 22.0156 5.8613 ZM 29.2227 35.7148
                            L 2.25 35.7148 C 1.3809 35.7148 0.6777 36.418 0.6777 37.2871
                            L 0.6777 38.2246 L 0.6777 39.1719 L 0.6777 40.7344 L 2.25 40.7344
                            L 29.2227 40.7344 L 30.7949 40.7344 L 30.7949 39.1719 L 30.7949 38.2246
                            L 30.7949 37.2871 C 30.7949 36.418 30.0918 35.7148 29.2227 35.7148 Z ";
}
As you can see we make use of SVG in the -fx-shape css property and set it's max size to 36x41 pixels. With this modifications in place our fuel gauge will then look like this...



et voilĂ  here you go, a fuel gauge...
And if you prefer a vertical gauge instead of the horizontal one you can simply exchange the call .skinType(SkinType.HORIZONTAL) with .skinType(SkinType.VERTICAL) in the example above and you will get something like this...



Please find the code for this demo over at github...

That's it for today, I hope you enjoy Java(FX) as much as I do, keep coding...

Wednesday, January 20, 2016

Building a simple Dashboard using Medusa...

Aloha,

after spending some time creating my new Medusa gauges library I've started playing around with it to get an idea about the usability.
So in this little blogpost I will show you how you could create a simple dashboard with a flat ui design.
For this dashboard we will make use of the SlimSkin that will look like this



The dashboard should contain 6 gauges for 

  • Steps
  • Distance
  • Active Calories
  • Food Calories
  • Weight
  • Body Fat
Each of those gauges should also get a specific label for the description and a specific color. 

So the code to build one gauge will look like this

Gauge gauge = GaugeBuilder.create()
                          .skin(SlimSkin.class)
                          .barColor(Color.RED)
                          .decimals(0)
                          .maxValue(100)
                          .unit("UNIT")
                          .build();

Because we will also need a Label for the description we'll put each Label, with a Rectangle filled with the specific color and the Gauge in a VBox. Therefor we will create a little method that creates that VBox for us, here it is...

private VBox getVBox(final String TEXT, final Color COLOR, final Gauge GAUGE) {
    Rectangle bar = new Rectangle(200, 3);
    bar.setArcWidth(6);
    bar.setArcHeight(6);
    bar.setFill(COLOR);

    Label label = new Label(TEXT);
    label.setTextFill(COLOR);
    label.setAlignment(Pos.CENTER);
    label.setPadding(new Insets(0, 0, 10, 0));

    GAUGE.setBarColor(COLOR);
    GAUGE.setBarBackgroundColor(MaterialDesign.GREY_800.get());
    GAUGE.setAnimated(true);
    GAUGE.setAnimationDuration(1000);

    VBox vBox = new VBox(bar, label, GAUGE);
    vBox.setSpacing(3);
    vBox.setAlignment(Pos.CENTER);
    return vBox;
}

So the only thing that's missing is now is the creation of the Gauges and the VBoxes. By making use of the Medusa GaugeBuilder it's just a few lines of code to realize that, here it is...

GaugeBuilder builder = GaugeBuilder.create().skin(SlimSkin.class);
steps        = builder.decimals(0).maxValue(10000).unit("STEPS").build();
distance     = builder.decimals(2).maxValue(10).unit("KM").build();
actvCalories = builder.decimals(0).maxValue(2200).unit("KCAL").build();
foodCalories = builder.decimals(0).maxValue(2200).unit("KCAL").build();
weight       = builder.decimals(1).maxValue(85).unit("KG").build();
bodyFat      = builder.decimals(1).maxValue(20).unit("%").build();

VBox stepsBox        = getVBox("STEPS", MaterialDesign.CYAN_300.get(), steps);
VBox distanceBox     = getVBox("DISTANCE", MaterialDesign.ORANGE_300.get(), distance);
VBox actvCaloriesBox = getVBox("ACTIVE CALORIES", MaterialDesign.RED_300.get(), actvCalories);
VBox foodCaloriesBox = getVBox("FOOD", MaterialDesign.GREEN_300.get(), foodCalories);
VBox weightBox       = getVBox("WEIGHT", MaterialDesign.DEEP_PURPLE_300.get(), weight);
VBox bodyFatBox      = getVBox("BODY FAT", MaterialDesign.PURPLE_300.get(), bodyFat);

Finally we just have to put the VBoxes in a GridPane like follows...

pane = new GridPane();
pane.setPadding(new Insets(20));
pane.setHgap(10);
pane.setVgap(15);
pane.setBackground(new Background(new BackgroundFill(MaterialDesign.GREY_900.get(), CornerRadii.EMPTY, Insets.EMPTY)));
pane.add(stepsBox, 0, 0);
pane.add(distanceBox, 1, 0);
pane.add(actvCaloriesBox, 0, 2);
pane.add(foodCaloriesBox, 1, 2);
pane.add(weightBox, 0, 4);
pane.add(bodyFatBox, 1, 4);

And that's all it needs...so easy...here is the result (with random values)...


As you can see in the code I've also used the MaterialDesign colors that you can find in my Colors project. Means you need the Medusa jar and the Colors jar to run that code above.

Please keep in mind that the code above only contains the important parts, you need to create the Gauge and GridPane member variables and also need to add the GridPane to the JavaFX Scene which should be easy.

Please find the code over at github...

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


Monday, January 11, 2016

Colors...

Aloha,

Today I just have a little project for you which might be helpful for one or the other. When creating ui's or controls I always have the problem with choosing colors, esp. with things like Flat UI or Material Design based interfaces/controls. In those cases I usually go to the browser or a drawing program to pick the right colors.
So for those of you that don't know what I'm talking about you might want to take a look at


Those are nice websites where you can pick the predefined color values very easily but if you would like to add either a few of those definitions or all of them to your project you have to pick a lot of values.
So I decided to create a little jar that contains these color definitions so if you need either Flat UI colors, Material Design, Social or Windows 8 Metro Style colors you simply can add the jar to your project and use the colors by their name.

Let's say you need the Material Design color Amber 800, then you can use it like this...

Color amber800 = MaterialDesign.AMBER_800.COLOR;

with the Flat UI colors is it the same, here it would look like this...


Color peterRiver = FlatUi.PETER_RIVER.COLOR;

If you need the colors for something else or if you simply need an overview, I've also added two classes that shows you all colors in a grid and if you click on a color it will copy the values to the system clipboard.

The Material Design color picker



The Flat UI color picker



The source and binary can be found here...


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


Friday, January 8, 2016

Medusa...

Because I didn't have any summer vacation last year I had to take the whole vacation at the end of 2015 which gave me 4 weeks of spare time...
And because I really needed some new motivation I did what I can do best...gauges :)

If you take a look at JavaFX you will find a nice feature set which also contains charts but unfortunately you won't find gauges. This was the reason why I've started porting gauges from Java Swing to the JFXtras Project 4 years ago. And that was also the reason why I've started the Enzo project. Those are nice projects but I always wanted to create something more general and so I've started another JavaFX library...Medusa



So where are the differences between Enzo and Medusa you might ask yourself, well there are a few differences...

1. No CSS in the standard GaugeSkin
When I've started with JavaFX I was totally convinced of the code only approach (means all graphics are done in code). After a year or two I've started to use CSS and used the Region+CSS approach for nearly all of my controls. This is totally fine and it works...but the more I thought about it the more unconvinced I became. The reasons are as follows, the idea to use CSS in JavaFX was to improve the Designer-Developer workflow and I like this. But the CSS approach in JavaFX is not Standard CSS which means no Designer really understands it directly which means it will end at the Developer side again. The other problem is that the CSS approach in JavaFX is based on CSS 2.1 and not on CSS 3.0. This means it is only a part of the current CSS spec. So why should I learn this part of CSS if I can also do it in code? I totally agree that CSS is fine to style an application and I will continue to use it where it makes sense. But if you create something like a gauge with all it's different options you will end up with a huge amount of boilerplate code only to support CSS where the code approach is much easier to use. It's no problem to use CSS in your own Medusa Skin, just to make that clear :)
You can simply use the .gauge CSS selector.

2. One Control different Skins
The Medusa library contains only one Gauge Control with a default GaugeSkin. The main idea is to have a more or less complete set of properties that will work for most of the gauges and create different Skins for the different use cases. The standard Medusa GaugeSkin comes without any fancy style but only with the basics that are really needed like Tick Marks, Tick Labels, Sections, Areas, Markers and a Needle. It also comes without a background and a border (they are just set to transparent). The reason for this simple Skin is the fact that you can use this to embed it in your own controls or apps very easily. Means you could create a CSS stylable JavaFX Control that comes with it's own Skin and embeds a Medusa Control to visualize the Tick Marks etc. I've put some very basic quick hacks in the skins folder of the project to give you an idea (the FramedGauge definitely needs some improvements because it uses CSS inlining UPDATE: Now there is the FGauge class which uses Borders instead of CSS inlining). If you know the Enzo library you will recognize that I've also ported some of the Enzo Skins to Medusa and I will port more of them in the future.

3. Better scales
The most complex part of a Gauge is the scale, it sounds easy but it could get complex. So you want to define a start angle and an angle range, apply a given value range to it and would like to see a nice scale right? Well I did my best to make that happen in Medusa. In Enzo I used the same approach but it did not work with ranges like 0 - 1 or 0 - 10. So I've found and fixed that problem in Medusa which means you will hopefully get nice scales for your given range of values. Another new feature is the ability to create scales with a counter clockwise direction. This is not always needed but sometimes it is really useful. This feature is at the moment only available in the standard Medusa GaugeSkin and not in the other Skins.

4. Different usage of properties
All properties of the Gauge Control are implemented with "shadow" variables which are using primitives. Only if you call the property method the properties will be initialized. There are only three exceptions

  • value (contains the value that was set by the setValue method)
  • currentValue (contains the current value during animations)
  • oldValue (contains the old value)

So in principle every property is implemented as follows...


private String         _title = "";
private StringProperty title;



public String getTitle() { return null == title ? _title : title.get(); }
public void setTitle(final String TITLE) {
    if (null == title) {
        _title = TITLE;
    } else {
        title.set(TITLE);
    }
    fireUpdateEvent(REDRAW_EVENT);
}
public StringProperty titleProperty() {
    if (null == title) { title = new SimpleStringProperty(Gauge.this, "title", _title); }
    return title;
}

To make sure that events will also be fired when using the primitives in the setTitle() method I use my own events that will always be fired. The advantage is that I really don't need to initialize the JavaFX properties as long as I don't call the titleProperty() method. This could be helpful when using the library on embedded devices. On a desktop machine you won't notice a difference but on an embedded device you could see an effect when initializing a lot of properties. I'm not 100% sure if this approach works in all use cases but time will tell :)


But now let's take a look at the Medusa standard gauge...



As mentioned it doesn't look really fancy and that's on purpose. To create this kind of gauge you simply can use the following code:


Gauge gauge = GaugeBuilder.create().build();


Ok, that's not really impressive isn't it? So let's play around with the standard Medusa GaugeSkin a bit...

Let's try the following features...

  • Scale direction CCW (CLOCKWISE, COUNTER_CLOCKWISE)
  • Tick labels outside of tick marks (OUTSIDE, INSIDE)
  • Start at the bottom (0-360)
  • Angle range of 270° (0-360)
  • Range from -1 to 2
  • Highlight the 0 (zeroColor property)
  • Get other types for major tickmarks ( LINE, DOT, TRIANGLE, TICK_LABEL)
So to get this gauge you need the following code...


Gauge gauge = GaugeBuilder.create()
                          .scaleDirection(ScaleDirection.COUNTER_CLOCKWISE)
                          .tickLabelLocation(TickLabelLocation.OUTSIDE)
                          .startAngle(0)
                          .angleRange(270)
                          .minValue(-1)
                          .maxValue(2)
                          .zeroColor(Color.ORANGE)
                          .majorTickMarkType(TickMarkType.TRIANGLE)
                          .build();


And the result will look like this...




So as you can see the angle starts at the bottom (startAngle == 0) and the direction is counter clockwise. You could now also add Sections, Areas and Markers where Sections will be drawn like a part of a doughnut and Areas like slices of a pie. For Markers you can choose between three different MarkerTypes. You could also disable the visibility of the minor-, medium- and major tick marks which sometimes makes sense.
For the needle I have only one version implemented at the moment but more will come in the future.
To make it at least a bit more interesting you could set the needle color and choose between three values for the needle size (THIN, MEDIUM, THICK). This could be helpful if the gauge is very small.
So, another one...


Gauge gauge = GaugeBuilder.create()
                          .prefSize(500,500)
                          .scaleDirection(ScaleDirection.COUNTER_CLOCKWISE)
                          .tickLabelLocation(TickLabelLocation.OUTSIDE)
                          .startAngle(0)
                          .angleRange(270)
                          .minValue(-1)
                          .maxValue(2)
                          .zeroColor(Color.ORANGE)
                          .majorTickMarkType(TickMarkType.TRIANGLE)
                          .sectionsVisible(true)
                          .sections(new Section(1.5, 2, Color.rgb(200, 0, 0, 0.5)))
                          .areasVisible(true)
                          .areas(new Section(-0.5, 0.5, Color.rgb(0, 200, 0, 0.5)))
                          .markersVisible(true)
                          .markers(new Marker(0.75, "Marker 1", Color.MAGENTA))
                          .needleColor(Color.DARKCYAN)
                          .needleSize(NeedleSize.THICK)
                          .build();

And the result will look like this...




Well these are just a few options that are available at the moment and I will add more, so please stay tuned.
But like I mentioned before I've also ported some Skins from Enzo to Medusa and also created new Skins. 
So here is a little screenshot of what is available at the moment...



The new Skins are 

  • BulletChartSkin
  • SpaceXSkin
  • ModernSkin
The Gauge in the upper right corner is good for visualizing KPI's (Key Performance Indicators) but that really depends on the user. An analyst mostly prefers a BulletChart because it saves space and doesn't use fancy graphics. But when you talk to Managers who would like to show the KPI's in a meeting you will find that they most of the times prefer Gauges because they look better. And because a BulletChart visualizes the same data as a Gauge I decided to also add a BulletChartSkin to Medusa. To make use of the Skins I've added the possibility to select the Skin the GaugeBuilder. If you would like to create the Gauge in the upper right corner you simply do the following


Gauge gauge = GaugeBuilder.create()
                          .skin(SimpleSkin.class)
                          .sections(new Section(0, 16.66666, "0", Color.web("#11632f")),
                                    new Section(16.66666, 33.33333, "1", Color.web("#36843d")),
                                    new Section(33.33333, 50.0, "2", Color.web("#67a328")),
                                    new Section(50.0, 66.66666, "3", Color.web("#80b940")),
                                    new Section(66.66666, 83.33333, "4", Color.web("#95c262")),
                                    new Section(83.33333, 100.0, "5", Color.web("#badf8d")))
                          .title("Simple")
                          .threshold(50)
                          .animated(true)
                          .build();


And you will get the following result...


To create a BulletChart with the same data you simply change the parameter in the skin() call from SimpleSkin.class to BulletChartSkin.class like this...


Gauge gauge = GaugeBuilder.create()
                          .skin(BulletChartSkin.class)
                          .sections(new Section(0, 16.66666, "0", Color.web("#11632f")),
                                    new Section(16.66666, 33.33333, "1", Color.web("#36843d")),
                                    new Section(33.33333, 50.0, "2", Color.web("#67a328")),
                                    new Section(50.0, 66.66666, "3", Color.web("#80b940")),
                                    new Section(66.66666, 83.33333, "4", Color.web("#95c262")),
                                    new Section(83.33333, 100.0, "5", Color.web("#badf8d")))
                          .title("Simple")
                          .threshold(50)
                          .animated(true)
                          .build();


And instead of the Gauge you will get this nice little BulletChart...



Each Skin needs a special set of parameters to be set to the correct values to make sure it looks ok. For example the SimpleSkin uses white for the value and title where the standard color of the GaugeSkin is nearly black.
So if you use the GaugeBuilder to create your Gauge, the GaugeBuilder will take about setting the needed default values for you which makes it easier for you.

Another new Skin is the SpaceXSkin which I saw when the Space X Falcon 9 started to it's liftoff and landing maneuver last month. It's a simple flat UI gauge with just a few features. So if you set a threshold value and a threshold color it will visualize the bar after the threshold with the given color. The interesting part was to visualize the bar when it exceeds the threshold because it changes it's color. So to use the SpaceXSkin you again use the .skin() method in the GaugeBuilder as follows.


Gauge gauge = GaugeBuilder.create()
                    .skin(SpaceXSkin.class)
                    .animated(true)
                    .title("SpaceX")
                    .unit("km/h")
                    .maxValue(30000)
                    .threshold(25000)
                    .build();


And the result will look like follows...



Like I said a really simple Skin but it also just has 8 nodes on the Scene Graph which makes it great for dashboards full of Gauges :)

The last new Skin that I've added is the ModernSkin which is my personal favourite, here I use another new approach where I highlight the tick marks which value is smaller than the current value. I saw that design in an app on my iPhone and copied most of it but also added more features to it. So this is the way you initialize it...


Gauge gauge = GaugeBuilder.create()
                         .skin(ModernSkin.class)
                         .sections(new Section(85, 90, "", Color.rgb(204, 0, 0, 0.5)),
                                   new Section(90, 95, "", Color.rgb(204, 0, 0, 0.75)),
                                   new Section(95, 100, "", Color.rgb(204, 0, 0)))
                         .title("MODERN")
                         .unit("UNIT")
                         .threshold(85)
                         .thresholdVisible(true)
                         .animated(true)
                         .build();


And this is how it will look like...


This gauge doesn't work for everything but form some use cases it might be really nice. It also only comes in the color scheme above but I'm also working on a bright scheme.


All other Skins are ports from Enzo and not really new but I will blog about the all controls within the next weeks but for today I guess that's it.

Here are the links to the source and binaries
The binaries will also be IS available on Maven Central , it just takes some time to make it happen... :)

That's the work of my vacation and I had a lot of fun creating it, from now on I will spend most of my spare time in Medusa and will continue adding features, new Skins and blogposts.

Stay tuned and keep coding...