= Laying Out the GUI in Java
:author:
:revnumber:
:revdate: 2016/03/17 20:48
:keywords: gui, documentation, nifty, hud
:relfileprefix: ../../
:imagesdir: ../..
ifdef::env-github,env-browser[:outfilesuffix: .adoc]


.  <<jme3/advanced/nifty_gui#,Nifty GUI Concepts>>
.  <<jme3/advanced/nifty_gui_best_practices#,Nifty GUI Best Practices>>
.  <<jme3/advanced/nifty_gui_xml_layout#,Nifty GUI XML Layout>> or *Nifty +++<abbr title="Graphical User Interface">GUI</abbr>+++ Java Layout*
.  <<jme3/advanced/nifty_gui_overlay#,Nifty GUI Overlay>> or <<jme3/advanced/nifty_gui_projection#,Nifty GUI Projection>>
.  <<jme3/advanced/nifty_gui_java_interaction#,Interact with the GUI from Java>>

*Work in progress* You can “draw the +++<abbr title="Graphical User Interface">GUI</abbr>+++ to the screen by writing Java code – alternatively to using XML. Typically you lay out the static base +++<abbr title="Graphical User Interface">GUI</abbr>+++ in XML, and use Java commands if you need to change the +++<abbr title="Graphical User Interface">GUI</abbr>+++ dynamically at runtime. In theory, you can also lay out the whole +++<abbr title="Graphical User Interface">GUI</abbr>+++ in Java (but we don't cover that here).


== Sample Code

Sample project

*  *Original Source Code:* link:http://nifty-gui.svn.sourceforge.net/viewvc/nifty-gui/nifty-default-controls-examples/trunk/src/main/java/de/lessvoid/nifty/examples/[/nifty-default-controls-examples/trunk/src/main/java/de/lessvoid/nifty/examples/]. +
*  *Download demo project:* link:http://files.seapegasus.org/NiftyGuiDemo.zip[http://files.seapegasus.org/NiftyGuiDemo.zip] (jme3-ready) +The full demo ZIP is based on `de.lessvoid.nifty.examples.controls.ControlsDemo.java`.
..  The demo is a SimpleApplication-based game (use e.g. the BasicGame template in the jMonkeyEngine SDK).
..  Copy images and sound files into your project's `assets/Interface/` directory. (In this example, I copied them from `nifty-default-controls-examples/trunk/src/main/resources/` to `assets/Interface/`).
..  Make sure to use paths relative to your project's `assets/` directory.
***  E.g. for .fnt/.png/.jpg files use `filename(“Interface/yang.png);` ( not `filename(“yang.png);`).
***  E.g. for .wav/.ogg files use `filename(“Interface/sounds/gong.wav);` (not `filename(“sounds/gong.wav);`).



Just so you get a quick picture what Nifty +++<abbr title="Graphical User Interface">GUI</abbr>+++'s Java Syntax looks like, here is the most basic example. It creates a screen with a layer and a panel that contains a button.

[source,java]
----
package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.niftygui.NiftyJmeDisplay;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.builder.ScreenBuilder;
import de.lessvoid.nifty.builder.LayerBuilder;
import de.lessvoid.nifty.builder.PanelBuilder;
import de.lessvoid.nifty.controls.button.builder.ButtonBuilder;
import de.lessvoid.nifty.screen.DefaultScreenController;

/**
 * @author iamcreasy
*/
public class Main extends SimpleApplication {

    public static void main(String[] args) {
        Main app = new Main();
        app.start();
    }

    @Override
    public void simpleInitApp() {
    NiftyJmeDisplay niftyDisplay = NiftyJmeDisplay.newNiftyJmeDisplay(
            assetManager, inputManager, audioRenderer, guiViewPort);
    Nifty nifty = niftyDisplay.getNifty();
    guiViewPort.addProcessor(niftyDisplay);
    flyCam.setDragToRotate(true);

    nifty.loadStyleFile("nifty-default-styles.xml");
    nifty.loadControlFile("nifty-default-controls.xml");

    // <screen>
    nifty.addScreen("Screen_ID", new ScreenBuilder("Hello Nifty Screen"){{
        controller(new DefaultScreenController()); // Screen properties

        // <layer>
        layer(new LayerBuilder("Layer_ID") {{
            childLayoutVertical(); // layer properties, add more...

            // <panel>
            panel(new PanelBuilder("Panel_ID") {{
               childLayoutCenter(); // panel properties, add more...

                // GUI elements
                control(new ButtonBuilder("Button_ID", "Hello Nifty"){{
                    alignCenter();
                    valignCenter();
                    height("5%");
                    width("15%");
                }});

                //.. add more GUI elements here

            }});
            // </panel>
          }});
        // </layer>
      }}.build(nifty));
    // </screen>

    nifty.gotoScreen("Screen_ID"); // start the screen
    }
}
----


== Implement Your GUI Layout


image::jme3/advanced/gui-layout-draft.png[gui-layout-draft.png,width="",height="",align="right"]


In this tutorial, you recreate the same screen as in the Nifty +++<abbr title="Graphical User Interface">GUI</abbr>+++ XML example.

Create an Screen.Java file in the `assets/Interfaces/` directory of your project. One Java file can contain several, or even all screens. As a reminder: Nifty displays one screen at a time; a screen contains several layers on top of one another; each layer contains panels that are embedded into another; the panels contain the actual content (text, images, or controls).


=== Make Screens

The following minimal Java file contains a start screen and a HUD screen. (Neither has been defined yet.)

[source,java]
----

nifty.addScreen("start", new ScreenBuilder("start"){{
    controller(new DefaultScreenController());
    // <!-- ... -->
  }}.build(nifty));

nifty.addScreen("hud", new ScreenBuilder("hud"){{
    controller(new DefaultScreenController());
    // <!-- ... -->
  }}.build(nifty));

----

Every Nifty +++<abbr title="Graphical User Interface">GUI</abbr>+++ must have a start screen. The others (in this example, the HUD screen) are optional.


=== Make Layers

The following Java code shows how we add layers to the start screen and HUD screen:

[source,java]
----

nifty.addScreen("start", new ScreenBuilder("start"){{
        controller(new DefaultScreenController());

         // layer added
         layer(new LayerBuilder("background") {{
            childLayoutCenter();
            backgroundColor("#000f");

            // <!-- ... -->
         }});

         layer(new LayerBuilder("foreground") {{
                childLayoutVertical();
                backgroundColor("#0000");

            // <!-- ... -->
         }});
         // layer added

      }}.build(nifty));
----

Repeat the same, but use

[source]
----
nifty.addScreen("hud", new ScreenBuilder("hud"){{
----

 for the HUD screen.

In a layer, you can now add panels and arrange them. Panels are containers that mark the areas where you want to display text, images, or controls (buttons etc) later.


=== Make Panels

A panel is the inner-most container (that will contain the actual content: text, images, or controls). You place panels inside layers. The following panels go into in the `start` screen:

[source,java]
----

    nifty.addScreen("start", new ScreenBuilder("start") {{
        controller(new DefaultScreenController());
        layer(new LayerBuilder("background") {{
            childLayoutCenter();
            backgroundColor("#000f");
            // <!-- ... -->
        }});

        layer(new LayerBuilder("foreground") {{
                childLayoutVertical();
                backgroundColor("#0000");

            // panel added
            panel(new PanelBuilder("panel_top") {{
                childLayoutCenter();
                alignCenter();
                backgroundColor("#f008");
                height("25%");
                width("75%");
            }});

            panel(new PanelBuilder("panel_mid") {{
                childLayoutCenter();
                alignCenter();
                backgroundColor("#0f08");
                height("50%");
                width("75%");
            }});

            panel(new PanelBuilder("panel_bottom") {{
                childLayoutHorizontal();
                alignCenter();
                backgroundColor("#00f8");
                height("25%");
                width("75%");

                panel(new PanelBuilder("panel_bottom_left") {{
                    childLayoutCenter();
                    valignCenter();
                    backgroundColor("#44f8");
                    height("50%");
                    width("50%");
                }});

                panel(new PanelBuilder("panel_bottom_right") {{
                    childLayoutCenter();
                    valignCenter();
                    backgroundColor("#88f8");
                    height("50%");
                    width("50%");
                }});
            }}); // panel added
        }});

    }}.build(nifty));

----

The following panels go into in the `hud` screen:

[source,Java]
----

    nifty.addScreen("hud", new ScreenBuilder("hud") {{
        controller(new DefaultScreenController());

        layer(new LayerBuilder("background") {{
            childLayoutCenter();
            backgroundColor("#000f");
            // <!-- ... -->
        }});

        layer(new LayerBuilder("foreground") {{
            childLayoutHorizontal();
            backgroundColor("#0000");

            // panel added
            panel(new PanelBuilder("panel_left") {{
                childLayoutVertical();
                backgroundColor("#0f08");
                height("100%");
                width("80%");
                // <!-- spacer -->
            }});

            panel(new PanelBuilder("panel_right") {{
                childLayoutVertical();
                backgroundColor("#00f8");
                height("100%");
                width("20%");

                panel(new PanelBuilder("panel_top_right1") {{
                    childLayoutCenter();
                    backgroundColor("#00f8");
                    height("15%");
                    width("100%");
                }});

                panel(new PanelBuilder("panel_top_right2") {{
                    childLayoutCenter();
                    backgroundColor("#44f8");
                    height("15%");
                    width("100%");
                }});

                panel(new PanelBuilder("panel_bot_right") {{
                    childLayoutCenter();
                    valignCenter();
                    backgroundColor("#88f8");
                    height("70%");
                    width("100%");
                }});
            }}); // panel added
        }});
    }}.build(nifty));
----

Try the sample. Remember to activate a screen using `nifty.gotoScreen(“start);` or `hud` respectively.
The result should look as follows:


image::jme3/advanced/nifty-gui-panels.png[nifty-gui-panels.png,width="",height="",align="center"]



== Adding Content to Panels

See also link:http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Layout_Introduction[Layout Introduction] on the Nifty +++<abbr title="Graphical User Interface">GUI</abbr>+++ site.


=== Add Images

The start-background.png image is a fullscreen background picture. In the `start` screen, add the following image element:

[source,java]
----

    nifty.addScreen("start", new ScreenBuilder("start") {{
        controller(new DefaultScreenController());
        layer(new LayerBuilder("background") {{
            childLayoutCenter();
            backgroundColor("#000f");

            // add image
            image(new ImageBuilder() {{
                filename("Interface/tutorial/start-background.png");
            }});

        }});

----

The hud-frame.png image is a transparent frame that we use as HUD decoration. In the `hud` screen, add the following image element:

[source,java]
----
    nifty.addScreen("hud", new ScreenBuilder("hud") {{
        controller(new DefaultScreenController());

        layer(new LayerBuilder("background") {{
            childLayoutCenter();
            backgroundColor("#000f");

            // add image
            image(new ImageBuilder() {{
                filename("Interface/tutorial/hud-frame.png");
            }});

        }});
----

The face1.png image is an image that you want to use as a status icon.
In the `hud` screen's `foreground` layer, add the following image element:

[source,java]
----
                panel(new PanelBuilder("panel_top_right2") {{
                    childLayoutCenter();
                    backgroundColor("#44f8");
                    height("15%");
                    width("100%");

                    // add image
                    image(new ImageBuilder() {{
                        filename("Interface/tutorial/face1.png");
                        valignCenter();
                        alignCenter();
                        height("50%");
                        width("30%");
                    }});

                }});
----

This image is scaled to use 50% of the height and 30% of the width of its container.


=== Add Static Text

The game title is a typical example of static text. In the `start` screen, add the following text element:

[source,java]
----

           // panel added
            panel(new PanelBuilder("panel_top") {{
                childLayoutCenter();
                alignCenter();
                backgroundColor("#f008");
                height("25%");
                width("75%");

                // add text
                text(new TextBuilder() {{
                    text("My Cool Game");
                    font("Interface/Fonts/Default.fnt");
                    height("100%");
                    width("100%");
                }});

            }});
----

For longer pieces of static text, such as an introduction, you can use wrap=“true. Add the following text element to the `Start screen`:

[source,java]
----

            panel(new PanelBuilder("panel_mid") {{
                childLayoutCenter();
                alignCenter();
                backgroundColor("#0f08");
                height("50%");
                width("75%");
                // add text
                text(new TextBuilder() {{
                    text("Here goes some text describing the game and the rules and stuff. "+
                         "Incidentally, the text is quite long and needs to wrap at the end of lines. ");
                    font("Interface/Fonts/Default.fnt");
                    wrap(true);
                    height("100%");
                    width("100%");
                }});

            }});
----

The font used is jME3's default font “Interface/Fonts/Default.fnt which is included in the jMonkeyEngine.JAR. You can add your own fonts to your own `assets/Interface` directory.


=== Add Controls

Before you can use any control, you must load a Control Definition first. Add the following two lines _before_ your screen definitions:

[source,java]
----

    nifty.loadStyleFile("nifty-default-styles.xml");
    nifty.loadControlFile("nifty-default-controls.xml");
----


==== Label Control

Use label controls for text that you want to edit dynamically from Java. One example for this is the score display.
In the `hud` screen's `foreground` layer, add the following text element:

[source,java]
----
                panel(new PanelBuilder("panel_top_right1") {{
                    childLayoutCenter();
                    backgroundColor("#00f8");
                    height("15%");
                    width("100%");

                    control(new LabelBuilder(){{
                        color("#000");
                        text("123");
                        width("100%");
                        height("100%");
                    }});
----

Note that the width and height do not scale the bitmap font, but make indirectly certain it is centered. If you want a different size for the font, you need to provide an extra bitmap font (they come with fixes sizes and don't scale well).


==== Button Control

Our +++<abbr title="Graphical User Interface">GUI</abbr>+++ plan asks for two buttons on the start screen. You add the Start and Quit buttons to the bottom panel of the `start` screen using the `&lt;control&gt;` element:

[source,java]
----

                panel(new PanelBuilder("panel_bottom_left") {{
                    childLayoutCenter();
                    valignCenter();
                    backgroundColor("#44f8");
                    height("50%");
                    width("50%");

                    // add control
                    control(new ButtonBuilder("StartButton", "Start") {{
                      alignCenter();
                      valignCenter();
                      height("50%");
                      width("50%");
                    }});

                }});

                panel(new PanelBuilder("panel_bottom_right") {{
                    childLayoutCenter();
                    valignCenter();
                    backgroundColor("#88f8");
                    height("50%");
                    width("50%");

                    // add control
                    control(new ButtonBuilder("QuitButton", "Quit") {{
                      alignCenter();
                      valignCenter();
                      height("50%");
                      width("50%");
                    }});

                }});
----

Note that these controls don't do anything yet – we'll get to that soon.


==== Other Controls

Nifty additionally offers many customizable controls such as check boxes, text fields, menus, chats, tabs, … See also link:http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Elements[Elements] on the Nifty +++<abbr title="Graphical User Interface">GUI</abbr>+++ site.


== Intermediate Result

When you preview this code in the jMonkeyEngine SDK, our tutorial demo should looks as follows: A start screen with two buttons, and a game screen with a simple HUD frame and a blue cube (which stands for any jME3 game content).

*Tip:* Remove all lines that set background colors, you only needed them to see the arrangement.


image::jme3/advanced/nifty-gui-simple-demo.png[nifty-gui-simple-demo.png,width="",height="",align="center"]



== Nifty Java Settings

Before initializing the nifty screens, you set up properties and register media.
[cols="2", options="header"]
|===

a| Nifty Method
a| Description

a| registerSound(“mysound, “Interface/abc.wav);
a|

a| registerMusic(“mymusic, “Interface/xyz.ogg);
a|

a| registerMouseCursor(“mypointer, “Interface/abc.png, 5, 4);
a|

a| registerEffect(?);
a| ?

a| setDebugOptionPanelColors(true);
a| Highlight all panels, makes it easier to arrange them.

|===

Example:

[source,java]
----
nifty.registerMouseCursor("hand", "Interface/mouse-cursor-hand.png", 5, 4);
----


== Next Steps

Integrate the +++<abbr title="Graphical User Interface">GUI</abbr>+++ into the game. Typically, you will overlay the +++<abbr title="Graphical User Interface">GUI</abbr>+++.

*  <<jme3/advanced/nifty_gui_overlay#,Nifty GUI Overlay>> (recommended)
*  <<jme3/advanced/nifty_gui_projection#,Nifty GUI Projection>> (optional)
