Friday, May 24, 2013

CSS == Confusing Style Sheets ?

Hi there,

Finally I found some time to play around with CSS Pseudo classes and so called StyleableProperties in JavaFX. Because there is already a good description about this topics available on the web (OpenJFX Wiki) this post is more about examples of those topics than about the details. So to keep it short...

CSS PSEUDO CLASS
You might have seen something like follows when reading CSS files

.style-class {
    ...
}

.style-class:pseudo {
    ...
}

In the case above pseudo is a so called CSS pseudo class. The nice thing about these pseudo classes is that one could trigger them by using a setter on a property in JavaFX. Means if one calls the method setPseudo(true) in JavaFX, the component that uses the .style-class will now use the .style-class:pseudo for styling. This is really useful because you as a developer don't have to take care about switching the style on the component manually but JavaFX will take care about this.
As a simple example lets create a custom control by extending Region and create a CSS pseudo class for that control. This the code for the control.

public class CSSPseudo extends Region {
  private static final PseudoClass DEMO_PSEUDO_CLASS
    PseudoClass.getPseudoClass("demo");
  private BooleanProperty demo;

  public CSSPseudo() {      
    getStylesheets().add(getClass()
      .getResource("csspseudo.css").toExternalForm());
    getStyleClass().add("region");
    setPrefSize(50, 50);
  }

  public final boolean isDemo() {
    return null == demo ? false : demo.get();
  }
  public final void setDemo(final boolean ON) {
    demoProperty().set(ON);
  }
  public final BooleanProperty demoProperty() {
    if (null == demo) {
      demo = new BooleanPropertyBase(false) {
        @Override protected void invalidated() { 
          pseudoClassStateChanged(DEMO_PSEUDO_CLASS, get()); 
        }
        @Override public Object getBean() { return this; }
        @Override public String getName() { return "demo"; }
      };
    }
    return demo;
  }

}

As you can see in the code the BooleanProperty looks in principle like a standard JavaFX BooleanProperty except the demoProperty() method. In this method the magic happens that if the property is invalid the style of the control will change to :demo in the CSS file.
The CSS file than looks like follows

.region {
    -fx-background-color: red;
}
.region:demo {
    -fx-background-color: green;

}

To test the behavior lets create a little Application and toggle the demo property between true and false which should lead to change of the Regions color between red and green. Here is the Application code

public class CSSDemo extends Application {
  private boolean        toggle;
  private long           lastTimerCall;
  private AnimationTimer timer;
  private CSSPseudo      control;

  @Override public void init() {
    toggle = true;
    lastTimerCall = System.nanoTime();
    timer = new AnimationTimer() {
      @Override public void handle(long now) {
        if (now > lastTimerCall + 1_000_000_000l) {
          toggle ^= true;
          control.setDemo(toggle);
          lastTimerCall = now;
        }
      }
    };
    control = new CSSPseudo();
  }

  @Override public void start(Stage stage) {
    StackPane pane = new StackPane();
    pane.setPadding(new Insets(10, 10, 10, 10));
    pane.getChildren().add(control);

    Scene scene = new Scene(pane);

    stage.setScene(scene);
    stage.show();

    timer.start();
  }

  public static void main(String[] args) {
    launch(args);
  }
}

If you start this application you should see a simple window with a rectangle that changes it's color between red and green every second.




Well and that's all it takes to switch a CSS style by using a JavaFX property...neat isn't it?

STYLEABLE PROPERTY
So now we now how to change a CSS style by using JavaFX properties but would it not be nice if one could set a CSS style (e.g. by loading a specific CSS file) and dependent on the CSS style a property in the code will set to the value given by the CSS style ?
And that's exactly what the StyleableProperties are for.
Means we would like to define the value of a JavaFX property by using a CSS variable.
Therefor it takes a bit more code...

First of all we now create a custom control by extending Control which means we also have to create a Skin for our control. So first of all we need the control class

public class CssStyleable extends Control {
  public static final Color     DEFAULT_CSS_COLOR = Color.RED;
  private ObjectProperty<Paint> cssColor;

  // ******************** Constructors **************************************
  public CssStyleable() {
    getStyleClass().add("css-styleable");
  }

  // ******************** Methods *******************************************
  public final Paint getCssColor() {
    return null == cssColor ? DEFAULT_CSS_COLOR : cssColor.get();
  }
  public final void setCssColor(Paint cssColor) {
    cssColorProperty().set(cssColor);
  }
  public final ObjectProperty<Paint> cssColorProperty() {
    if (null == cssColor) {
      cssColor = new StyleableObjectProperty<Paint>(DEFAULT_CSS_COLOR) {
        @Override public CssMetaData getCssMetaData() { 
          return StyleableProperties.CSS_COLOR
        }
        @Override public Object getBean() { return CssStyleable.this; }
        @Override public String getName() { return "cssColor"; }
      };
    }
    return cssColor;
  }

  // ******************** Style related *************************************
  @Override protected String getUserAgentStylesheet() {
    return getClass().getResource("cssstyleable.css").toExternalForm();
  }

  private static class StyleableProperties {
    private static final CssMetaData<CssStyleable, Paint> CSS_COLOR =
      new CssMetaData<CssStyleable, Paint>("-css-color"
        PaintConverter.getInstance(), DEFAULT_CSS_COLOR) {

      @Override public boolean isSettable(CssStyleable node) {
        return null == node.cssColor || !node.cssColor.isBound();
      }

      @Override public StyleableProperty<Paint> getStyleableProperty(
        CssStyleable node) {
        return (StyleableProperty) node.cssColorProperty();
      }

      @Override public Color getInitialValue(CssStyleable node) {
        return node.DEFAULT_CSS_COLOR;
      }
    };

  private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
  static {
    final List<CssMetaData<? extends Styleable, ?>> styleables = new ArrayList<>
      (Control.getClassCssMetaData());
       Collections.addAll(styleables, CSS_COLOR);
       STYLEABLES = Collections.unmodifiableList(styleables);
    }
  }

  public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
    return StyleableProperties.STYLEABLES;
  }

  @Override public List<CssMetaData<? extends Styleable, ?>> 
    getControlCssMetaData() {
      return getClassCssMetaData();
  }

}

The next thing we need is the Skin class for our control which looks like this

public class CssStyleableSkin extends SkinBase<CssStyleable> implements Skin<CssStyleable> {
  private static final double PREFERRED_SIZE = 64;
  private Pane                pane;
  private Region              region;

  // ******************** Constructors **************************************
  public CssStyleableSkin(final CssStyleable CONTROL) {
    super(CONTROL);
    pane = new Pane();

    getSkinnable().setPrefSize(PREFERRED_SIZE, PREFERRED_SIZE);
    initGraphics();
    registerListeners();
  }

  private void initGraphics() {
    region = new Region();
    region.getStyleClass().setAll("region");
    region.setPrefSize(PREFERRED_SIZE, PREFERRED_SIZE);
    pane.getChildren().setAll(region);
    getChildren().setAll(pane);
  }

  private void registerListeners() {
    getSkinnable().cssColorProperty().addListener(observable -> { 
      handleControlPropertyChanged("CSS_COLOR"); } );
  }

  // ******************** Methods *******************************************
  protected void handleControlPropertyChanged(final String PROPERTY) {
    if ("CSS_COLOR".equals(PROPERTY)) {
      System.out.println("CSS color property changed to "
                         getSkinnable().getCssColor());
    }
  }

}

As you could see in the code we attach an InvalidationListener to the cssColorProperty() of the CssStyleable control. That means as soon as this property gets invalid (by being changed to another value) the InvalidationListener will print the new color on the console.

Now we need the CSS file (cssstyleable.css) that will be used for our control. In this case it's really small and looks like follows

.css-styleable {
    -fx-skin  : "CssStyleableSkin";
    -css-color: red;
}

.css-styleable .region {
    -fx-background-color: -css-color;

}

As you can see it only defines the Skin file that should be loaded for the control and a the CSS variable named -css-color which is set to red;

With all the files in place we now just need a little application that demonstrates the StyleableProperty. Therefor we will create an app that simply toggles the CSS style of the Region between red and green by calling region.setStyle()

KEEP IN MIND that this CSS inlining should be avoided in an application due to performance but for this demo it's ok to use it.

So the code for the demo Application looks like this

public class CSSDemo extends Application {
  private boolean        toggle;
  private long           lastTimerCall;
  private AnimationTimer timer;
  private CssStyleable   control;


  @Override public void init() {
    toggle = true;
    lastTimerCall = System.nanoTime();
    timer = new AnimationTimer() {
      @Override public void handle(long now) {
        if (now > lastTimerCall + 1_000_000_000l) {
          toggle ^= true;
          control.setStyle(toggle ? "-css-color: red;" : "-css-color: green;");
          lastTimerCall = now;
        }
      }
    };
    control = new CssStyleable();
  }

  @Override public void start(Stage stage) {
    StackPane pane = new StackPane();
    pane.setPadding(new Insets(10, 10, 10, 10));
    pane.getChildren().add(control);

    Scene scene = new Scene(pane);

    stage.setScene(scene);
    stage.show();

    timer.start();
  }

  public static void main(String[] args) {
    launch(args);
  }

}

If you now start that application you should see the same as in the example before, a simple rectangle that changes it's color every second between red and green. In addition you should see something like follows on the the console

CSS color property changed to 0x008000ff
CSS color property changed to 0xff0000ff

CSS color property changed to 0x008000ff

And this indicates that the InvalidationListener in the Skin was triggered because the cssColorProperty() in the CssStyleable class was changed. So you could change a CSS style and the appropriate StyleableProperty in your code will be triggered so that you can react on that change. 

Like I mentioned at the beginning, this post won't explain all the details because there is a good explanation available but it will give you an easy example for the CSS pseudo class and StyleableProperty that you could try by yourself and use it for your controls etc.

And to be honest, I just needed to write it down somewhere so that I could take a look at it when I need it... :)

Keep coding...

Monday, May 13, 2013

Monday Fun Component...???

Ups...what's that...a monday fun component...???
Why not...today I was traveling from Münster to Basel by train because I have to give a JavaFX training tomorrow and Wednesday. During the train ride there was some time and didn't had internet on the train so that I had to do something locally on my machine. 
Some time ago I found the following button somewhere on the web and I thought it might be useful as a control for my BeagleBoard.




Long story short, I simply created the control and instead of styling a ToggleButton or CheckBox (which would be the right approach here) I created a new control. I did this because I can...no, it was because I was much faster by drawing that stuff and convert it to a control as trying to figure out how to tweak the caspian.css in the way that a ToggleButton or CheckBox would look like the button above.
I created the control as a JavaFX 2.x control instead of a JavaFX 8 control because I would like to use it as a touchable button on my BeagleBoard which is running on JDK7 with JavaFX 2.x at the moment.
Here is the result that I was able to create...





This is really more a quick hack than a ready to go control but...I don't care...it works on my BeagleBoard and that was the target...so I'm fine with the result and if you would like to use it...here is the code...

Source as zip

The control has the following properties,

  • touchable
  • selected
  • text
  • ledColor

The touchable property will simply add touchEvent listeners instead of mouseEvent listeners to the control. So if you would like to use it on a touchable device you should switch touchable on.
The control will fire SelectEvents and will give you some convenience methods like onSelect and onDeselect where you could attach your EventHandlers to.

Like I said...a quick hack and if you have the time...feel free to attach the css to a CheckBox etc. and tweak an existing control which would be a better approach.

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


Monday, May 6, 2013

Java(FX) BBQ

Hi there,
Today's post is not about JavaFX but more about community. I decided to organize a little Java(FX) BBQ where I'll try to give people the chance to meet and have some fun. The event will happen at my house in Münster (Germany) and will be open for everybody who's interested in meeting some people that are interested in Java and especially in JavaFX :)
It will happen on a friday afternoon and the date is not fixed yet, so if you would like to attend, feel free to add yourself to the following Doodle:

JavaFX BBQ Doodle

I saw that some people from the JFXtras project signed up already so it might also be a good chance to meet and greet these guys behind the JFXtras project. If you would like to stay here over night you will find a guesthouse here

Gästehaus Asche

If not too many people sign up I will sponsor the beer which means you just have to bring your food with you and if you have to drive something to drink without alcohol.

If you have something to show or would like to discuss something related to JavaFX...feel free to bring your computer with you and I will take care about a beamer or something else if you would like to present something.

As a side note...my bbq grill is not that big so don't expect too much of it... :)

I will post more information about the location etc. as soon as we will have a date (at the moment everything looks like it will be the 21st of June).

That's it so far...would love to see you at the BBQ...so keep coding...

Friday, April 19, 2013

Validate it...

Hi there,
It's already some time ago when I released my last blog post but I was busy with presentation preparation, trainings, preparing stuff for my upcoming JavaFX related podcast etc.
I was playing around with validation using css styles and so far that is an easy way to do some validation. But I in the Java Swing days I used the GlasPane to draw validation icons on top of invalid or valid controls. This approach was not always useful but I liked it because I could use one set of validation icons and validate all kinds of controls. So I was asking myself how I could implement this behavior in JavaFX. 
I decided to go with the Canvas node because it has a translucent background by default and enables me to draw whatever I like by only using one node on the scene graph. The only disadvantage was that the Canvas node is like an image means it won't resize automatically but you have to take care about size by yourself.
Well the solution to this problem could be extending Canvas and implement the autosizing behavior or encapsulate the Canvas node into another node which could be resized automatically and react on the new size by using an InvalidationListener to the resizable control. I decided to encapsulate the Canvas node in a Region because it's lightweight and supports resizing. 
The implementation is more a proof of concept than a ready to go solution but it should be good enough to play around with it. It only takes two classes, the
  • ValidationPane
  • Validator
The ValidationPane is simply a Region which encapsulates a Canvas node. To use the ValidationPane one simply has to add the nodes that should get the validation overlays by using one of the following methods
  • add(Node node)
  • add(Pos position, Node node)
  • addAll(Node... nodes)
  • addAll(Pos position, Node... nodes)
Here is a short example that shows you how to add a TextField to the ValidationPane

TextField textField = new TextField();

ValidationPane validationPane = new ValidationPane();
validationPane.add(Pos.TOP_LEFT, textField);

As you could see it is possible to configure the position of the validation icon (the default position is Pos.TOP_LEFT).

There are five different states that one could use for validation
  • Validator.State.VALID
  • Validator.State.INVALID
  • Validator.State.INFO
  • Validator.State.OPTIONAL
  • Validator.State.CLEAR
To set the validation state of a node you simply have to call the setState() method on the validation pane, for the example above this would look like follows

validationPane.setState(textField, Validator.State.INVALID);

If you set the validation state to Validator.State.VALID the validation icon will fade out after 1500 ms to keep the interface clean. 
If the node is invalid the validation icon will stay visible as long as it is in the invalid state.
On the following screenshot you could see three different states (Validator.State.CLEAR has no indicator).


You could see all three available indicators on the image above (invalid, valid and info). 
The idea was to use the validation not only for textfields (which is most of the times the standard use case) but for example also for complete layout containers like a HBox, GridPane etc.
Therefor it works on the JavaFX Node instead of Control. I did not make very indeep tests with it and cannot guarantee that it works in any case but like I said it's more a proof of concept than a ready to go solution.
To use it you simply have to wrap your existing root pane in an additional StackPane and put the ValidationPane on top by adding it at the last node to the StackPane. Because the ValidationPane is transparent to mouse events it won't catch events and should be "invisible" to your application. The following image should try to give you an idea...



It was fun to create and very similar to the Swing GlasPane approach and proofed that even if JavaFX is based on a SceneGraph using nodes for visualization one could easy adopt a bitmap based approach by using the Canvas node.

If you are interested in the source code, please find it here.

ATTENTION: I'm using lambdas in the code which might not work in every IDE !!!


UPDATE:
During the last JavaFX training course at Canoo in Basel one of the attendees pointed me to a useful feature for the validation pane. If you think about nodes that are invalid and are not visible. These nodes should not show their validation icon right...so I've added this behavior to the ValidationPane. So if you would like to take a look, feel free to get the code from BitBucket. I've also updated the demo to show the new behavior.


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

Friday, March 1, 2013

Just for the fun(k) of it...

Hi there,
again time for some fun. This time it's (again) about a clock that simply has an awesome design. I blogged about it nearly exact two years ago, it's the QlockTwo from Biegert & Funk...maybe it should better be Biegert & Fun :)
This clock is simple and stylish and two years ago I've created a Swing version from it which was fun. After I have finished the JavaFX training course last week in Basel at Canoo Headquarters a colleague of mine came to me and showed me his version of a JavaFX QlockTwo and I showed him the Swing version. Well what should I say, on my way back home I could not withstand and started porting the Swing version to JavaFX (thanx Sven for pointing me on that).
Two years ago I've implemented german, english, french and dutch as supported languages but now that we have friends in Spain too (yes José this is for you) I decided to add also a spanish version. The original QlockTwo also supports something like a seconds only mode where the current seconds will be displayed and because this was not in my original version I've added it to the JavaFX version too. 
Long story short, here is a screenshot that shows nearly all styles available (only dark-chocolate is missing on the screenshot), here you go...



The main problem was to get the display of the time right for all the languages (and there are still some problems) but overall it was great fun to create it. So if you figure out problems, just let me know or file an issue on github.

And because the original QlockTwo costs € 345 for the small version and € 885 for the standard version which means I guess most of you could not afford to buy one...I decided to add the control to the Enzo library which you could find on github. So everyone who's interested could have it's own version on his desktop monitor.

Well having the clock on the desktop monitor is some kind of nice but having it on a Raspberry Pi would be even better, so I've also added it to the Enzo7 library which you could find here (only as binary because things will change in the future). Means that if you have a lcd panel attached to your Raspberry Pi (like I have :) ) you could use the Raspberry Pi as a poor mans QlockTwo.

That's it for today, I hope you enjoy JavaFX as much as I do...keep coding...


Monday, February 4, 2013

One class gauge...

Aloha...
Last week I prepared some things for my JFokus session and found a nice gauge on the web that looks like this...


It shows the temperature...wait a moment...the JavaFX app on my BeagleBoard also shows the temperature...why not use this gauge to visualize it. The gauge seems to be simple enough so that there should be no performance problems with the restricted resources of the BeagleBoard.
Long story short...here is the result...


I used different colors for the sections because this colors look better on the lcd screen that is connected to my BeagleBoard. In addition I've also added an indicator that shows up if a given threshold is exceeded.
When you create a custom JavaFX control for the JDK7 implementation that runs on the BeagleBoard you can't use the 

  • Control
  • Skin
  • Behavior
  • css

approach because the control won't show up. So the solution is to create the complete control in one file which is totally fine for such a simple control.
And that's exactly what I did and now I could use this control on my BeagleBoard JavaFX app to show the measured temperature.
One could define the sections with their colors, a min- and max-value and a threshold for the gauge. The tickmark implementation is really simple and won't really work with large ranges, so for me it works out and if you would like to use that thing by yourself...feel free to fork it on github.

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




Sunday, February 3, 2013

Native idea...

Hi there,

This will be a short blogpost about how to get native packaging up and running in IntelliJ Idea. Usually I used NetBeans to create native packages in JavaFX because it's so easy with NetBeans but it would be nice to be able to build the native package also in IntelliJ. Fortunately Thierry Wasyl blogged about how to create startable JavaFX jar files in IntelliJ Idea a few weeks ago so I just had to modify his work a bit to get also native packages out of a build.
In principle you just have to do the following:

1. create a Java project in IntelliJ Idea or use an existing one

2. go the 'Build' menu and select 'generate Ant Build...'



3. open the generated ant xml file and delete all content

4. copy the following content into the ant xml file


<?xml version="1.0" encoding="UTF-8"?>
<project name="PROJECT_NAME" default="default" basedir="." xmlns:fx="javafx:com.sun.javafx.tools.ant">

<!-- 
Project structure:
PROJECT_NAME/src              Sources folder
PROJECT_NAME/lib              Folder of external jar files
PROJECT_NAME/build            Folder for the output
PROJECT_NAME/build/classes    Folder that will contain the class files
PROJECT_NAME/build/dist       Folder that will contain the jar file
PROJECT_NAME/build/bundles    Folder that will contain the native package
-->

    <property name="application.title" value="APPLICATION_TITLE"/>
    <property name="vendor.name" value="VENDOR_NAME"/>
    <property name="java.home" value="${env.JAVA_HOME}"/>
    <property name="source.dir" value="src"/>
    <property name="lib.dir" value="lib"/>
    <property name="out.dir" value="build"/>
    <property name="out.dir.classes" value="${out.dir}/classes"/>
    <property name="out.dir.dist" value="${out.dir}/dist"/>
    <property name="out.dir.dist.lib" value="${out.dir.dist}/lib"/>
    <property name="app.jar.name" value="JAR_FILE_NAME.jar"/>
    <property name="main.class" value="PATH.TO.MAIN.CLASS"/>
    <property name="manifest.classpath" value="lib"/>
    <property name="manifest.externaljars" value="${manifest.classpath}/EXT_LIB1.jar ${manifest.classpath}/EXT_LIB2.jar"/>

    <path id="external.jars">
        <fileset dir="${lib.dir}" includes="**/*.jar"/>
    </path>

    <path id="classpath">
        <fileset dir="${java.home}/lib" includes="**/*.jar"/>
        <path refid="external.jars"/>
    </path>

    <target name="default">
        <taskdef resource="com/sun/javafx/tools/ant/antlib.xml"
                 uri="javafx:com.sun.javafx.tools.ant"
                 classpath=".:${java.home}/lib/ant-javafx.jar"/>
    </target>

    <target name="clean">
        <delete dir="${out.dir}"/>
    </target>

    <target name="init" depends="clean">
        <mkdir dir="${out.dir}"/>
        <mkdir dir="${out.dir.classes}"/>
        <mkdir dir="${out.dir.dist}"/>
    </target>

    <target name="compile" depends="default, init">
        <javac srcdir="${source.dir}" destdir="${out.dir}/classes" classpathref="classpath"
               source="1.7"
               target="1.7" />
        <copy todir="${out.dir}/classes">
            <!-- Define all filetypes that you need in your project -->
            <fileset dir="${source.dir}">
                <include name="**/*.png"/>
                <include name="**/*.fxml"/>
                <include name="**/*.css"/>
                <include name="**/*.wav"/>
                <include name="**/*.ttf"/>
                <include name="**/*.otf"/>
                <include name="**/*.html"/>
            </fileset>
        </copy>
        <copy todir="${out.dir.dist.lib}">
            <fileset dir="${lib.dir}">
                <include name="**/*.jar"/>
            </fileset>
        </copy>
    </target>

    <target name="build" depends="compile">
        <fx:application id="APPLICATION_TITLE" mainClass="${main.class}"/>

        <!-- Create the jar file -->
        <fx:jar destfile="${out.dir.dist}/${app.jar.name}">
            <fx:application refid="${application.title}"/>

            <manifest>
                <attribute name="Implementation-Vendor" value="${vendor.name}"/>
                <attribute name="Implementation-Title" value="${application.title}"/>
                <attribute name="Implementation-Version" value="1.0"/>
                <attribute name="Class-Path" value="${out.dir.dist.lib}"/>
                <attribute name="Main-Class" value="com/javafx/main/Main"/>
                <attribute name="JavaFX-Application-Class" value="${main.class}"/>
                <attribute name="JavaFX-Class-Path" value="${manifest.externaljars}"/>
            </manifest>

            <fileset dir="${out.dir.classes}"/>
        </fx:jar>

        <!-- Create the native package -->
        <fx:deploy verbose="true" width="200" height="400" nativeBundles="all" outdir="${out.dir.dist}" outfile="${application.title}">
            <fx:application name="${application.title}" mainClass="${main.class}"/>
            <fx:resources>
                <fx:fileset dir="${out.dir.dist}" includes="*.jar"/>
                <fx:fileset dir="${out.dir.dist}" includes="lib/*.jar"/>
            </fx:resources>
            <fx:info title="${application.title}" vendor="${vendor.name}"/>
        </fx:deploy>
    </target>
</project>



5. modify all the yellow marked text in the build xml file which should be self explaining

6. open the Ant Build area and add the build xml file by pressing the plus button



7. select the build entry and press play and after some seconds you should have a native package of your JavaFX application.

Please keep in mind that I'm running 7u13 on OS X which means the path to the jdk might be different on your machine. This build script is also able to add external jar files but therefor you have to put the external jar files in a "lib" folder that is at the same level as the source folder.



After the build is finished you should find a build folder that contains a classes folder which contains all the generated class files. In addition you will find a dist folder that contains the jar file and the lib folder with the external libs (jars)


In the dist folder you will also find a bundles folder that contains the native package and the setup program.



In my case it's the app folder and the dmg file.

You could also download the buildfx.xml file directly here.

I hope this was helpful for some of you...so keep coding...