Wednesday, May 16, 2012

Yes...we can...

A long long time ago i wrote the last blog post but now i'm back...
Some of you might already know that i've changed my job (again) and now am working for canoo engineering in Basel (Switzerland).
To make it short...i really love it :)


Yesterday i was playing around with the new release of Adobe Fireworks CS6 to learn about the new features of the new version. Because i'm working on JavaFX 2.x now a lot i had a special interest in the new CSS capabilities of Fireworks CS6 to check if they might be of use for my JavaFX development. 
As an very small example i will take the following image (you might know it from the iPhone):




If you take a look at the design in Adobe Fireworks it's made out of three shapes:

  • background
  • gloss
  • arrow



If i would like to convert this image to JavaFX i could do this by using my own FXG Converter but that would mean i have to use the FXG file format which is only available on Adobe products. So to make this blogpost more usefull i decided to stick to a more widely used format...SVG.
To be able to export SVG from Fireworks one has to install a little extension created by Aaron Beall which is named Export and could be found here. (This extension will also work on Fireworks CS5)
Now with this extension in place i exported the SVG file of the image and got the following file:



<?xml version="1.0" standalone="no"?>
<!-- Generator: Adobe Fireworks CS6, Export SVG Extension by Aaron Beall (http://fireworks.abeall.com) . Version: 0.6.0  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="" viewBox="0 0 128 128" style="background-color:#ffffff00" version="1.1"
     xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
     xml:space="preserve" x="0px" y="0px" width="128px" height="128px">
  <defs>
    <filter id="filter1" x="-100%" y="-100%" width="300%" height="300%">
      <!-- Drop Shadow -->
      <feOffset result="out" in="SourceGraphic" dx="-1.2941" dy="-4.8296"/>
      <feColorMatrix result="out" in="out" type="matrix" 
                     values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.451 0"/>
      <feGaussianBlur result="out" in="out" stdDeviation="3"/>
      <feBlend in="SourceGraphic" in2="out" mode="normal" result="Drop_Shadow1"/>
    </filter>
  </defs>
  <path id="background" 
        d="M 62.6381 6.8085 C 31.0529 6.8085 5.447 32.4156 5.447 64 
           C 5.447 66.482 5.6577 68.9089 5.9636 71.3072 C 9.5577 99.4342 33.5351 
           121.1915 62.6381 121.1915 C 91.7415 121.1915 115.7188 99.4342 119.313 
           71.3072 C 119.6185 68.9089 119.83 66.482 119.83 64 C 119.83 32.4156 
           94.2232 6.8085 62.6381 6.8085 Z" 
        stroke="#ffffff" 
        stroke-width="11" 
        fill="#6096e3"/>
  <path id="gloss" 
        d="M 62.6381 114.383 C 88.9706 114.383 110.6626 94.6968 113.9152 69.2487 C 
           100.6936 60.109 82.6032 54.4681 62.6381 54.4681 C 42.673 54.4681 24.5821 
           60.109 11.3617 69.2487 C 14.6139 94.6968 36.3059 114.383 62.6381 114.383 
           Z" 
        fill="#236ed8"/>
  <path id="arrow" 
        filter="url(#filter1)" 
        d="M 44.7016 41.0951 L 69.3251 65.7207 L 44.5005 90.2008 L 55.7281 101.4289 
           L 92.0866 65.0698 L 56.5768 29.5638 L 44.7016 41.0951 Z" 
        fill="#ffffff"/>
</svg>



So you might ask yourself why i choosed svg for the conversion, well there's a really simple reason named SVGPath. With this Object you will be able to simple copy the path definition from the svg file and paste it as a string into your JavaFX code. The arrow of the example would look like this:



String arrow = "M 44.7016 41.0951 L 69.3251 65.7207 L 44.5005 90.2008 L 55.7281 
                101.4289 L 92.0866 65.0698 L 56.5768 29.5638 L 44.7016 41.0951 Z";        
SVGPath arrowShape = SVGPathBuilder.create()
                                   .content(arrow)                                        
                                   .build();

That's easy isn't it? But now we also need to style these shapes with css and that's unfortunately not as easy as the shape "conversion". Well it's still easy enough but you can't simply copy paste some code. This is because the css definition in JavaFX has it's own syntax (which is nothing special if you take a look at all the different browser vendors which do exactly the same).


In Adobe Fireworks CS6 you will find support for CSS in a way that makes working with stylesheets a charm. For the background in our example it will look like this:




You could see that i've selected the background circle and the CSS Properties window shows the css style definition for the selected shape. But if you know the JavaFX css definitions you will also see that these are different and that you have to modify them manually which will lead to this:


-fx-fill        : rgb(96, 150, 227);
-fx-stroke      : rgb(255, 255, 255);
-fx-stroke-width: 11px;


This information is also in the svg file and could be taken from there too which means it's up to you where you take it from.
The advantage of the css support in Adobe Fireworks CS6 is more that you could modify the drawing and directly get the css style information like colors and gradients.


In the end the conversion of the drawing led to the following JavaFX code:



Pane pane = new Pane();


String background       = "M 62.6381 6.8085 C 31.0529 6.8085 5.447 32.4156 5.447 64 
                           C 5.447 66.482 5.6577 68.9089 5.9636 71.3072 C 9.5577 
                           99.4342 33.5351 121.1915 62.6381 121.1915 C 91.7415 
                           121.1915 115.7188 99.4342 119.313 71.3072 C 119.6185 
                           68.9089 119.83 66.482 119.83 64 C 119.83 32.4156 94.2232 
                           6.8085 62.6381 6.8085 Z";
String backgroundStyle  = "-fx-fill        : rgb(96,150,227);" +
                          "-fx-stroke      : rgb(255,255,255);" +
                          "-fx-stroke-width: 11px;";
SVGPath backgroundShape = SVGPathBuilder.create()
                                        .content(background)
                                        .style(backgroundStyle)
                                        .build();


String gloss       = "M 62.6381 114.383 C 88.9706 114.383 110.6626 94.6968 113.9152 
                      69.2487 C 100.6936 60.109 82.6032 54.4681 62.6381 54.4681 C 
                      42.673 54.4681 24.5821 60.109 11.3617 69.2487 C 14.6139 
                      94.6968 36.3059 114.383 62.6381 114.383 Z";
String glossStyle  = "-fx-fill  : rgb(35,110,216);" +
                     "-fx-stroke: transparent;";
SVGPath glossShape = SVGPathBuilder.create()
                                   .content(gloss)
                                   .style(glossStyle)
                                   .build();


String arrow       = "M 44.7016 41.0951 L 69.3251 65.7207 L 44.5005 90.2008 L 
                      55.7281 101.4289 L 92.0866 65.0698 L 56.5768 29.5638 L 
                      44.7016 41.0951 Z";
String arrowStyle  = "-fx-fill  : rgb(255,255,255);" +
                     "-fx-stroke: transparent;" +
                     "-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.35), 4, 0.1, 
                                             -2px, -4px);";
SVGPath arrowShape = SVGPathBuilder.create()
                                   .content(arrow)
                                   .style(arrowStyle)
                                   .build();


pane.getChildren().addAll(backgroundShape, glossShape, arrowShape);



And here you will see the original (left) and the converted version (right):




So if you have to convert a shape from your drawing to code you might want to use SVGPath which makes this task a piece of cake.


The nice thing about this approach is that once the path is a SVGPath you could do everything with it that works on javafx.scene.shape.Shape like scaling, adding effects etc.


And there's one more thing that might be interesting for you...one could use the SVG paths directly in css. This will allow you to separate the visualization completely from the code. In this case you would only define a StackPane in the code and apply a style to the stackpane object. The appearance of this stackpane object is then completely taken from the given css definition.
The code for the example above would than look like this:



Pane pane = new Pane();


StackPane backgroundPane   = new StackPane();
String backgroundPaneStyle = 
    "-fx-background-color  : transparent, rgb(255,255,255), rgb(96,150,227);" +
    "-fx-shape             : \"M 62.6381 6.8085 C 31.0529 6.8085 5.447 32.4156 
                               5.447 64 C 5.447 66.482 5.6577 68.9089 5.9636 
                               71.3072 C 9.5577 99.4342 33.5351 121.1915 62.6381 
                               121.1915 C 91.7415 121.1915 115.7188 99.4342 119.313 
                               71.3072 C 119.6185 68.9089 119.83 66.482 119.83 64 C 
                               119.83 32.4156 94.2232 6.8085 62.6381 6.8085 Z\";" +
    "-fx-background-insets : 0, 0, 11;" +
    "-fx-padding           : 0 128 128 0;";
backgroundPane.setStyle(backgroundPaneStyle);


StackPane glossPane   = new StackPane();
String glossPaneStyle = 
    "-fx-background-color: transparent, transparent, rgb(35,110,216);" +
    "-fx-shape           : \"M 62.6381 114.383 C 88.9706 114.383 110.6626 94.6968 
                             113.9152 69.2487 C 100.6936 60.109 82.6032 54.4681 
                             62.6381 54.4681 C 42.673 54.4681 24.5821 60.109  
                             11.3617 69.2487 C 14.6139 94.6968 36.3059 114.383 
                             62.6381 114.383 Z\";" +
    "-fx-padding         : 0 103 60 0;";
glossPane.setStyle(glossPaneStyle);
glossPane.relocate(13, 56);


StackPane arrowPane = new StackPane();
String arrowPaneStyle =
    "-fx-background-color: transparent, transparent, white;" +
    "-fx-shape  : \"M 44.7016 41.0951 L 69.3251 65.7207 L 44.5005 90.2008 L 55.7281 
                    101.4289 L 92.0866 65.0698 L 56.5768 29.5638 L 44.7016 41.0951 
                    Z\";" +
    "-fx-padding: 0 48 73 0;" +       
    "-fx-effect : dropshadow(gaussian, rgba(0,0,0,0.35), 4, 0.1, -2px, -4px);";
arrowPane.setStyle(arrowPaneStyle);
arrowPane.relocate(45, 30);


pane.getChildren().addAll(backgroundPane, glossPane, arrowPane);



And to be complete again a comparison between the original and the style based approach:








Keep in mind that you would usually store the style information in a separate css file instead of using it inline.


That's it so far...i hope this post will be usefull for one or the other...




Keep coding...

Friday, March 23, 2012

Friday Fun Component XVI

Hi everybody,
time for some fun again...last monday i attended a meeting where some colleagues presented some piece of software. The software was a logfile analyzer and to make the results comparable they've added the so called score of the result. This is a simple integer between 1 and 5, where 1 is bad and 5 is very good.
This score thing reminded me on a graphic that i found on the web a few days ago and i decided to create a little component to visualize the score of something.
Long story short, here is the screenshot of the component...



The image above visualizes all available features of this component. Here are the available properties:


noOfArrows      setNoOfArrows(int) [3 - 10]
                getNoOfArrows()
score           setScore(int)
                getScore()
colorDirection  setColorDirection(ColorDirection) ColorDirection.RED_TO_GREEN
                                                  ColorDirection.GREEN_TO_RED
                getColorDirection()
textVisible     setTextVisible(boolean)
                isTextVisible()
textColor       setTextColor(Color)
                getTextColor()


And i think that's it with this component, like i said it's really simple but it might be useful for one or the other, so enjoy using it...
------------------------------------------------------
here is the binary and the NetBeans project:
binary:                 score.jar
NetBeans project: Score.zip
------------------------------------------------------

Enjoy the upcoming weekend and keep coding...

Monday, March 5, 2012

SteelSeries 3.9.20 (cough...3.9.23)

I know i know...long time no update...sorry for that... :)


In the meantime i released some versions of the SteelSeries library but most of the changes have been related to issues so i did not blog about it.
Now in the 3.9.23 release i have something that might be interesting for one or the other of you.
I gave some love to the DisplaySingle component (LCD) because we needed some features in our software at Quintiq.
First of all i've changed the digital font to a more light version and this is how it looks like...




As you could see the font is not as bold as before and also not italic. 


In addition i've added a bargraph to the lcd that shows the current value in relation to the min and max value of the component.
That means if you set the min value to 0 and the max value to 100 and have a current value of 50 the bargraph will be half filled.


Here you get an impression:




If you add sections to the DisplaySingle component the bargraph will use the colors of the sections to visualize the current value. This might be usefull to visualize the quality of the current value.
In this case one could choose between a plain color or a radial gradient as painter for the bargraph leds by using the method setPlainBargraphSegments(true/false). 


You could see the difference on the next screenshot...




Without sections the bargraph leds will have the same color as the lcd text (top), with plainBargraphSegments set to true and with sections applied to the DisplaySingle component the bargraph leds will be filled with the color of the currently active section (middle). If you set the plainBargraphElements to false the bargraph leds will be filled with a radial gradient using the color of the currently active section.


And that's all what is new in the current SteelSeries release.


One more thing...


As you might know i started porting the SteelSeries library to JavaFX 2.x and i would like to tell you that there won't be a seperate SteelSeriesFX library in the future because i've decided to make the gauges part of the JFXtras project. I won't go into detail now but believe me when i say that this project will rock (again)...so stay tuned...


...and keep coding... :)




SteelSeries 3.9.23:


Binary release    : steelseries-3.9.23.jar


Maven central    : link



Friday, January 27, 2012

Gradient trick...

Aloha,
during my work at Quintiq i stumbled upon a problem when drawing lot's of linear gradients in "realtime". In our software we have a gantt chart component that could contain thousands of nodes. Each of these nodes could contain multiple so called compartments which are representing a range of values. So the node itself is visualized using a LinearGradientPaint and also each compartment is visualized with it's own LinearGradientPaint. So far this should not be a problem but now it comes...we can't really cache things because the whole gantt chart is so to say "live". This means if somewhere in the businessmodel a value changed it will affect the ganttchart in the way that the nodes and their compartments will change it's size. Another problem is that the nodes could not only have different widths but also different heights. 
The compartments are separate shapes that will drawn on top of the nodes.
And that's not enough, the chart that is visible on the screen only represents a small part of the whole data which means one could scroll horizontal which let new nodes appear on the screen and others might change their height (this is something special to this kind of graph in our software).



Long story short...we could nail the performance problem to the drawing of the linear gradients and their creation. 
So i was thinking about how to improve the drawing speed of these gradients and came to an interesting approach that i would like to share with you in this post.

First of all i created a 1px wide BufferedImage with the most common height of the nodes. Then i filled this 1px image with a linear gradient (e.g. the green one) and saved the image for later use. Everytime when there was a new color of a compartment i created an 1px gradient image for this color. 
The trick is now to use the TexturePaint to fill all these nodes which has the big advantage that it will scale the gradientimage automaticaly to the needed height. Because we have to create each gradient only once now the repaint speed could be reduced by 30ms on each repaint.

This performance problem only occured when the gantt chart became really huge with thousands of nodes, but i thought it might be interesting for you to know.

Here is a little code snippet that will give you a hint on what i did...

private BufferedImage nodeTexture;

private void init() {
    private final float[] fractions = {
        0.0f,
        0.5f,
        1.0f
    };
    private final Color[] colors = {
        Color.RED,
        Color.GREEN,
        Color.BLUE
    };
    nodeTexture = createNodeTexture(24, fractions, colors);
}

@Override
protected void paintComponent(Graphics g) {
    ...
    Graphics2D g2 = (Graphics2D) g.create();
    for (RoundRectangle2D node : nodes) {
        TexturePaint nodePaint = new TexturePaint(nodeTexture, node.getBounds());
        g2.setPaint(nodePaint);
        g2.fill(node);
    }
    g2.dispose();
    ...
}

// Method that creates a 1px wide gradient image    
private BufferedImage createNodeTexture(final int HEIGHT, float[] fractions, Color[] colors) {
    GraphicsEnvironment gfxEnv = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsConfiguration gfxConf = gfxEnv.getDefaultScreenDevice().getDefaultConfiguration();
    BufferedImage image = gfxConf.createCompatibleImage(1, HEIGHT, Transparency.OPAQUE);
    Graphics2D g2 = image.createGraphics();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    Point2D start = new Point2D.Double(0, 0);
    Point2D stop = new Point2D.Double(0, HEIGHT);
    final LinearGradientPaint GRADIENT_NODE = new LinearGradientPaint(
        start, 
        stop, 
        fractions, 
        colors);
    g2.setPaint(GRADIENT_NODE);
    g2.fillRect(0, 0, 1, HEIGHT);
    g2.dispose();
    return image;
} 

Before i forget it...we are hiring, so if you are looking for a job in the Java and/or C++ area please check here


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

Friday, January 6, 2012

Friday Fun Component XV

Here we go again...
Today i have nothing special for you but just another traffic light component. This time the component is more compatible to different background colors because it's semitransparent.
We needed something for our software and the other traffic light component was simply too dark...so i created this one...

click to see it in action...


As you can see it comes in two versions and you could switch between both versions by using the yellowVisible property.

The frame has the color #333333 with an opacity of 50% and the inner part has the color #CCCCCC with an opacity of 50%.
Due to the transparency this component fits better on different backgroundcolors because they shine through.


This component is now also part of the SteelSeries Java Swing component library.


Well that's all for this friday, as always you could download the binary and source (as NetBeans project) here:


binary version: TrafficLight2.jar


source          : TrafficLightDemo2.zip


So enjoy the upcoming weekend and keep coding...

Monday, January 2, 2012

SteelSeries 3.9.10 (QuickRelease)

Happy new year everybody...


UPDATE: due to some minor modifications the current version is 3.9.12


I know i said it would take some months until you will see the next release but i needed some components be part of the library so i decided this morning to make a quick release and added these new things to the lib.
The new things i have added are the traffic light and light bulb you might know already from the friday fun components, another traffic light component that might fit better to different color schemes and at least 8 new indicator symbols in the IndicatorGauge. 
To give you an idea on what the stuff looks like...here they are...


The traffic lights and the light bulb...




and the eight new symbols which are just arrows pointing to different directions...




And that's all for this release...like i said a quick release with just a few new additions. You will find the new version either here on this blog on the right side or at MavenCentral.


For those of you that are interested in the progress of the SteelSeriesFX i could show you one screenshot of the current state...


As you can see i made some progress but it's still a looooooong way to go...


so stay tuned and keep coding...









Friday, November 25, 2011

SteelSeries 3.9.9

It took some time due to some conferences and my new job but i finally decided that it's time for another release of the SteelSeries component library.
Because i will port the complete library to JavaFX 2.0 this will be the last release  of the Swing library for the next months. 
Porting the lib to JavaFX 2.0 means a complete rewrite from scratch combined with learning JavaFX...so this will also take some time...which means patience my friends...
But now let's talk about the stuff that's in this release...


The DisplaySingle component (lcd with a single row) got most of my attention in this release. So first of all it's now capable of displaying also text instead of numbers only.


Click me to see a youtube video of the scrolling...
If you click on the link below the image you will see a little video on youtube that shows the rudimentary scrolling capability that is supported by the DisplaySingle component.
The display of text could be enabled/disabled by using setting the lcdNumericValues property to false and fill the lcdText property with some text.


There's also a new LcdColor available that is only useful in the DisplaySingle component and will be used to visualize sections in the lcd display.


Without any section applied to the DisplaySingle it will look like this:






As an example i defined sections as follows:


Section[] sections = {

    new Section(0, 25, Color.GREEN),
    new Section(25, 50, Color.YELLOW),
    new Section(50, 75, Color.ORANGE),
    new Section(75, 100, Color.RED)
};



If you set these sections with the setSections() method to a DisplaySingle component and activate the visibility of the sections by calling setSectionsVisible(true) you will get results like follows:










We will use this feature to visualize the quality of kpi's in the next version of the Quintiq software.


In the gauges it's now possible to adjust the color for the inner (green in the image) and outer frame (red in the image), which was requested...






And again some new pointer types are available...







The pointer type 13 and also type 2 now change their color dependend on the background color. That means the pointer will get a better contrast on the choosen background color. The color that will be used to fill the pointer is the same as the label color defined in the background color.


Another new thing i've added to the lib is the ability to use logarithmic scaling for the gauges which might be useful when measuring over a large range of values.
The implementation is rudimentary and only for base 10 but it's a start...


logScaling disabled (default)

logScaling enabled
The logarithmic scaling is available on the radial and linear gauges and bargraphs.


As you could see on the images above there's also another new feature that makes it possible to adjust the orientation of the ticklabels.
There are three possibilities available:

  • normal
  • horizontal
  • tangent

and that's how they look like...






And that's still not the end, there's also a new frame design called GlossyMetal which looks like this...




Started talking about the frames there's also a new feature that makes it possible to choose a custom color for a frame (this feature only works for the frame design named ShinyMetal) and could be switched on with setFrameBaseColorEnabled(true). If you have switched this feature on you could set a frame base color that will be used to colorize the frame of the gauge which leads to a visualization like this...






The next feature is something that was on my list for a long time but i never found the time to do it...now it's done...
Frameless gauges...



If you switch off the visibility of the frame the gauge will take the whole space of the component instead of simply not show the frame. This is really useful if you do have a lot of gauges on your dashboard where you don't need the frames.


At least i made some modifications to the visualization of the sections in a gauge that might be useful for business dashboards. Because that are only small modifications i won't explain everthing but show you some more images...










As always you could find the binary version on the right side of this blog.


I guess that's it for 3.9.9 and like i said already this will be the last release for the next months because i really have not time to do all this stuff in my spare time again and will focus on the SteelSeriesFX version...so stay tuned and keep coding...