What Is A Theme, What Is A Style & What Is a Component?

Every visual element within Codename One is a Component, the button on the screen is a Component and so is the Form in which it’s placed. This is all represented within the Component, which is probably the most central class in Codename One.

Every component has 4 standard style objects associated with it: Selected, Unselected, Disabled & Pressed.

If you wish to set a value to all component states you can use getAllStyles() which implicitly sets all the different styles. Notice that you must use it for write operations (set) and never use it for read operations (get).

Only one style is applicable at any given time and it can be queried via the getStyle() method. A style contains the colors, fonts, border and spacing information relating to how the component is presented to the user.

You should not use getStyle() in normal execution but instead use getUnselectedStyle(), getSelectedStyle(), getPressedStyle() & getDisabledStyle(). The reasoning is simple, getStyle() might return any one of those 4 depending on component state and you might not get the result you want. You should only use`getStyle()` when painting the component (e.g. in the paint callback method) to query information and not to set information.

A theme allows the designer to define the styles externally via a set of UIID’s (User Interface ID’s), the themes are created via the Codename One Designer tool and allow developers to separate the look of the component from the application logic.

Native Theme

By default Codename One applications are created with a theme that derives from the builtin OS native theme. You can add additional themes into the resource file by pressing the Add A New Theme button. You can also create multiple themes and ship them with your app or download them dynamically.

You can create a theme from scratch or customize one of the Codename one themes to any look you desire.

To preview the look of your theme in the various platforms use the Native Theme menu option in the designer.
The native theme menu option
Figure 1. The native theme menu option

You can easily create deep customizations that span across all themes by adding a UIID or changing an existing UIID. E.g. going back to our original hello world application the "GetStarted" UIID is defined within the designer as:

  • A green background

  • White forground

  • A thin medium sized font

  • Center aligned text

  • A small amount of spacing between the text and the edges

To achieve the colors we define them in the color tab.

We define the transparency to 255 which means the background will be a solid green color. This is important since the native OS’s might vary with the default value for background transparency so this should be defined explicitly.
The Color tab for the get started button theme settings
Figure 2. The Color tab for the get started button theme settings

The alignment of the text is pretty simple, notice that the alignment style attribute applies to text and doesn’t apply to other elements. To align other elements we use layout manager logic.

The alignment tab for the get started button theme settings
Figure 3. The alignment tab for the get started button theme settings

Padding can be expressed in pixels, millimeters (approximate) or percentages of the screen size.

We recommend using millimeters for all measurements to keep the code portable for various device DPI’s.
The padding tab for the get started button theme settings
Figure 4. The padding tab for the get started button theme settings

The font uses native OS light font but has a fallback for older OS’s that don’t support truetype fonts. The "True Type" font will be applicable for most modern OS’s. In the case of the "native:" fonts Android devices will use Roboto whereas iOS devices will use Helvetica Neue. You can supply your own TTF and work with that.

Since Codename One cannot legally ship Helvetica Neue fonts the simulator will fallback to Roboto on PC’s.
At the time of this writing the desktop/simulator version of the Roboto font doesn’t support many common character sets (languages). This will have no effect on an Android device where thenative font works properly.
The font tab for the get started button theme settings
Figure 5. The font tab for the get started button theme settings

Component/Container Hierarchy

Codename One Simplified Component Hierarchy
Figure 6. Codename One Simplified Component Hierarchy

The component class is the basis of all UI widgets in Codename One, to arrange multiple components together we use the Container class which itself “IS A” Component subclass. The Container is a Component that contains Components effectively allowing us to nest Containers infinitely to build any type of visual hierarchy we want by nesting Containers.

Component UML
Figure 7. Component UML

Layout Managers

Layout managers are installed on the Container class and effectively position the Components within the given container. The Layout class is abstract and allows users to create their own layout managers, however Codename One ships with multiple layout managers allowing for the creation of many layout types.

The layout managers are designed to allow developers to build user interfaces that seamlessly adapt to all resolutions and thus don’t state the component size/position but rather the intended layout behavior.

To install a layout manager one does something like this:

Container c = new Container(new BoxLayout(BoxLayout.X_AXIS));
c.addComponent(new Button("1"));
c.addComponent(new Button("2"));
c.addComponent(new Button("3"));

This would produce 3 buttons, one next to the other horizontally.

This can also be expressed using a shorter syntax since the add method returns a container:

Container c = new Container(new BoxLayout(BoxLayout.X_AXIS)).
    add(new Button("1")).
    add(new Button("2")).
    add(new Button("3"));
The add method can also accept an Image or a String. This will effectively wrap such data in a label so add("abc") would be equivalent to add(new Label("abc")).

There is an even shorter version since most layout managers have helper methods to facilitate smaller code sizes e.g. BoxLayout has encloseX(Component…​) that can be used as such:

Container c = BoxLayout.encloseX(new Button("1"),
                    new Button("2"), new Button("3"));

Constraint Based Layout Managers

There are two major types of layout managers:
Constraint based & regular. The regular layout managers like the box layout are just installed on the container and “do their job”. The constraint based layout managers associate a value with a Component sometimes explicitly and sometimes implicitly. Codename One ships with 5 such layouts BorderLayout, TableLayout, GridBagLayout, GroupLayout & MigLayout.

A constraint layout CAN accept a value when adding the component to indicate its position. Notice that some layout manager require such a value (e.g. BorderLayout will throw an exception if a constraint is missing) whereas other constraint based layout managers will fallback to a sensible default (e.g. TableLayout).

You can use a constraint based layout like BorderLayout using syntax like this:

Container c = new Container(new BorderLayout());
c.addComponent(BorderLayout.CENTER, new Button("1"));
c.addComponent(BorderLayout.NORTH, new Button("2"));
c.addComponent(BorderLayout.SOUTH, new Button("3"));

This will stretch button 1 across the center of the container and buttons 2-3 will be stretched horizontally at the top and bottom of the container.

The order to adding doesn’t mean much for most constraint based layouts involved.

Like the above sample code this too can be written using terse syntax e.g.:

Container c = new Container(new BorderLayout()).
        add(BorderLayout.CENTER, new Button("1")).
        add(BorderLayout.NORTH, new Button("2")).
        add(BorderLayout.SOUTH, new Button("3"));

This can also be written with a helper method from the layout e.g.

Container c = BorderLayout.center(new Button("1")).
        add(BorderLayout.NORTH, new Button("2")).
        add(BorderLayout.SOUTH, new Button("3"));

Understanding Preferred Size

The Component class contains many useful methods, one of the most important ones is calcPreferredSize() which is invoked to recalculate the size a component “wants” when something changes

By default Codename One invokes the getPreferredSize() method and not calcPreferredSize() directly.
getPreferredSize() invokes calcPreferredSize() & caches the value.

The preferred size is decided by the component based on many constraints such as the font size, border sizes, padding etc.

When a layout manager positions & sizes the component, it MIGHT take the preferred size into account. Notice that it MIGHT ignore it entirely!

E.g. FlowLayout always gives components their exact preferred size, yet BorderLayout resizes the center component by default (and the other components on one of their axis).

You can define a group of components to have the same preferred width or height by using the setSameWidth & setSameHeight methods:

Component.setSameWidth(cmp1, cmp2, cmp3, cmp4);
Component.setSameHeight(cmp5, cmp6, cmp7);
Setting The Preferred Size

Codename One has a setPreferredSize method that allows developers to explicitly request the size of the component. However, this caused quite a lot of problems since the preferred size should change with device orientation or similar operations. The API also triggered frequent inadvertant hardcoding of UI values. As a result the method was deprecated.

We recommend developers use setSameWidth, setSameHeight when sizing alignment is needed. setHidden when hiding is needed. As a last resort we recommend overriding calcPreferredSize.

Flow Layout

Flow Layout
Figure 8. Flow Layout

Flow layout can be used to just let the components “flow” horizontally and break a line when reaching the edge of the container. It is the default layout manager for containers, but because it is so flexible it is often problematic as it can cause the preferred size of the Container to provide false/misleading information, triggering endless layout reflows.

Form hi = new Form("Flow Layout", new FlowLayout());
hi.add(new Label("First")).
    add(new Label("Second")).
    add(new Label("Third")).
    add(new Label("Fourth")).
    add(new Label("Fifth"));
hi.show();

Flow layout also supports terse syntax shorthand such as:

Container flowLayout = FlowLayout.encloseIn(
        new Label("First"),
        new Label("Second"),
        new Label("Third"),
        new Label("Fourth"),
        new Label("Fifth")));

Flow layout can be aligned to the left (the default), to the center, or to the right. It can also be vertically aligned to the top (the default), middle (center), or bottom.

Flow layout aligned to the center
Figure 9. Flow layout aligned to the center
Flow layout aligned to the right
Figure 10. Flow layout aligned to the right
Flow layout aligned to the center horizontally & the middle vertically
Figure 11. Flow layout aligned to the center horizontally & the middle vertically

Components within the flow layout get their natural preferred size by default and are not stretched in any axis.

The natural sizing behavior is often used to prevent other layout managers from stretching components. E.g. if we have a border layout element in the south and we want it to keep its natural size instead of adding the element to the south directly we can wrap it using parent.add(BorderLayout.SOUTH, FlowLayout.encloseCenter(dontGrowThisComponent)).

Box Layout

box-layout-x-no-grow

BoxLayout places elements in a row (X_AXIS) or column (Y_AXIS) according to box orientation. Box is a very simple and predictable layout that serves as the "workhorse" of component lists in Codename One.

You can create a box layout Y using something like this:

Form hi = new Form("Box Y Layout", new BoxLayout(BoxLayout.Y_AXIS));
hi.add(new Label("First")).
    add(new Label("Second")).
    add(new Label("Third")).
    add(new Label("Fourth")).
    add(new Label("Fifth"));

Which results in this

BoxLayout Y
Figure 12. BoxLayout Y

Box layout also supports a shorter terse notation which we use here to demonstrate the X axis box.

Container box = BoxLayout.encloseX(new Label("First"),
        new Label("Second"),
        new Label("Third"),
        new Label("Fourth"),
        new Label("Fifth")));
BoxLayout X
Figure 13. BoxLayout X

The box layout keeps the preferred size of its destination orientation and scales elements on the other axis. Specifically X_AXIS will keep the preferred width of the component while growing all the components vertically to match in size. Its Y_AXIS counterpart keeps the preferred height while growing the components horizontally.

This behavior is very useful since it allows elements to align as they would all have the same size.

In some cases the growing behavior in the X axis is undesired, for these cases we can use the X_AXIS_NO_GROW variant.

BoxLayout X_AXIS_NO_GROW
Figure 14. BoxLayout X_AXIS_NO_GROW
Comparing FlowLayout & BoxLayout - There are quite a few differences between FlowLayout and BoxLayout. When it doesn’t matter to you we recommend BoxLayout as it acts more consistently in all situations & is far simpler. Another advantage of BoxLayout is the fact that it grows and thus aligns nicely.

Border Layout

Border Layout
Figure 15. Border Layout

Border layout is quite unique, it’s a constraint-based layout that can place up to 5 components in one of the 5 positions: NORTH, SOUTH, EAST, WEST or CENTER.

Form hi = new Form("Border Layout", new BorderLayout());
hi.add(BorderLayout.CENTER, new Label("Center")).
    add(BorderLayout.SOUTH, new Label("South")).
    add(BorderLayout.NORTH, new Label("North")).
    add(BorderLayout.EAST, new Label("East")).
    add(BorderLayout.WEST, new Label("West"));
hi.show();

The layout always stretches the NORTH/SOUTH components on the X-axis to completely fill the container and the EAST/WEST components on the Y-axis. The center component is stretched to fill the remaining area by default. However, the setCenterBehavior allows us to manipulate the behavior of the center component so it is placed in the center without stretching.

E.g.:

Form hi = new Form("Border Layout", new BorderLayout());
((BorderLayout)hi.getLayout()).setCenterBehavior(BorderLayout.CENTER_BEHAVIOR_CENTER);
hi.add(BorderLayout.CENTER, new Label("Center")).
    add(BorderLayout.SOUTH, new Label("South")).
    add(BorderLayout.NORTH, new Label("North")).
    add(BorderLayout.EAST, new Label("East")).
    add(BorderLayout.WEST, new Label("West"));
hi.show();

Results in:

Border Layout with CENTER_BEHAVIOR_CENTER
Figure 16. Border Layout with CENTER_BEHAVIOR_CENTER
Because of its scaling behavior scrolling a border layout makes no sense. However it is a common mistake to apply a border layout to a scrollable container or trying to make a border layout scrollable. That is why Container explicitly blocks scrolling on a border layout.

In the case of RTL [1] the EAST and WEST values are implicitly reversed as shown in this image:

Border Layout in RTL mode
Figure 17. Border Layout in RTL mode
The preferred size of the center component doesn’t matter in border layout but the preferred size of the sides is. E.g. If you place an very large component in the SOUTH it will take up the entire screen and won’t leave room for anything.

Grid Layout

GridLayout accepts a predefined grid (rows/columns) and grants all components within it an equal size based on the dimensions of the largest component.

The main use case for this layout is a grid of icons e.g. like one would see in the iPhone home screen.

If the number of rows * columns is smaller than the number of components added a new row is implicitly added to the grid. However, if the number of components is smaller than available cells (won’t fill the last row) blank spaces will be left in place.

In this example we can see that a 2x2 grid is used to add 5 elements, this results in an additional row that’s implicitly added turning the grid to a 3x2 grid implicitly and leaving one blank cell.

Form hi = new Form("Grid Layout 2x2", new GridLayout(2, 2));
hi.add(new Label("First")).
    add(new Label("Second")).
    add(new Label("Third")).
    add(new Label("Fourth")).
    add(new Label("Fifth"));
Grid Layout 2x2
Figure 18. Grid Layout 2x2

When we use a 2x4 size ratio we would see elements getting cropped as we do here. The grid layout uses the grid size first and doesn’t pay too much attention to the preferred size of the components it holds.

Grid Layout 2x4
Figure 19. Grid Layout 2x4

Grid also has an autoFit attribute that can be used to automatically calculate the column count based on available space and preferred width. This is really useful for working with UI’s where the device orientation might change.

There is also a terse syntax for working with a grid that has two versions, one that uses the "auto fit" option and another that accepts the column names. Heres a sample of the terse syntax coupled with the auto fit screenshots of the same code in two orientations:

GridLayout.encloseIn(new Label("First"),
    new Label("Second"),
    new Label("Third"),
    new Label("Fourth"),
    new Label("Fifth")));
Grid Layout autofit portrait
Figure 20. Grid Layout autofit portrait
Grid Layout autofit landscape
Figure 21. Grid Layout autofit landscape

Table Layout

The TableLayout is a very elaborate constraint based layout manager that can arrange elements in rows/columns while defining constraints to control complex behavior such as spanning, alignment/weight etc.

The table layout is in the com.codename1.ui.table package and not in the layouts package.
This is due to the fact that TableLayout was originally designed for the Table class.

Despite being constraint based the table layout isn’t strict about constraints and will implicitly add a constraint when one is missing.

Unlike grid layout table layout won’t implicitly add a row if the row/column count is incorrect
Form hi = new Form("Table Layout 2x2", new TableLayout(2, 2));
hi.add(new Label("First")).
    add(new Label("Second")).
    add(new Label("Third")).
    add(new Label("Fourth")).
    add(new Label("Fifth"));
hi.show();
2x2 TableLayout with 5 elements
Figure 22. 2x2 TableLayout with 5 elements, notice that the last element is missing

Table layout supports the ability to grow the last column which can be enabled using the setGrowHorizontally method. You can also use a shortened terse syntax to construct a table layout however since the table layout is a constraint based layout you won’t be able to utilize its full power with this syntax.

The default usage of the encloseIn below uses the setGrowHorizontally flag.

Container tl = TableLayout.encloseIn(2, new Label("First"),
                new Label("Second"),
                new Label("Third"),
                new Label("Fourth"),
                new Label("Fifth")));
TableLayout.encloseIn() with default behavior of growing the last column
Figure 23. TableLayout.encloseIn() with default behavior of growing the last column
The Full Potential

Table layout is a beast, to truly appreciate it we need to use the constraint syntax which allows us to span, align and set width/height for the rows & columns.

Table layout works with a Constraint instance that can communicate our intentions into the layout manager. Such constraints can include more than one attribute e.g. span and height.

Table layout constraints can’t be reused for more than one component.

The constraint class supports the following attributes

Table 1. Constraint properties

column

The column for the table cell. This defaults to -1 which will just place the component in the next available cell

row

Similar to column, defaults to -1 as well

width

The column width in percentages, -1 will use the preferred size. -2 for width will take up the rest of the available space

height

Similar to width but doesn’t support the -2 value

spanHorizontal

The cells that should be occupied horizontally defaults to 1 and can’t exceed the column count - current offset.

spanVertical

Similar to spanHorizontal with the same limitations

horizontalAlign

The horizontal alignment of the content within the cell, defaults to the special case -1 value to take up all the cell space can be either -1, Component.LEFT, Component.RIGHT or Component.CENTER

verticalAlign

Similar to horizontalAlign can be one of -1, Component.TOP, Component.BOTTOM or Component.CENTER

You only need to set width/height to one cell in a column/row.

The table layout constraint sample tries to demonstrate some of the unique things you can do with constraints.

Due to the complexity of the code below we annotate lines with numbers and follow up on individual lines.
TableLayout tl = new TableLayout(2, 3); (1)
Form hi = new Form("Table Layout Cons", tl);
hi.setScrollable(false); (2)
hi.add(tl.createConstraint(). (3)
            widthPercentage(20),
                new Label("AAA")).

        add(tl.createConstraint(). (4)
            horizontalSpan(2).
            heightPercentage(80).
            verticalAlign(Component.CENTER).
            horizontalAlign(Component.CENTER),
                new Label("Span H")).

        add(new Label("BBB")).

        add(tl.createConstraint().
            widthPercentage(60).
            heightPercentage(20),
                new Label("CCC")).

        add(tl.createConstraint().
            widthPercentage(20),
                new Label("DDD"));
1 We need the table layout instance to create constraints. A constraint must be created for every component and must be used with the same layout as the parent container.
2 This is rather important. To get the look in the screenshot we need to turn scrolling off so the height constraint doesn’t take up available height. Otherwise it will miscalculate available height due to scrolling. You can scroll a table layout but sizing will be different.
3 We create the constraint and instantly apply width to it. This is a shorthand syntax for the code block below
4 We can chain constraint creation using a call like this so multiple constraints apply to a single cell. Notice that we don’t span and set width on the same axis (horizontal span + width), doing something like that would create confusing behavior.

Here is the full code mentioned in item 3:

TableLayout.Constraint cn = tl.createConstraint();
cn.setWidthPercentage(20);
hi.add(cn, new Label("AAA")).
TableLayout.encloseIn() with default behavior of growing the last column
Figure 24. TableLayout constraints can be used to create very el

Layered Layout

The LayeredLayout places the components in order one on top of the other and sizes them all to the size of the largest component. This is useful when trying to create an overlay on top of an existing component. E.g. an “x” button to allow removing the component.

The X on this button was placed there using the layered layout code below
Figure 25. The X on this button was placed there using the layered layout code below

The code to generate this UI is slightly complex and contains very little relevant pieces. The only truly relevant piece is this block:

hi.add(LayeredLayout.encloseIn(settingsLabel,
        FlowLayout.encloseRight(close)));

We are doing three distinct things here:

  1. We are adding a layered layout to the form.

  2. We are creating a layered layout and placing two components within. This would be the equivalent of just creating a LayeredLayout Container and invoking add twice.

  3. We use FlowLayout to position the X close button in the right position.

The layered layout sizes all components to the exact same size one on top of the other. It usually requires that we use another container within; in order to position the components correctly.

This is the full source of the example for completeness:

Form hi = new Form("Layered Layout");
int w = Math.min(Display.getInstance().getDisplayWidth(), Display.getInstance().getDisplayHeight());
Button settingsLabel = new Button("");
Style settingsStyle = settingsLabel.getAllStyles();
settingsStyle.setFgColor(0xff);
settingsStyle.setBorder(null);
settingsStyle.setBgColor(0xff00);
settingsStyle.setBgTransparency(255);
settingsStyle.setFont(settingsLabel.getUnselectedStyle().getFont().derive(w / 3, Font.STYLE_PLAIN));
FontImage.setMaterialIcon(settingsLabel, FontImage.MATERIAL_SETTINGS);

Button close = new Button("");
close.setUIID("Container");
close.getAllStyles().setFgColor(0xff0000);
FontImage.setMaterialIcon(close, FontImage.MATERIAL_CLOSE);
hi.add(LayeredLayout.encloseIn(settingsLabel,
        FlowLayout.encloseRight(close)));

Forms have a built in layered layout that you can access via getLayeredPane(), this allows you to overlay elements on top of the content pane.

The layered pane is used internally by components such as InteractionDialog, AutoComplete etc.

Codename One also includes a GlassPane that resides on top of the layered pane. Its useful if you just want to "draw" on top of elements but is harder to use than layered pane.
Placing native widgets within a layered layout is problematic due to the behavior of peer components. Sample of peer components include the BrowserComponent, video playback etc.
We discuss peer components in the advanced topics section.

GridBag Layout

GridBagLayout was introduced to simplify the process of porting existing Swing/AWT code with a more familiar API. The API for this layout is problematic as it was designed for AWT/Swing where styles were unavailable. As a result it has its own insets API instead of using elements such as padding/margin.

Our recommendation is to use Table which is just as powerful but has better Codename One integration.

To demonstrate grid bag layout we ported the sample from the Java tutorial to Codename One.

Button button;
hi.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
//natural height, maximum width
c.fill = GridBagConstraints.HORIZONTAL;


button = new Button("Button 1");
c.weightx = 0.5;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
hi.addComponent(c, button);

button = new Button("Button 2");
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0.5;
c.gridx = 1;
c.gridy = 0;
hi.addComponent(c, button);

button = new Button("Button 3");
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0.5;
c.gridx = 2;
c.gridy = 0;
hi.addComponent(c, button);

button = new Button("Long-Named Button 4");
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 40;      //make this component tall
c.weightx = 0.0;
c.gridwidth = 3;
c.gridx = 0;
c.gridy = 1;
hi.addComponent(c, button);

button = new Button("5");
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 0;       //reset to default
c.weighty = 1.0;   //request any extra vertical space
c.anchor = GridBagConstraints.PAGE_END; //bottom of space
c.insets = new Insets(10,0,0,0);  //top padding
c.gridx = 1;       //aligned with button 2
c.gridwidth = 2;   //2 columns wide
c.gridy = 2;       //third row
hi.addComponent(c, button);

Notice that because of the way gridbag works we didn’t provide any terse syntax API for it although it should be possible.

GridbagLayout sample from the Java tutorial running on Codename One
Figure 26. GridbagLayout sample from the Java tutorial running on Codename One

Group Layout

GroupLayout is a layout that would be familiar to the users of the NetBeans GUI builder (Matisse). Its a layout manager that’s really hard to use for manual coding but is remarkably powerful for some really elaborate use cases.

It was originally added during the LWUIT days as part of an internal attempt to port Matisse to LWUIT. It is still useful to this day as developers copy and paste Matisse code into Codename One and produce very elaborate layouts with drag & drop.

Since the layout is based on an older version of group layout some things need to be adapted in the code or you should use the special "compatibility" library for Matisse to get better interaction. We also recommend tweeking Matisse to use import statements instead of full package names, that way if you use Label just changing the awt import to a Codename One import will make it use Label.

Unlike any other layout manager group layout adds the components into the container instead of the standard API. This works nicely for GUI builder code but as you can see from this sample it doesn’t make the code very readable:

Form hi = new Form("GroupLayout");

Label label1 = new Label();
Label label2 = new Label();
Label label3 = new Label();
Label label4 = new Label();
Label label5 = new Label();
Label label6 = new Label();
Label label7 = new Label();

label1.setText("label1");

label2.setText("label2");

label3.setText("label3");

label4.setText("label4");

label5.setText("label5");

label6.setText("label6");

label7.setText("label7");

GroupLayout layout = new GroupLayout(hi.getContentPane());
hi.setLayout(layout);
layout.setHorizontalGroup(
    layout.createParallelGroup(GroupLayout.LEADING)
    .add(layout.createSequentialGroup()
        .addContainerGap()
        .add(layout.createParallelGroup(GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(label1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(LayoutStyle.RELATED)
                .add(layout.createParallelGroup(GroupLayout.LEADING)
                    .add(label4, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                    .add(label3, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                    .add(label2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)))
            .add(label5, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
            .add(layout.createSequentialGroup()
                .add(label6, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(LayoutStyle.RELATED)
                .add(label7, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)))
        .addContainerGap(296, Short.MAX_VALUE))
);
layout.setVerticalGroup(
    layout.createParallelGroup(GroupLayout.LEADING)
    .add(layout.createSequentialGroup()
        .addContainerGap()
        .add(layout.createParallelGroup(GroupLayout.TRAILING)
            .add(label2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
            .add(label1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
        .addPreferredGap(LayoutStyle.RELATED)
        .add(label3, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(LayoutStyle.RELATED)
        .add(label4, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(LayoutStyle.RELATED)
        .add(label5, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(LayoutStyle.RELATED)
        .add(layout.createParallelGroup(GroupLayout.LEADING)
            .add(label6, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
            .add(label7, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
        .addContainerGap(150, Short.MAX_VALUE))
);
GroupLayout Matisse generated UI running in Codename One
Figure 27. GroupLayout Matisse generated UI running in Codename One

If you are porting newer Matisse code there are simple changes you can do:

  • Change addComponent to add

  • Change addGroup to add

  • Remove references to ComponentPlacement and reference LayoutStyle directly

Mig Layout

MigLayout is a popular cross platform layout manager that was ported to Codename One from Swing.

MiG is still considered experimental so proceed with caution!
The API was deprecated to serve as a warning of its experimental status.

The best reference for MiG would probably be its quick start guide (PDF link). As a reference we ported one of the samples from that PDF to Codename One:

Form hi = new Form("MigLayout", new MigLayout("fillx,insets 0"));

hi.add(new Label("First")).
    add("span 2 2", new Label("Second")).  // The component will span 2x2 cells.
    add("wrap", new Label("Third")).      // Wrap to next row
    add(new Label("Forth")).
    add("wrap", new Label("Fifth")).    // Note that it "jumps over" the occupied cells.
    add(new Label("Sixth")).
    add(new Label("Seventh"));
hi.show();
MiG layout sample ported to Codename One
Figure 28. MiG layout sample ported to Codename One

It should be reasonably easy to port MiG code but you should notice the following:

  • MiG handles a lot of the spacing/padding/margin issues that are missing in Swing/AWT. With Codename One styles we have the padding & margin which are probably a better way to do a lot of the things that MiG does

  • The add method in Codename One can be changed as shown in the sample above.

  • The constraint argument for Coedname One add calls appears before the Component instance.

GUI Builder

The GUI builder allows us to arrange components visually within a UI using drag & drop, property sheets etc. With the GUI builder we can create elaborate, rich UI’s without writing the layout code.

The new GUI builder is still in beta state at this time, it shouldn’t be confused with the old GUI builder that is a part of the Codename One designer tool
Why two GUI Builders?

The original old GUI builder has it’s roots in our work at Sun Microsystems, it was developed directly into the designer tool and stores it’s data as part of 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

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 29. The old GUI builder
The new GUI builder
Figure 30. The same UI in the new GUI builder

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 and is covered in all the getting started tutorials for the various IDE’s specifically in 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 31. Right click the package select NewOther
In the Codename One section select the GUI builder form
Figure 32. In the Codename One section select the GUI builder form
Type in the name of the form and click finish
Figure 33. 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 34. 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 35. Right click the package select NewCodename One Form (or Dialog/Container)
Type in a name for the new form
Figure 36. Type in a name for the new form
Launch the GUI builder thru the right click menu on the newly created file
Figure 37. 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 38. Right click the package select NewOther
In the Codename One section select the GUI builder option
Figure 39. In the Codename One section select the GUI builder option
Type in the name of the form and click finish
Figure 40. 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 41. 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 various ways but the basic concepts should remain the same.

The GUI builder is controlled via it’s main toolbar, notice that your changes will only be applied when you click the Save button on the right:

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

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

The sidebar options
Figure 43. 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 44. 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 45. 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 will be 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 46. 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 47. 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 48. 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 various Codename One layouts in the developer guide.

In general layouts define the mathematical logic for component positions that we can then apply to the various 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 49. 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 various locations:

FlowLayout settings
Figure 50. FlowLayout settings

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

Border layout constraints
Figure 51. 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 52. 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 53. 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 54. 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. Various IDE’s generate that code at different times. Some 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.


1. RTL = Right To Left or Bidi = bi-directional. A common term used for languages such as Hebrew or Arabic that are written from the right to left direction hence all the UI needs to be "reversed". Bidi denotes the fact that while the language is written from right to left, the numbers are still written in the other direction hence two directions…​