4.1 Tutorial

Welcome to the RapaGUI tutorial! This small step-by-step document will guide you through the process of creating your first GUI with RapaGUI in very few steps. We will create a little GUI application that consists of a listview, a text entry widget, and two buttons. The two buttons should be programmed to allow the addition and removal of items from the listview. The data to be inserted into the listview should be taken from the text entry widget. Here is what this little application looks like on Windows:

Let us start with the basics: In RapaGUI GUIs are created using XML files that contain a description of a number of windows containing a variety of GUI elements. Here is a minimal GUI description for a RapaGUI GUI that contains a window with a listview, a text entry widget, and two buttons in XML format:

 
<?xml version="1.0" encoding="iso-8859-1"?>
<application>
   <window title="Example GUI">
      <vgroup>
         <listview>
            <column/>
         </listview>
         <textentry/>
         <hgroup>
            <button id="add">Add</button>
            <button id="rem">Remove</button>
         </hgroup>
      </vgroup>
   </window>
</application>

The <application> object is the master MOAI object for every application and must only be used once per application. All other MOAI objects are children of Application class. The root element of every <window> object must be derived from Group class, i.e. it must be either <vgroup>, <hgroup>, or <colgroup>. Also note that there must be only one root element per window.

To see how our XML declaration above looks as a GUI, we have to save it to a file named GUI.xml and then use the following code to make RapaGUI convert it to a native GUI for the operating system Hollywood is running on:

 
@REQUIRE "RapaGUI"

moai.CreateApp(FileToString("GUI.xml"))

Repeat
   WaitEvent
Forever

Next you should add some information about your program using the @APPAUTHOR, @APPCOPYRIGHT, @APPDESCRIPTION, @APPTITLE, and @APPVERSION preprocessor commands. RapaGUI needs this information for several purposes, e.g. the information passed in @APPTITLE is used by the MUI preferences window on AmigaOS and compatibles. Here is an example declaration of these preprocessor commands:

 
@APPTITLE "Tutorial"
@APPVERSION "$VER: Tutorial 1.0 (29.12.15)"
@APPCOPYRIGHT "Copyright ©2015, Andreas Falkenhahn"
@APPAUTHOR "Andreas Falkenhahn"
@APPDESCRIPTION "The tutorial app from the RapaGUI guide"

The next thing we have to do is install an event handler callback using the InstallEventHandler() Hollywood function because our Hollywood script needs to be informed every time a RapaGUI event comes in. Thus, we have to modify our code as follows:

 
@REQUIRE "RapaGUI"

Function p_EventFunc(msg)
   ; contents follow below
EndFunction

InstallEventHandler({RapaGUI = p_EventFunc})
moai.CreateApp(FileToString("GUI.xml"))

Repeat
   WaitEvent
Forever

What we have done here is installing the function p_EventFunc as an event handler callback that gets executed whenever a RapaGUI event comes in. When we get such an event, we then have to check which MOAI class and attribute has triggered it. This is done by looking into the msg.Class and msg.Attribute fields of the event message that our callback receives as its first parameter.

The next thing we want to do is add the functionality that whenever the user presses the "Add" button the text in the text entry widget should get added to the listview as the last entry. To do this, we first have to find a way of identifying our widgets from the Hollywood script. This is done by giving them IDs in the XML declaration. IDs are simply text strings that are used for talking to MOAI objects from Hollywood scripts. So let's add some IDs now for all widgets that we need to talk to. We have to modify our XML declaration like this:

 
...
         <listview id="mylistview">
            <column/>
         </listview>
         <textentry id="mystring"/>
         <hgroup>
            <button id="mybt1">Add</button>
            <button id="mybt2">Remove</button>
         </hgroup>
...

Now that we have done this we can add some code to our event handler callback that grabs the contents of the text entry widget and adds it to the end of the list in our listview object. This is done by first calling moai.Get() on the Textentry.Text attribute to get the contents of the string widget and then running the method Listview.Insert on the listview widget using moai.DoMethod() to insert the entry into the listview. Here is the code that has to be inserted into p_EventFunc for this purpose:

 
   Switch msg.Class
   ...
   Case "Button":
      Switch msg.Attribute
      Case "Pressed":
         Switch msg.ID
         Case "mybt1":    ; "Add" button was pressed
            Local s$ = moai.Get("mystring", "text")
            moai.DoMethod("mylistview", "insert", "bottom", s$)
         EndSwitch
      EndSwitch
   EndSwitch

The next thing we want to do is implement the functionality of our "Remove" button. Whenever this button is pressed, we want the active entry to be removed from the listview. We can do this by running the Listview.Remove method on the listview. Hence, we have to modify our code like this:

 
         Switch msg.ID
         ...
         Case "mybt2":    ; "Remove" button was pressed
            moai.DoMethod("mylistview", "remove", "active")
         EndSwitch

Now we want the active entry of the listview to be automatically displayed in the text entry widget. For this purpose we have to set up a notification on the Listview.Active attribute which is triggered whenever the active entry of the listview changes. Thus, we have to modify our XML file like this:

 
...
         <listview id="mylistview" notify="active">
            <column/>
         </listview>
...

In our event handler callback we can implement this functionality quite easily by running the Listview.GetEntry method and then setting the text entry widgets contents using the Textentry.Text attribute. Here is the code for doing that:

 
   Switch msg.Class
   ...
   Case "Listview":
      Switch msg.Attribute
      Case "Active":
         Local s$ = moai.DoMethod("mylistview", "getentry", "active")
         moai.Set("mystring", "text", s$)
      EndSwitch
   EndSwitch

If you try this code, you will set that the Listview.Active attribute is not only triggered when the user selects a new listview entry with his mouse, but also when entries are removed from the listview and thus cause a new entry becoming the active one.

The next thing we want to do is disable the "Remove" button when there is no active entry in the listview. We can disable widgets by setting the Area.Disabled attribute to True. As there are no entries in the listview initially, we have to set Area.Disabled to True already at the start of our program. So you have to insert this code:

 
...
moai.CreateApp(FileToString("GUI.xml"))
moai.Set("mybt2", "disabled", True)
...

Now we have to make some modifications to our event handler callback. Whenever we get the notification on Listview.Active we have to check if it is different from the special value "Off". If that is the case, we will enable the "Remove" button. The special value "Off" (-1) is returned by Listview.Active whenever there is no active entry in the listview. We have to modify our code like this:

 
   Switch msg.Class
   ...
   Case "Listview":
      Switch msg.Attribute
      Case "Active":
         Local s$ = moai.DoMethod("mylistview", "getentry", "active")
         moai.Set("mystring", "text", s$)
         moai.Set("mybt2", "disabled", IIf(msg.triggervalue = -1,
             True, False))
      EndSwitch
   EndSwitch

We use the field msg.TriggerValue here. This always contains the current value of the attribute that has triggered the event, i.e. in our case it contains the current value of the Listview.Active attribute. We could also call moai.Get() manually on Listview.Active first, but this is not really required because we can simply use the msg.TriggerValue shortcut.

The last thing we want to do is add a menu to our GUI. All RapaGUI programs should have a menu item informs the user that this program was done using RapaGUI. You can popup the this dialog by running the Application.AboutRapaGUI method on the application object. To add this menu to our program, we use Menubar class. Here is the XML code that you have to add before your window declaration:

 
...
<application>
   <menubar id="mymenubar">
      <menu title="File">
         <item id="menabout">About...</item>
         <item id="menaboutrapagui">About RapaGUI...</item>
         <item/>
         <item id="menquit">Quit</item>
      </menu>
   </menubar>
   ...
</application>

After we have created our menubar object using the XML code above we have to attach this menubar to our window. This is done by setting the Window.Menubar attribute to our menubar object. Here is the XML code for this:

 
<window title="Example GUI" menubar="mymenubar">

Now we have to add code to our event handler function that takes the appropriate action when a menu item is selected. Before we can do that, however, we need to assign an ID to our application object because we need to use moai.DoMethod() on it. Here is how the XML code needs to be adapted:

 
<application id="app">

Now we can write the code for our event handler callback function that handles menu items:

 
   Switch msg.Class
   ...
   Case "Menuitem":
      Switch msg.Attribute
      Case "Selected":
         Switch msg.id
         Case "menabout":
            moai.Request("Test", "Test program\n" ..
                "© 2015 by Andreas Falkenhahn", "OK")
         Case "menaboutrapagui":
            moai.DoMethod("app", "aboutrapagui")
         Case "menquit":
            End
         EndSwitch
      EndSwitch
   EndSwitch

Some final touches to our program could be adding online help to our widgets by using the Area.Tooltip and Menuitem.Help attributes, adding a status bar, and adding keyboard shortcuts for the menu items using the underscore character. These changes are left as an exercise for the reader.

So here is what our final program looks like. First the XML file:

 
<?xml version="1.0" encoding="iso-8859-1"?>
<application id="app">
   <menubar id="mymenubar">
      <menu title="File">
         <item id="menabout">About...</item>
         <item id="menaboutrapagui">
            About RapaGUI...</item>
         <item/>
         <item id="menquit">Quit</item>
      </menu>
   </menubar>
   <window title="Example GUI" menubar="mymenubar">
      <vgroup>
        <listview id="mylistview" notify="active">
            <column/>
         </listview>
         <textentry id="mystring"/>
         <hgroup>
            <button id="mybt1">Add</button>
            <button id="mybt2">Remove</button>
         </hgroup>
      </vgroup>
   </window>
</application>

And here is the code for the program logic:

 
@REQUIRE "RapaGUI"

@APPTITLE "Tutorial"
@APPVERSION "$VER: Tutorial 1.0 (29.12.15)"
@APPCOPYRIGHT "Copyright ©2015, Andreas Falkenhahn"
@APPAUTHOR "Andreas Falkenhahn"
@APPDESCRIPTION "The tutorial app from the RapaGUI guide"

Function p_EventFunc(msg)

   Switch msg.Class
   Case "Button":
      Switch msg.Attribute
      Case "Pressed":
         Switch msg.ID
         Case "mybt1":    ; "Add" button was pressed
            Local s$ = moai.Get("mystring", "text")
            moai.DoMethod("mylistview", "insert", "bottom", s$)
         Case "mybt2":    ; "Remove" button was pressed
            moai.DoMethod("mylistview", "remove", "active")
         EndSwitch
      EndSwitch

   Case "Listview":
      Switch msg.Attribute
      Case "Active":
         Local s$ = moai.DoMethod("mylistview", "getentry", "active")
         moai.Set("mystring", "text", s$)
         moai.Set("mybt2", "disabled", IIf(msg.triggervalue = -1,
             True, False))
      EndSwitch

   Case "Menuitem":
      Switch msg.Attribute
      Case "Selected":
         Switch msg.id
         Case "menabout":
            moai.Request("Test", "Test program\n" ..
                "© 2015 by Andreas Falkenhahn", "OK")
         Case "menaboutrapagui":
            moai.DoMethod("app", "aboutrapagui")
         Case "menquit":
            End
         EndSwitch
      EndSwitch
   EndSwitch

EndFunction

InstallEventHandler({RapaGUI = p_EventFunc})
moai.CreateApp(FileToString("GUI.xml"))
moai.Set("mybt2", "disabled", True)

Repeat
   WaitEvent
Forever

That's it! Now you should be able to create fantastic new GUI programs with Hollywood and RapaGUI. Thank you for reading this tutorial and enjoy the power of modern GUI programming with Hollywood and RapaGUI at your hands!


Show TOC