Tuesday, June 14, 2011

SteelSeries 3.9.3

Hello again...it's time for another release of the SteelSeries Java Swing component library.


Enable / disable nice scaling...
Because somebody asked for it i added the functionality to disable the usage of the automatic tickmark calculation. If you have for example limits of

  • minValue = 0
  • maxValue = 124

and you use the automatic tickmark calculation (niceScale=true) the calculation will set the maximum value to 140 instead of 124 to get a nice scaling. There might be usecases where you need to have the scale ends at 124 and for this reason one could now enable/disable the nice scaling by the method setNiceScale(boolean) which default's true.
A picture will better explain what this means...


On the left gauge the niceScale property is set to true and on the right it is set to false.


More realistic inner shadow on radial gauges...
Another tiny thing that annoyed me a long time was the inner shadow of the radial gauges. Somehow it looked not the way it should and therefore i modified it a little bit so that it looks better to my eyes now.




                    

You might not even noticed the difference but for me it was visible all the time so i had to change it... :-)

New backgrounds...
When i was playing around with the lib i thought i might add more background colors to the gauges and so i've added six new designs...


Well not all of them might be useful but you never know...so feel free to play around with it. Here i would like to thank Wolfgang Zitzelsberger of Jyloo Software for the idea with the carbon. And by the way if you don't know him you should know that he's in charge of the Synthetica look and feel which you could find here

StopWatch component...
And i have to say thanx again to Wolfgang because he also asked me for a StopWatch component and here it is...


It's nothing special with this stopwatch, just a simple analog stopwatch.

Additional clock design...
And talking about clocks...there's also a new clock design available in the existing Clock component of the SteelSeries. I while ago i created a Swing component that looked like the clock of the german railway company "Deutsche Bahn". So for those who do not know this clock just click this link and you will find some images of it. So my version looks like this...


You could activate this design by changing the pointerType property in the Clock component to eu.hansolo.steelseries.tools.PointerType.TYPE2. In addition i've added the ability to let the second pointer move continuously by calling secondMovesContinuous(true).
Because it's derived from AbstractRadial you could use all the frameDesigns, backgroundColors, pointerColors (except the SecondPointer which is always red) and foregroundTypes to customize this clock.

Additional frame designs...
So now that i mentioned frameDesigns it's time to talk about some new frameDesigns too. I have added three new frameDesigns to the lib that are looking like this...


It's again nothing special but i thought you could never have to much designs to choose from. Of course this designs are available for the linear gauges too. Because we are talking about the frames already i extended the effect feature of the frames. 

Frame effects...
In the former version you only could activate one frameEffect but i found that there too many possibilities that might make sense too, so i added a property named frameEffect and you could choose between four different effects as overlay for your frame, here they are...


These frameEffects will work on all frameDesigns and on the radial and linear gauges. They won't work on the Radial2Top and Radial1Square component right now (but i'm working on a new ContourGradientPaint which hopefuly will make it possible to use it on these gauges too).
Instead of adding a new ContourGradientPaint class i have added a class to scale convex polygons which makes it possible to apply the frame effects also to the Radial2Top and Radial1Square component. 

Additional foregrounds...
But not only the backgrounds and frames got something new, i've also added two new foregroundTypes to the radial gauges, check them out...

The left one (TYPE4) has a more unobtrusive look where the right one (TYPE5) stays more present in the foreground. 

Number systems in lcd...
So far so good but that was not the end right now...i've got the request if i could add a hexdecimal numberformat to the lcd component and you know i always try to do my best to make your wishes come true, so i added it to the lcd in general which means it's now available in all gauges and in the standalone lcd displays too. 


Right now the decimal, hexadecimal and octal number system is supported.

Additional lcd design...
Well there are some color schemes for the lcd but from time to time i find something new to implement and so i added another LcdColor named STANDARD_GREEN which looks like this...


Like all the other things nothing special but it looks nice doesn't it...?

Additional pointer type...
And talking about little new things i also want to mention the new pointerType in the radial gauges named TYPE9 that i found on a car...


This pointerType is a bit special, because it won't change it's color if you set the pointerColor but it will only change the little rectangle at it's end to the given pointerColor which means this pointer is best used on bright backgrounds.

Additional threshold indicator...
And now the smallest new add on (and it might change in the next release because i'm not 100% satisfied with it), another thresholdType named ARROW which comes in addition to the former thresholdType that is now named TRIANGLE. The color of the threshold indicator could now be modified too.



Additional center knob...
Another tiny thing i've added to the library is a new type of center knob which is available for all radial components. Here's how it looks like...


KnobStyles...
After i finished the new center knob i figured out that it might be a good idea to have knobs with adjustable colors because if you have a brass colored frame the silver center knob won't fit very well to the design. Long story short...here they are...



You might have figured out that the standard knob also got a little polish and looks more shiny now. By the way, the MinMax alignment posts do change their color too... :-)


Additional pointers for the compass...
Oh what's this...how does the compass pointer look like...? Ahh...yes i gave some love to the compass component and added two additional pointer types, so here is an image of the three available types of pointers in the compass component...


So far so good, now i just have another little modification which might be usefull for one or the other of you...the ability to save an image of a component.

Save component as image...
Each component now has a method named getAsImage() which will return a buffered image of the current state of the component. In addition i've added another helper method to the Util class in the package eu.hansolo.steelseries.tools which will save the given buffered image as a png image with the given name. Here's a small example on how to use it...

// the component we would like to save as image is named radial
SwingUtilities.invokeLater(new Runnable() 
{
    @Override
    public void run() 
    {
        // store the radial component as radial.png
        Util.INSTANCE.savePngImage(radial.getAsImage(), "radial.png");
    }
});


New battery component...
Man that's a long post with lots of pictures again and to give you some eyecandy at the end i've added a battery component to the SteelSeries lib that takes integer values from 0 to 100 and looks like this...


So...i think it's done for today, i hope some of these modifications will be of use for you and please do me a favour and let me know if you have the need for a special component and i'll see what i can do for you...

Keep coding...

26 comments:

  1. Loving your post! excellent tools! Thanks to share!

    ReplyDelete
  2. Hi PrinCeSs,
    Glad you like it... :-)

    ReplyDelete
  3. Good work... keep it up :)

    ReplyDelete
  4. Very impressive and thank very much for sharing!
    I'm starting to use and study the library and I have a first question: why the DisplaySingle class is declared final? I want to extends with some custom functionality. Do you suggest a better way?

    ReplyDelete
  5. Hi Giulio,
    You might want to check out the source and create your own component from it directly. I made it final to avoid problems with derived versions of the class but it would be possible to change it in future versions of the lib again.
    Maybe you would like to let me know your custom functionality and i might add it to the component if it's useful for others too...
    Cheers,
    Gerrit

    ReplyDelete
  6. Hi,
    yes I can change the source directly but I want to avoid changing the library source every time I check out a new release. I prefere to change my source if the new release of the library is not compatible with the previous (I hope not so frequent).
    Mainly I need a "standard" way to connect to the values from the field (PLC variables and calculation of the application) and some other things.
    I'll be more precise ASAP.
    Thanks in advance for the availability.

    ReplyDelete
  7. niceScale works! i think you forgot some Sysouts."Model setMaxValue" , but its not problem at all.

    I have a doubt... I added a radial gauge inside a jframe with a jpanel using border layout center. But the gauge border dont auto fit correcly(cuts the bottom) when i'm resing the window.

    That happens too when the size of the frame is little (300,300). Theres a minimum size that i must force and fix the frame?

    ReplyDelete
  8. Hi,
    about my previous comment: I changed my code so that my class doesn't extends DisplaySingle but has a DisplaySingle object as a private variable. This way the objects of my class are no more JComponent and i need to call a new method getComp() where i need a JComponent and if i need a DisplaySingle component i have to call a new method getDisplaySingle().
    It works fine but I don't know if all this is better or not.

    The main feature i added are:
    1. A way to connect to "variable" so that when the variable change the display change too. I done this becouse i want a common interface for different kind of object. For example for DisplaySingle to change the value i have to call the setLcdValue(); for Radial i have to call setValueAnimated() (if it's animated) or setValue() (if it's !animated).

    2. A way to set a unit converter for the value to be displayed. Yes i can create a new "variable" that is the converted value of the base variable.


    Another question is about (for example) LcdColor: i need a custom LcdColor but i want to create it exactly the same way LcdColor are created; i think it would be nice if LcdColor is a standard class so that object can be instantiated like
    MYCOLOR=new LcdColor(...)
    At the moment i have to set LcdColor.CUSTOM and then create a Color and a Paint and call setCustomLcdForeground() and setCustomLcdBackground(). This is more flexible but is different. Maybe LcdColor can be rearranged to be an interface:

    interface LcdColor {
    Color getForeground();
    Paint getBackground();
    }

    Sorry for all this, i hope it's a bit of interest to you.

    bye

    ReplyDelete
  9. Hi,
    i done what i say in my previous comment about LcdColor in a way that is completly backward compatible.
    If you want i can send the files i changed in the library so you can check.

    Now in my code i can do something like this:


    public static final LcdColor.LcdColorClass ORANGE_LED = new LcdColor.LcdColorClass(
    new java.awt.Color(80, 55, 0, 255),
    new java.awt.Color(60, 40, 0, 255),
    new java.awt.Color(38, 26, 0, 255),
    new java.awt.Color(17, 12, 0, 255),
    new java.awt.Color(4, 3, 0, 255),
    new java.awt.Color(255, 79, 19));

    DisplaySingle comp = new DisplaySingle();
    comp.setLcdColor(ORANGE_LED);
    comp.setLcdColor(LcdColor.BEIGE_LCD);



    About the "final" problem of the DisplaySingle class i adopted the following strategies. Maybe someone can be interested in it.


    public interface DComponent {
    public void setTheValue(double value);
    public T getComp();
    }

    public abstract class DComponentAbstract implements DComponent {

    protected final T comp;

    public DComponentAbstract(T comp) {
    this.comp = comp;
    }

    @Override
    public T getComp() {
    return comp;
    }
    }



    public class DValue extends DComponentAbstract {

    public static final LcdColor.LcdColorClass ORANGE_LED = new LcdColor.LcdColorClass(
    new java.awt.Color(80, 55, 0, 255),
    new java.awt.Color(60, 40, 0, 255),
    new java.awt.Color(38, 26, 0, 255),
    new java.awt.Color(17, 12, 0, 255),
    new java.awt.Color(4, 3, 0, 255),
    new java.awt.Color(255, 79, 19));

    public DValue() {
    super(new DisplaySingle());
    comp.setLcdColor(ORANGE_LED);
    }


    @Override
    public void setTheValue(double value) {
    comp.setLcdValue(value);
    }
    }

    ReplyDelete
  10. Sorry for missings generics in the code above.

    public interface DComponent< T extends JComponent> {
    public void setTheValue(double value);
    public T getComp();
    }

    public abstract class DComponentAbstract< T extends JComponent> implements DComponent< T> {

    protected final T comp;

    public DComponentAbstract(T comp) {
    this.comp = comp;
    }

    @Override
    public T getComp() {
    return comp;
    }
    }


    public class DValue extends DComponentAbstract< DisplaySingle> {

    public static final LcdColor.LcdColorClass ORANGE_LED = new LcdColor.LcdColorClass(
    new java.awt.Color(80, 55, 0, 255),
    new java.awt.Color(60, 40, 0, 255),
    new java.awt.Color(38, 26, 0, 255),
    new java.awt.Color(17, 12, 0, 255),
    new java.awt.Color(4, 3, 0, 255),
    new java.awt.Color(255, 79, 19));

    public DValue() {
    super(new DisplaySingle());
    comp.setLcdColor(ORANGE_LED);
    }

    @Override
    public void setTheValue(double value) {
    comp.setLcdValue(value);
    }
    }

    ReplyDelete
  11. Hello,
    it seems that the minMeasuredValue of the Radial components are updated only if i set the value using the setValueAnimated() and not with the setValue(). Is it right and wanted or i'm doing something wrong?

    ReplyDelete
  12. Hi Giulio,
    Sorry for the late reply, so...the setLcdValue() method was named like this because i use the same component with it's interface in the gauges too and to make it possible to have different values in the gauge and the lcd display i won't change this, sorry.
    The min- and maxMeasuredValue right now is only supported by using the setValueAnimated() method (might change in the future).
    Cheers,
    Gerrit

    ReplyDelete
  13. What about LcdColor? Do you want to look my changes and decide if commit in the next release?

    ReplyDelete
  14. Hi Giulio,
    Could you send me the code ? (han.solo.gg at googlemail.com)
    Have to play with it first...
    Cheers,
    Gerrit

    ReplyDelete
  15. Hi Giulio,

    I found probably a bug for component LinearBargraph. Problem is with the method setBarGraphColor(), when I want to use custom color, component is resized. Here is the example, component with name bar2 describes this behavior.. Thanks for your reply. Best regards,

    Michal

    Example:

    public class Bug {

    private static void createAndShowGUI() {

    //Create and set up the window.
    JFrame frame = new JFrame("FrameDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setExtendedState(frame.getExtendedState() | JFrame.MAXIMIZED_BOTH);

    JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
    frame.getContentPane().add(panel, BorderLayout.CENTER);

    // slider
    final JSlider slider = new JSlider(0, 100, 0);
    panel.add(slider);

    // bar with 'standard' colors
    final LinearBargraph bar = new LinearBargraph();
    bar.setPreferredSize(new Dimension(120, 240));
    panel.add(bar);

    // bar with custom colors
    final LinearBargraph bar2 = new LinearBargraph();
    bar2.setPreferredSize(new Dimension(120, 240));
    panel.add(bar2);

    // change listener
    slider.addChangeListener(new ChangeListener() {

    @Override
    public void stateChanged(ChangeEvent e) {

    if (slider.getValue() < 50) {

    bar.setBarGraphColor(ColorDef.GREEN);

    bar2.setBarGraphColor(ColorDef.CUSTOM);
    bar2.setCustomBarGraphColor(Color.GREEN);

    } else {

    bar.setBarGraphColor(ColorDef.RED);

    bar2.setBarGraphColor(ColorDef.CUSTOM);
    bar2.setCustomBarGraphColor(Color.RED);


    }

    bar.setValue((double) slider.getValue());
    bar.setLcdValue((double) slider.getValue());
    bar2.setValue((double) slider.getValue());
    bar2.setLcdValue((double) slider.getValue());
    }
    });


    //Display the window.
    frame.pack();
    frame.setVisible(true);
    }

    public static void main(String[] args) {

    javax.swing.SwingUtilities.invokeLater(new Runnable() {

    public void run() {
    createAndShowGUI();
    }
    });
    }
    }

    ReplyDelete
  16. I'm not the owner of the project...
    I looked in the source and actually there's a small bug (i think a copy/paste error) in the
    setCustomBarGraphColor() method of the AbstractLinearBargraph class. The second line

    init(getInnerBounds().width, getInnerBounds().width);

    is wrong and must be

    init(getInnerBounds().width, getInnerBounds().height);

    I think it's a copy/paste error because the same is in the AbstractRadialBargraph class but here it's ok because the radials are square.

    Bye

    ReplyDelete
  17. Hi Michal,
    The problem is fixed and you will find it in the latest snapshot binary.
    Cheers, Gerrit

    ReplyDelete
  18. Hi Gerrit, thank you very much! Bye
    Michal

    ReplyDelete
  19. I must say I am much impressed by your work: the amount, and the quality!
    I have only one regret: to have no use, currently, for your nice displays.
    But I am sure I can go back and look at your sources (and articles) for source of inspiration and expertise.
    And, yes, the inner shadow improvement is noticeable and good.

    Keep up the good work.

    ReplyDelete
  20. Hi Gerrit.

    This is really good work. I would really like a linen effect like this:
    http://i.imgur.com/uiiQ7.jpg

    and a way to have translucent text sunken into it :)

    Thanks, Nick

    ReplyDelete
  21. Hi Gerrit,
    i found that when i change the threshold value using the setThreshold() method in a Radial object it doesn't update until the change of the Radial with setValue().

    I look in the source seen that in the setThreshold() you missed to call
    repaint(getInnerBounds());

    maybe for performance reason.

    Bye

    ReplyDelete
  22. Hello Gerrit
    I have found a fellow weather watcher using your wonderful Steel Series gauges http://41south.net.nz/weather/gauges-ss.htm How do I get them or an alternative style http://www.brooklynweather.co.nz/gauges.htm

    Thanks Andrew

    ReplyDelete
  23. Hi Andrew,
    The library could be found on the right side of this blog or also on GitHub. The weather station code is done by Mark Crossley who is also in charge of the JavaScript port of the library. You might want to contact him at
    mark at wilmslowastro dot com
    Cheers,
    Gerrit

    ReplyDelete
  24. Would love the frameeffect.innerframe and glow as i read elsewhere you've added, Inserted into the cumulus setup. Any chance there will be another version off this ? Or hints how to achieve that? LOVE YOUR WORK! ;D

    ReplyDelete
    Replies
    1. Well for the radial gauges this would not be a big deal but for the linear gauges it's needed to create a ContourGradient in Canvas. Maybe I will find some time to do that but I can't promise it...

      Cheers,

      Gerrit

      Delete
    2. I'm all about the radial gauges, so if you could find the time to implement just that it would be much apreciated :) cheers ;)

      Delete