Tutorial

Customize The UI

To create your first application, we'll use the DefaultProject template that only contains a simple lobby room listing all users. So, first, start up your Eclipse and create a new Mupe project using the DefaultProject template (File->New->Project->Mupe->New Mupe Project).

new_project.png

select_template.png

As a very short introduction, in Mupe projects two folders are important:

  • src/com.nokia.mupe.server/
  • xml/content/

First one contains all java classes, second one all the xml UIs.

package_explorer.png

Now, finally to the actual topic: customizing the UI

By default, you'll see UI description file of Lobby object when you log into the service. It looks something like this:

lobby.png

And since we haven't changed any code, this is what we'll see too. So, we'll want to change the description file of Lobby. How?

Open the file xml/content/Lobby/description.xml and replace the contents with the following. Try to figure what does it do:

<canvas>
<string text='Hello World!' halign='center' width='100%' selectable='true'>
<on_select>
<quit />
</on_select>
</string>
<allowuserinput />
</canvas> 

When you now connect to the service, you'll see this:

lobby_modified.png

This example is really just a small glimpse of what you can do with the xml script, but to keep this tutorial short, let's move on to next stage, creating your own java class into Mupe.

Create Your Own Mupe Class

When we want to do more complicated things than just changing the looks of the UI of your Mupe application, you'll need to start coding in java. And when that happens, the first thing to do is to create a new Class into your project.

On this example, we'll create a new Room subclass:

  1. select com.nokia.mupe.server package on your Eclipse's view, under src/ folder
  2. press <Ctrl>N to open the New dialog
  3. choose MUPE->New Mupe Class and click Next
  4. give your class a name, for example MyRoom
  5. choose superclass, in this case Room (type the name of the class, use Browse, or type the first letters of the name and press Ctrl+Space)
  6. click Finish

new_class.png

Now you should see newly created src/com.nokia.mupe.server/MyRoom.java and xml/content/MyRoom/.

Having created a new class isn't enough yet, because the platform is still using Lobby objects by default when creating a new application. We want to change that, so open src/com.nokia.mupe.server/World.java for editing. From there, find method createDefaultRoom() and edit it to look like this:

public Room createDefaultRoom() throws MupeException {
return new MyRoom(null, null, "DefaultRoom"); 
}

Not a big change. If you wish, you can change the last parameter to anything you like. It's just the name given to this room and might be shown in some UI if your application uses names for places.

Since in previous stage we created a new UI for Lobby object and now we are no longer using Lobby, let's move that nice piece of UI to our new MyRoom instead. So, just move description.xml from xml/content/Lobby/ to xml/content/MyRoom/.

 

Note: If you have already started your server earlier to test it out, you have created a Lobby into the world and it won't be recreated even though we made this change to World.java. If that's the case, we need to get rid of the old created content by deleting the stored content files (content.dat & backup.dat). You can select the "restart and delete content" option from StartServer utility.

restart.png

 

That's all for creating a new class. Next topic is about writing java methods that can be called from the client.

Create Client Method

Mupe allows you to call java methods from the client side, over the network. But only very specific methods to keep things secure. On this step we'll go through making one.

On your MyRoom.java, add following piece of code

public String clientMyMethod(User caller, String name) {
return "<settext id='hello' text='Hello "+name+"!'/>"; 
}

Now this short piece of code contains a lot of stuff that's actually kind of important:

  • the method must be public
  • the method must return a String
  • the method name must begin with client
  • the first parameter must be User caller (ok, User subclasses are fine, and parameter name doesn't matter)
  • in addition to the first compulsory parameter, any number of other parameters can be relayed of all basic types (int, long, boolean, String), or even objects as long as they're derived from Base.

There's also a short piece of xml returned from this java method. What does it do? It changes a specific string object's text value on the UI.

Ok, so now we have a fancy java method. How about calling it then? Let's bring back our nice UI and modify it to look like this:

<canvas>
<string id='hello' text='Who are you?' halign='center' width='100%' />
<prompt id='name' anchor='top_left/bottom_left/hello' />
<button text='OK' anchor='center_left/center_right/name'>
<on_select>
<send>!#this#!::clientMyMethod {$(name.text)}</send>
</on_select>
</button>
<allowuserinput />
</canvas> 

Things just got more complicated. First, we added an id for the string object. Just to be able to refer to it later. We also removed the event handler of the string object to keep the example short. Two new items were added: a prompt (a field where the user can write text) and a button. They are positioned relative to each other using anchor attributes that we do not need to worry about. When the button is pressed, we take what is currently written in the prompt and send it to the server. This call may need a bit of explaining so let's take a closer look at it:

<send>!#this#!::clientMyMethod {$(name.text)}</send>
  • send is the xml tag that sends stuff over the network to the server
  • !#this#! is a special marker replaced by a server side ID number of this object (in this case, MyRoom)
  • clientMyMethod is exactly the same name as we have in java code
  • we're sending one parameter, to which we insert a value from variable name.text

But that doesn't quite match, our java method had two parameters! Yep. The first parameter is compulsory because system adds it to every call automatically. And because it's added automatically, your call always has one less parameter than the receiving method in java.

If you now restart the server (no need to delete content.dat or backup.dat) and connect with a client, you'll see this:

myroom1.png

When you type something into the field and press the OK button, the text at the top should change:

myroom2.png

Java To Xml

It's a pretty bad habit to write xml directly into java code. And we just did it. So blame me for teaching you bad habits. Anyway, before you get too used to it, let's fix the situation and separate xml into its own file. First, change the java method into this:

public String clientMyMethod(User caller, String name) throws MupeException {
return getDynamicXML("update_hello.xml", caller, name); 
}

And then create new xml file /xml/content/MyRoom/update_hello.xml with following content:

<settext id='hello' text='Hello !#param0#!!'/>

So what happened here? First, in java, we access the xml file giving it two parameters. Caller is given always for security and other reasons, but the name we give is an actual content parameter we can insert directly into the xml. And if you look at the xml, !#param0#! is what gets replaced by the contents of name. That's all there was to it. Try to remember this next time you get the urge of writing xml directly into java code :)

Anyway, you're done with the tutorial. I hope you've understood everything we did here. And if you didn't, don't feel bad about it but instead send us feedback, because it's completely our fault if this tutorial wasn't understandable and easy enough.