Fork us on GitHub

Using the new GUI Builder

Getting started with the new gui builder
Post Image

Using the new GUI Builder

We had a couple of posts in the past about the new GUI builder but we didn’t have a "how to" guide yet. In this post we’ll try to go step by step over the process of using the GUI builder and understanding its inner workings. We’ll also try to clarify conclusively the role the new GUI builder plays in the toolchain and the migrations process from the old GUI builder.

How do I Know if I’m Using the new GUI Builder?

The old GUI builder is in the designer tool, it’s a Swing application that includes the theme design etc.
It generates a Statemachine class that contains all the main user GUI interaction code.

The new GUI builder is a standalone application that you launch from the right click menu by selecting a form as explained below. Here are screenshots of both to help you differentiate:

The old GUI builder
Figure 1. The old GUI builder
The new GUI builder
Figure 2. The same UI in the new GUI builder
Why two GUI Builders?

The original old GUI builder has it’s roots in our work at Sun Microsystems. We developed it as part of the designer tool and we store it’s data in the resource file. When creating an application for the old GUI builder you must define it as a "visual application" which will make it use the old GUI builder.

The roots of this GUI builder are pretty old. When we initially built it we still had to support feature phones with 2mb of RAM and the iPad wasn’t announced yet. Due to that we picked an architecture that made sense for those phones with a greater focus on navigation and resource usage. Newer mobile applications are rivaling desktop applications in complexity and in those situations the old GUI builder doesn’t make as much sense

Hello World

Creating a hello world app in the new GUI builder is actually pretty trivial, you need to start with a regular handcoded application. Not a GUI builder application as it refers to the old GUI builder!

Creating a new hello world is similar for all IDE’s. We cover this process in the getting started tutorials for all the IDE’s: NetBeans, IntelliJ & Eclipse.

The new GUI builder requires Java 8. This means the IDE itself needs to run on top of Java 8!

Following are the instructions for creating a form and launching the GUI builder. While they are similar there are minor IDE differences. Usage of the GUI builder is identical in all IDE’s as the GUI builder is a separate application.

NetBeans

In NetBeans you need to follow these 4 steps:

Right click the package select New -> Other
Figure 3. Right click the package select NewOther
In the Codename One section select the GUI builder form
Figure 4. In the Codename One section select the GUI builder form
Type in the name of the form and click finish
Figure 5. Type in the name of the form and click finish, you can change the type to be a Container or Dialog
Launch the GUI builder thru the right click menu on the newly created file
Figure 6. Launch the GUI builder thru the right click menu on the newly created file

IntelliJ/IDEA

In IntelliJ you need to follow these 3 steps:

Right click the package select New -> Codename One Form (or Dialog/Container)
Figure 7. Right click the package select NewCodename One Form (or Dialog/Container)
Type in a name for the new form
Figure 8. Type in a name for the new form
Launch the GUI builder thru the right click menu on the newly created file
Figure 9. Launch the GUI builder thru the right click menu on the newly created file

Eclipse

In Eclipse you need to follow these 4 steps:

Right click the package select New -> Other
Figure 10. Right click the package select NewOther
In the Codename One section select the GUI builder option
Figure 11. In the Codename One section select the GUI builder option
Type in the name of the form and click finish
Figure 12. Type in the name of the form and click finish, you can change the type to be a Container or Dialog
Launch the GUI builder thru the right click menu on the newly created file
Figure 13. Launch the GUI builder thru the right click menu on the newly created file

Basic Usage

Notice that the UI of the new GUIBuilder might change in the future but the basic concepts should remain the same.

We control the GUI builder via it’s main toolbar, notice that your changes will apply only when you click the Save button on the right:

The features of the main toolbar
Figure 14. The features of the main toolbar

The sidebar includes the functionality we will be working with most of the time:

The sidebar options
Figure 15. The sidebar options

We’ll start by selecting the Component Palette and dragging a button into the UI:

You can drag any component you want from the sidebar to the main UI
Figure 16. You can drag any component you want from the sidebar to the main UI

You can then re-arrange the order of the components but since they use the default FlowLayout you can’t position them anywhere you want. We’ll discuss arrangement and layout managers in the GUI builder below.

You should have a UI that looks like this when you select the button you placed, it shows the properties that you can modify and the events that you can bind:

Properties allow you to customize everything about a component
Figure 17. Properties allow you to customize everything about a component

You can edit any property by clicking it, this launches the appropriate UI. E.g. for image properties you are presented with an image dialog that allows you to pick an image from the resource file:

You can edit properties such as the icon property by clicking it
Figure 18. You can edit properties such as the icon property by clicking it, this opens the image selection dialog
You can add an image to the resource file using the designer tool as covered in this video

For things like setting the text on the component we can use a convenient "long click" on the component to edit the text in place as such:

Use the long click to edit the text
Figure 19. Use the long click to edit the text "in place"

Events

When a component supports broadcasting events you can bind such events by selecting it, then selecting the events tab and clicking the button matching the event type

The events tab is listed below supported event types can be bound above
Figure 20. The events tab is listed below supported event types can be bound above

Once an event is bound the IDE will open to the event code e.g.:

public void onButton_1ActionEvent(com.codename1.ui.events.ActionEvent ev) {
}
Some IDE’s only generate the project source code after you explicitly build the project so if your code needs to access variables etc. try building first

Within the code you can access all the GUI components you defined with the gui_ prefix e.g. Button_1 from the UI is represented as:

private com.codename1.ui.Button gui_Button_1 = new com.codename1.ui.Button();

Layouts

In this section we won’t try to discuss layouts in depth as this is a deep and complex subject. You can read more about the properties of the Codename One layouts in the developer guide.

In general layouts define the mathematical logic for component positions that we can then apply to the resolutions supported by the devices. If we didn’t have layouts the UI wouldn’t fit on the multitude of devices where it should work. You can nest layouts by placing containers within the UI and giving any container a different layout manager, this allows you to construct very elaborate layouts.

You can pick a layout manager using this UI:

Layouts can be picked via the GUI builder UI
Figure 21. Layouts can be picked via the GUI builder UI

Most layouts support settings that allow you to configure their behavior, e.g. FlowLayout supports settings such as these that allow you to align the components within it to your locations of choice:

FlowLayout settings
Figure 22. FlowLayout settings

BorderLayout & TableLayout support constraints that allow you to provide additional hints about the components within the layout:

Border layout constraints
Figure 23. Border layout constraints

Mixing these layouts in a hierarchy allows you to produce most UI’s.

E.g. one of the most powerful tricks in the new GUI builder is the multi selection mode:

Multi selection icon
Figure 24. Multi selection icon

When this mode is turned on the icon turns into a cancel icon to cancel that mode. When it’s turned on you can select multiple components and perform operations on all of them such as changing a property on multiple components or enclosing them in a container e.g.:

When we toggle on multi-select mode and select several components we can then enclose them in a Container
Figure 25. When we toggle on multi-select mode and select several components we can then enclose them in a Container

Underlying XML

Saving the project generates an XML file representing the UI into the res directory in the project, the GUI file is created in a matching hierarchy in the project under the res/guibuilder directory:

The java and GUI files in the hierarchy
Figure 26. The java and GUI files in the hierarchy
If you refactor (rename or move) the java file it’s connection with the GUI file will break. You need to move/rename both

You can edit the GUI file directly but changes won’t map into the GUI builder unless you reopen it. These files should be under version control as they are the main files that change. The GUI builder file for the button and label code looks like this:

<?xml version="1.0" encoding="UTF-8"?>

<component type="Form" layout="FlowLayout" flowLayoutFillRows="false" flowLayoutAlign="1" flowLayoutValign="0"  title="My new title" name="MyForm">
  <component type="Button" text="Button" name="Button_1" actionEvent="true">
  </component>
  <component type="Label" text="Hi World" name="Label_1">
  </component>
</component>

This format is relatively simple and is roughly the same format used by the old GUI builder which makes the migration to the new GUI builder possible. This file triggers the following Java source file:

package com.mycompany.myapp;

/**
 * GUI builder created Form
 *
 * @author shai
 */
public class MyForm extends com.codename1.ui.Form {

    public MyForm() {
        this(com.codename1.ui.util.Resources.getGlobalResources());
    }

    public MyForm(com.codename1.ui.util.Resources resourceObjectInstance) {
        initGuiBuilderComponents(resourceObjectInstance);
    }

//-- DON'T EDIT BELOW THIS LINE!!!
    private com.codename1.ui.Label gui_Label_1 = new com.codename1.ui.Label();
    private com.codename1.ui.Button gui_Button_1 = new com.codename1.ui.Button();


// <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void guiBuilderBindComponentListeners() {
        EventCallbackClass callback = new EventCallbackClass();
        gui_Button_1.addActionListener(callback);
    }

    class EventCallbackClass implements com.codename1.ui.events.ActionListener, com.codename1.ui.events.DataChangedListener {
        private com.codename1.ui.Component cmp;
        public EventCallbackClass(com.codename1.ui.Component cmp) {
            this.cmp = cmp;
        }

        public EventCallbackClass() {
        }

        public void actionPerformed(com.codename1.ui.events.ActionEvent ev) {
            com.codename1.ui.Component sourceComponent = ev.getComponent();
            if(sourceComponent.getParent().getLeadParent() != null) {
                sourceComponent = sourceComponent.getParent().getLeadParent();
            }

            if(sourceComponent == gui_Button_1) {
                onButton_1ActionEvent(ev);
            }
        }

        public void dataChanged(int type, int index) {
        }
    }
    private void initGuiBuilderComponents(com.codename1.ui.util.Resources resourceObjectInstance) {
        guiBuilderBindComponentListeners();
        setLayout(new com.codename1.ui.layouts.FlowLayout());
        setTitle("My new title");
        setName("MyForm");
        addComponent(gui_Label_1);
        addComponent(gui_Button_1);
        gui_Label_1.setText("Hi World");
        gui_Label_1.setName("Label_1");
        gui_Button_1.setText("Click Me");
        gui_Button_1.setName("Button_1");
    }// </editor-fold>

//-- DON'T EDIT ABOVE THIS LINE!!!
    public void onButton_1ActionEvent(com.codename1.ui.events.ActionEvent ev) {
    }

}
Don’t touch the code within the DON’T EDIT comments…​

The GUI builder uses the "magic comments" approach where code is generated into those areas to match the XML defined in the GUI builder. The IDE’s generate that code at different times. Some IDE’s will generate it when you run the app while others will generate it as you save the GUI in the builder.

You can write code freely within the class both by using the event mechanism, by writing code in the constructors or thru overriding functionality in the base class.

Should I Switch

Yes if you want to move forward.

If your app is in maintenence mode then no. We have no plans to remove support for the old GUI builder although we will de-emphasize it slowly.

While we still aren’t ready to crown the GUI builder as fully production grade we do think the XML based file format is very stable (since we inherited it from the old GUI builder) and should thus work rather well. So even if you run into issues in the tool itself you can probably workaround most of them thru the XML code which is already easier to work with than it was with the old GUI builder.

Currently, NetBeans and Eclipse have a migration wizard from the old GUI builder. It is flaky as it tries to "fake" the "statemachine navigation" and does it rather badly. So the assumption is that you would need to use that as a starting point and adapt the logic of the application.

If your app is very complex it might be a difficult task so we would suggest dedicating some time to evaluating this before jumping in head first.

Final Word

We’ve spent a lot of time building up the new GUI builder and it is still not as refined as the old one. However, we think that once you guys start reporting bugs & requesting enhancements it will quickly mature into an amazing tool.

Take the time to work with it and let us know what you think.

Share this Post:

Posted by Shai Almog

Shai is the co-founder of Codename One. He's been a professional programmer for over 25 years. During that time he has worked with dozens of companies including Sun Microsystems.
For more follow Shai on Twitter & github.