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!