Tuesday, April 27, 2010

So What's It All Good For?

Ok, so my previous post (which I refer to facetiously as the Encyclopedia of JavaFX Styling) was a tad on the long-ish side. It contained a lot of not-so-trivial-to-understand information. It contained information that was biased toward helping control authors understand the new system rather than application developers.

So I can certainly understand the reactions of some folks: "Holy cow that looks complicated!" or "Why should I learn all of that?" or "What's this new-fangled system even good for?". The reason application developers should learn the new styling system is very simple: you can now do things with a few lines of CSS that used to take many lines of JavaFX code.
Like all of JavaFX, it's all about developer productivity!
Let's say as an application developer you decided that:
  • All of your application buttons should be round, or
  • Your checkboxes should have red X's rather than black checks and the text associated with them should turn red when the checkbox is selected, or
  • You want an awesome slider for your "number of gold stars" rating system complete with a star-shaped thumb bar that casts a drop shadow! (Really? Ok...).
Pre-JavaFX 1.3 you would be doing some combination of styling and overriding skin classes and rewriting skin code. Now with JavaFX 1.3, all of this is just a style sheet away.
.scene {
    -fx-font: 16pt "Amble"
}

.button {
    -fx-base: dodgerblue;
    -fx-shape: "M 50,30  m 0,25  a 1,1 0 0,0 0,-50  a 1,1 0 1,0 0,50";
    -fx-scale-shape: false;
}

.check-box:selected *.label {
    -fx-text-fill: red
}

.check-box:selected *.mark {
    -fx-background-color: red;
    -fx-shape: "M 0,0 H1 L 4,3 7,0 H8 V1 L 5,4 8,7 V8 H7 L 4,5 1,8 H0 V7 L 3,4 0,1 Z";
}

.slider *.track {
    -fx-base: derive( goldenrod, 50% );
}

.slider *.thumb {
    -fx-shape: "M 50,5 L 37,40 5,40 30,60 20,95 50,75 80,95 70,60 95,40 63,40 Z";
    -fx-background-color: derive(goldenrod,-50%), goldenrod;
    -fx-background-radius: 0, 0;
    -fx-background-insets: 0, 2;
    -fx-padding: 10;
    -fx-effect: dropshadow( two-pass-box , rgba(0,0,0,0.6) , 4, 0.0 , 0 , 1 );
}

Just apply this style sheet and BLAM! All your buttons are round, all your checkboxes are X'ed, and all of your sliders are golden. Life is good. Behold.

simpleskinning.png

Although... we may want to re-think that red checkbox label. Ick.

25 comments:

  1. Ok. That kinda makes sense. But I still don't like it ;-)

    ReplyDelete
  2. Tom: :-) To each, his (or her) own!

    ReplyDelete
  3. I like the slider. :-)

    ReplyDelete
  4. I liked your previous post, too. In fact, I expect the usage of ladder function, too. I'm trying to rewrite Caspian.getXXXYYY(base) functions.

    ReplyDelete
  5. ihsan: ladder is a curious creature. It's function is to pick a single color out of a gradient. So if we write:

    -fx-base: ladder(steelblue) stops (0.0, black) (1.0, white)

    Then we will select a color along the range from black to white based on the calculated brightness of steelblue. Since steelblue is a little on the darker side, you would end up using a dark gray for your -fx-base in this case.

    Dean

    ReplyDelete
  6. ihsan: Correction, that ladder function should be written as:

    -fx-base: ladder steelblue stops (0.0, black) (1.0, white);

    No parenthesis around the steelblue. Sorry about that!

    ReplyDelete
  7. >> you can now do things with a few lines of CSS that used to take many lines of JavaFX code.

    I agree, the css stuff, makes simple things simple and more complicated things easier - the css way is more manageable and more concise.

    If you compare the styling done with 1.3 and how you needed to do stuff previously with 1.2, http://pleasingsoftware.blogspot.com/2009/12/creating-custom-caspian-controls.html, it is clear that JavaFX has undergone a quantum leap in styling capabilities. Not to say that more great leaps forward aren't appreciated/required :-)

    ReplyDelete
  8. Hi Dean,

    This is some good stuff, its very much pleasing me!

    This kind of info and detail and granularity in terms of relating it to simpler shapes is just what the doctor ordered. Keep it coming, its causing me to reconsider in favor of using nodes for music notation symbols.

    The big question of the day for me is if all this wonderful styling only applies to Controls or also to straight Nodes? My symbols are also very interactive so it is not a far jump to think of them as Controls, however, are Controls much more heavyweight than Nodes? What about Nodes inside Controls, is their styling limited because they are not regions?

    Also, SVG Path support rocks! What is very much needed is a method to read a glyph (say its from a music notation font) and to be able to convert it to a SVG Path. Or maybe just use it directly as a Shape. Are these alternatives doable? Really need this thype of functionality in order to move forward here.

    Cheers!

    ReplyDelete
  9. Torch: What is very much needed is a method to read a glyph (say its from a music notation font) and to be able to convert it to a SVG Path. Or maybe just use it directly as a Shape. Are these alternatives doable?

    Yes, they are, although I am not sure of the runtime performance for an entire music score on the screen - you'd have to try it and see I guess.

    Here is a tool to convert truetype fonts to svg:

    http://xmlgraphics.apache.org/batik/tools/font-converter.html

    Wikimedia commons also has some music notation symbols in svg format, for example:

    http://upload.wikimedia.org/wikipedia/commons/5/55/1-8_note_quaver_%28music%29.svg (open in firefox and view source to get an svg path).

    ReplyDelete
  10. Thanks, the Truetype to SVG converter is helpful.

    There are some good options but they are not tested, basically I'm thinking along these lines:

    1 - Convert my font to SVG.
    2 - Open it in Illustrator, arrange it for FXZ format and save it as FXZ.
    3 - Use it in JavaFX as a palette of ready made nodes that can be duplicated as needed.
    4 - Create and use JavaFX Stylesheets to skin the nodes further.

    It would also be possible to use the SVG paths from font glyphs as paths in the style sheet directly.

    This is all super and it has me excited but performance could be an issue. What is needed is a way to reuse and reskin a limited number of nodes on the fly, so there are just enough nodes to display the data that is currently on screen.

    My data model is apart from JavaFX and handles all time related issues and much more. All I expect from JavaFX is to do its graphic representation thing well.

    I'd like to test all these possibilities out soon, as a prototype project to see how it all fits together.

    ReplyDelete
  11. I tried the batik tt2svg converter and I'm not sure its working. Batik is fairly old, anyways I just get "Unable to access jarfile batik-tt2svg.jar
    " on OS X 10.6.3.

    Does the convert work for you?

    ReplyDelete
  12. @torch: fontsquirrel http://www.fontsquirrel.com/fontface/generator will run a free ttf => svg conversion for you. Just upload your ttf font there and all of the gylphs will come back in svg format. Many free fonts are available here => http://www.dafont.com/

    ReplyDelete
  13. Very appreciated, font squirrel seems to work fine. I have not yet tried the SVG paths it generates in a JavaFX stylesheet, hopefully that works okay.

    ReplyDelete
  14. Let's compare ways to build themed controls in JavaFX. I used CSS, javafx.scene.control.Skin and javafx.scene.CustomNode to implement same mixin class.
    You can test applet and download source from

    http://www.javafx.me/files/jfx/wrongcss/JavaFXwrongCSS.html

    How it works:

    * Default buttons - just default buttons.
    * Custom components - see javafxwrongcss\components\custom\GlassButton.fx. You can use any JavaFX components to create any desing. Buttons starts flicker while you place mouse over it. Looks nice.
    * Skinned component - see javafxwrongcss\components\skinned\SkinnedButton.fx. You need create class that extends Skin and assign it to your button. Your skin need same code as Custom component example.
    * CSS - see javafxwrongcss\components\withcss\CSSButton.fx. You need describe button's design in .css file. You need use ugly CSS sintax instead of JavaFX Script. No binding, no custom shapes, no additional behaviour. CSS too poor so CSS buttons are ugly. Moreover you can't change CSS style programmaticaly so you can't change color from external code.

    ReplyDelete
  15. @Torch and @jsmith,great discussion guys. Really useful info!

    Sergey: :-) That's what I love about you, you're never bashful about sharing your opinions. I think what you might be overlooking is that JavaFX supports these three different methods because there are different use-cases.

    For someone who is trying to create *reusable* controls rather than one-off custom controls, the new CSS support makes it easy for the users of your controls to customize the look while taking advantage of the (sometimes complex) functionality of the control.

    Not everything is as simple as a custom button, so most times you want to re-use other controls but adjust the look slightly so it fits into your application. This rather large use-case covers folks like the jfxtras authors and, of course, the JavaFX runtime team at Oracle. Not surprising then that they spent time to make sure their users could customize the controls they've spent so much time writing.

    If you enjoy writing custom controls for just your application and dislike CSS syntax, that's great! JavaFX supports the way you want to work.

    It may be just a bit hasty of you to dismiss everyone else's use-cases as trash or a waste of time, though.

    Dean

    ReplyDelete
  16. This rather large use-case covers folks like the jfxtras authors and, of course, the JavaFX runtime team at Oracle.
    --

    just show me this "use case".

    You can't derive CSS style from other CSS style.
    You can't create new components properties from CSS. You can use existing properties only.
    You can't debug CSS styles.
    You can't use CSS style to create new behaviour of component.

    CSS is widely used for extending HTML. HTML is very limited. JavaFX has rich facilities for GUI development. There aren't any need to use CSS in JavaFX.

    I work as GUI developer more 10 years. I used JavaFX in 4 commercial projects. I think you should listen to me.

    ReplyDelete
  17. Sergey,

    Certainly we should abandon logic and reason and just go by experience, right? Since I've been developing GUIs longer and have written more JavaFX applications, does that mean that you now have to listen to me? That would be silly.

    Look, I think you're a talented guy and I respect your opinions even when I don't agree with them. But if you keep making ridiculous statements like that, people are going to stop taking you seriously.

    Besides which, I think you have sort of missed the point. Nobody is trying to force you to write Region-based, style-able controls. In fact, I would actively discourage anybody from doing it (see the warning in my previous post) unless they completely understood the ramifications of relying on private APIs.

    There is only one, I repeat, ONE, case where most people should use CSS at the moment: when they need to change the look of one of the core controls to match the requirements of their application. That was the subject of this post (did you actually read it?), see the gold star slider above.

    It took me less than 5 minutes to write and test those 10 lines of CSS. I would be pretty skeptical if you told me that you can write a gold star slider faster and easier than that using a custom control or by overriding the core slider's skin.

    I would guess that it would take even a great, experienced JavaFX programmer like yourself at least five times that long (yes, 25 minutes) to create the whole control yourself or to create a new skin for the existing slider.

    Do you see the use-case now? Being able to easily and quickly adapt the look of existing controls *will save you time* on your project. You may not be able to appreciate that, but you are not the only user of JavaFX. Believe me, the guy that does need the gold slider, the round button, or the ugly red checkbox label does appreciate the time savings.

    My point is that you are free to, and in fact I would encourage you to, completely ignore the CSS functionality and continue to write custom controls for your applications.

    Dean

    ReplyDelete
  18. look to my point of view: CSS isn't enough for nice GUI. JavaFX team should take care about missed controls (grid, treeview and many other) but not for useless technology.

    ReplyDelete
  19. I think we can agree that it would be nice if JavaFX was progressing more rapidly. There are certainly things that made it into this release that aren't at the top of my priority list either. The old CSS support was kind of slow and buggy, but I probably would have preferred a tableview and other controls to all of this new CSS support, myself.

    But I realize that if they did that, people would undoubtedly be complaining right now that they couldn't customize their tableviews easily like they can in HTML5 and Flex4.

    Writing a brand new toolkit like this, and balancing the competing demands of many internal and external users, is certainly not an easy job.

    ReplyDelete
  20. May be it is time for Oracle dismiss the whole JavaFX team.

    They are unable to add the required components like grid or richtextbox. They waste time for useless technologies like CSS.

    All i listen from JavaFX team is "coming soon". They say it for JavaFX 1.0, 1.1, 1.2 and now for 1.3. But Swing, Flex and Silverlight have all those components now.

    ReplyDelete
  21. I think Oracle need real professional RIA developers.

    ReplyDelete
  22. 2 Sergey Surikov:
    I don't think CSS is useless, and Swing, Flex and Silverlight has it's own problems.
    And if you're so experienced, you'd better start writing your components like Grid or Tree and stop writing such comments, cause everyone knows that JavaFx isn't perfect in all aspects, but it more faster then Swing and more secured then Flex.

    P.S. Я думаю тебе стоит извиниться перед чуваком, который пишет отличные статьи. А для того чтобы высказывать свои негативные и независимые мысли, люди, в наше время, заводят блоги.

    ReplyDelete
  23. да я тоже не лаптем щи хлебаю. И с JavaFX я работаю ещё когда оно называлось F3.

    see
    http://code.google.com/p/crudfx/
    http://jfxstudio.wordpress.com/author/surikov/
    http://javafx.me/

    ReplyDelete
  24. Thank you for those links, nice job I should say :) but don't be so pessimistic if compare 1.2 and 1.3 We already have List and ComboBox :) and CSS support is really nice.

    I think the main problem why development of JavaFx was so slow is about that migration Sun into Oracle.

    ReplyDelete
  25. I strongly believe that CSS style of Look & Feel development is lot quicker than other means.

    The only problem I see is the Look & Feel development should be done by Web Designer's, not developer's. There should be a Visual Tool for CSS creation or a easy way to import existing CSS and converting into the JavaFX CSS.

    is JavaFX Team working on any tool like this ?

    -Not all Developer's are as good as WebDesigner's.

    ReplyDelete

Please Note: All comments are moderated. That's why you won't see your comment appear right away. If it's not some stupid piece of spam, it will appear soon.

Note: Only a member of this blog may post a comment.