söndag 27 november 2011

JavaFX 2 - Breadcrumbs and styling

One new cool feature in JavaFX2 is that you can style your application using a subset of W3C CSS 2.1. In this post we will be looking into how one can style components and how you can create a basic breadcrumb using the same technich which you can see in the JavaFX2 Assemble application.

The demo that we will be looking into:


First of one should say that the CSS support in JavaFX 2 is not the same CSS as you use on regular web pages. However there are common CSS styles which you can use within JavaFX 2, but they are all named with the prefix 'fx'.

@Override
 public void start(Stage stage) throws Exception {
  initComponents();
  
  VBox mainPane = new VBox();
  mainPane.setId("main");
  mainPane.getChildren().addAll(bc1, bc2, bc3);
  
  Scene scene = new Scene(mainPane);
  scene.getStylesheets().add("com/loop81/sandbox/styles/style.css");

  stage.setTitle("Demo of styles");
  stage.setScene(scene);
  stage.sizeToScene();
  stage.show(); 
 }
 
 /** Create and setup all the components used in this demo. */
 private void initComponents() {
  ...
  
  // Last breadcrumbs. Three elements.
  bc3 = new ToolBar();
  bc3.getStyleClass().add("breadcrumbs");
  
  Button bc3Button1 = new Button("First");
  bc3Button1.getStyleClass().addAll("item", "first");
  
  ...
  
  bc3.getItems().addAll(bc3Button1, bc3Button2, bc3Button3);
 }

Row 10: First of, to get your application styled we need to add the style sheet to the application. This is done by adding a string path to the style sheet on the stage. Note that the style need to be in the class path of your application.

Row 27: Secondly we need to specify which classes that a element should have. As a example have I selected one of the buttons seen in the picture above. Here we add two classes to the element 'item', and 'alone'.

That is basically all you need to do to be able to style you elements. Note that some of the code has been omitted since it is just the same for all the buttons.

Also with JavaFX 2 it is possible to keep all your design code within the style sheet, however you can not specify layout in the style sheet. The layout you will have to write within your java files.

Let us have a look on the styles for this demo.

#main {
  -fx-padding: 5 0;
  -fx-spacing: 5;
}

.breadcrumbs {
  -fx-padding: 0 50 0 0;
}

.breadcrumbs .item {
  -fx-background-color: null;
  -fx-background-radius: 0;
  -fx-background-insets: 0;
  -fx-border-color: null;
  -fx-border-insets: 0;
  -fx-border-image-source: url("crumb.png");
  -fx-border-image-slice: 1 10 1 10 fill;
  -fx-border-image-width: 1 10 1 10;
  -fx-border-image-repeat: stretch;
  -fx-font-size: 18px;
}

.breadcrumbs .item:hover {
  -fx-border-image-source: url("crumb-hover.png");
}

.breadcrumbs .alone {
  -fx-border-image-width: 0 0 0 0;
  -fx-border-image-repeat: stretch;
  -fx-border-image-source: url("crumb-selected.png");
  -fx-border-color: transparent #6e737d transparent rgba(255,255,255,0.3) , transparent rgba(255,255,255,0.3) transparent transparent;
  -fx-border-insets: 0 0 1 0, 1;
}

.breadcrumbs .first {
  -fx-border-image-insets: -2 -5 -2 0;
  -fx-border-image-width: 0 10 0 0;
}

.breadcrumbs .middle {
  -fx-border-image-insets: -2 -5 -2 -7;
}

.breadcrumbs .last {
  -fx-border-image-insets: 0 0 0 -7;
  -fx-border-image-width: 0 0 0 10;
  -fx-border-image-repeat: stretch;
  -fx-border-image-source: url("crumb-selected.png");
  -fx-border-color: transparent #6e737d transparent transparent , transparent rgba(255,255,255,0.2) transparent transparent;
  -fx-border-insets: 0 0 1 0, 1;
}

Row 1-4: Here are the design specified for the main layout, which is a VBox (vertical box). This vertical box has been given a padding and notice the -fx-spacing. This is the same as specify the internal spacing between the box components with the constructor. In the JavaFX 2 CSS reference guide all components special styles are defined.

That is so far. If you have a little knowledge about CSS and how it is used on the web today you will find your self quite home with how the styling works in JavaFX 2.

So let us see how we create the breadcrumbs are created. First of we have three types of scenarios.
  1. Only one element (alone).
  2. Two element (first, last).
  3. Three or more element (first, middle, last).
As you can see in the CSS these different scenarios are supported by have four types of elements: item, first, middle, and last. 

Row 10-20: Defines the basic item which all elements in the breadcrumb have. Here you will see one cool thing in JavaFX 2. You can define a image for the border of the element.

Row 16: Defines the image of the border.

Row 17: Defines how the border should appear. This is a bit tricky to get hold on, but when you specify all the four values the element is divided into 9 slices. A upper left corner, a top edge, a upper right corner, a right edge, a lower right corner, a bottom edge, a bottom left corner, a left edge, and a middle. Using the fill command preserves the middle section. This means that you can create a arrow shape form. reading our style: 1 10 1 10 fill. We tell that we like to have a border which have a top size by one pixel, a right side by a size of 10px and since we have fill the middle will be preserved. You can read this like "top right corner is -10px, middle 0px, bottom right corner is -10px". Try this out to get an understanding if you do not get it :).

Row 18: Specify the width of the border image.The values are top, right, bottom, and left. That is 1px top border, 10px right border, 1 bottom border, and 10px left border.

Row 19: Specify that we like to stretch the given image to fit the element.

Row 27: For the alone element we do not like to have any arrow. This is simply removed by telling that we do  not like to have any width of the border image.

Row 31: Since the border image is not shown we add some colors to the border.

Row 32: Here we basically specify the size of the borders.

Row 35-42: The first and middle elements are nothing fancy only a tweak to the border widths.

Row 44-51: As for the last element there are some tweaks to the width of the borders.

In this post we have created a breadcrumb styled toolbar which have all styles defined in a separate stylesheet. It can sometimes be a bit tricky to get all the insets and widths to work out, and if you have a problem with them my only recommendation is to try them out. See what happens. Also take a look in the well written reference guide. 

Also some points to think of:

  • It is possible to write style rules for components. This is done by using the component name. However this is not recommended since the components can change name and will brake all your style rules. Use classes instead.
  • Watch out for mixing element.setStyle() and element.getStyleSheets().add(). The setStyle() function set the style to the element directly, like setStyle("fx-padding: 3"). When getStyleSheets().add() will add a new style rule to the element.
  • Pixels are default in JavaFX 2. No need to write px after each size.

The source code can be found here: http://leppe.se/blog/2011-11-27/styles.zip.

The JavaFX 2 CSS reference guide can be found here: http://docs.oracle.com/javafx/2.0/api/javafx/scene/doc-files/cssref.html

Inga kommentarer:

Skicka en kommentar