Using Inputs

Rich UI applications require of course some way of interacting with a user. This tutorial will show two of the basic ways of catching and handling user input in Disko.

To download the code for this tutorial, fetch it from the git-repository by issuing:

git clone git://www.diskohq.org/disko-tutorials.git

Then you can follow this part by having a look at the tutorials firststeps/05 folder.

Preface

Disko utilizes two essentially different ways of handling user input. The default way of handling user input is by the GUI component when item are pressed or some navigation from one item to another occurs. In this case an input is handed to the item that is currently selected, if the item is not able to handle the input, it is then handed over to the controlling window of the dialog which tries to use the input to navigate between different items it contains, if the input could not be handled it is finally discarded. The second way of handling inputs is to directly subscribe an input event to a specific callback. This will prevent the GUI to receive the input at all. As there are very different needs for different environments, Disko distinguishes between 2 fundamental input schemes. Settopbox application for insance are driven by a "keyboard only" approach of user inputs, a touchscreen terminals have no keyboard at all, and completely rely on touch input. Therefore we need to clarify 3 different terms: Input mode, Input subscription, Callback handling

Input mode

As mentioned above Disko distinguishes between two fundamental modes of operation when it comes to inputs. They can be set by a parameter in the applications configuration file diskorc.xml:.

<diskorc version="1.6.0">
    <global>
    	...
        <parameter name="inputmode"   value="CLICK"/> //or MOVE
        ...
    </global>
    ...
</diskorc>

MOVE

This is the default setting for the inputmode parameter. It is used for keyboard centric approaches. In this mode there is always a visibly selected item, which eases the navigation of the GUI for the user. There is always a consistent state as only one item can be selected at the same time. The default keys that are involved to that are the cursor keys and return.

CLICK

This setting is used for touch or mouse operation. In this mode there is no predefined selection visible on the screen, but any icon that is clicked on is briefly selected and the registered method is called by the GUI.

Try to play a bit with the setting in the diskorc.xml located in the firststeps/05 folder.

The resulting screens after the binary is started should look like this: move

As you can see in input mode MOVE the first item of the three item menu is selected and appears yellow all the time. In input mode CLICK there is no selection: move

Callback handling

Disko uses the sigc++ library for function callback handling. A dialog is typically constructed of one ore more widget that can be selected or pressed. There is a set of standard callbacks that are implemented as sigc++ signals which are emitted when the concerning action takes places. The one interesting for our example is the onReturn signal. This signal is emittable by each single widget that also can be selected either by the navigation or a direct click.

For the example a simple menu defintion was added to the theme.xml of the application (see firststeps/05/themes/default).

The dialog root.xml was extended to define a simple menu cotaining three elements:

<mainwindow w="100%" h="100%" margin="0" alignment="center"
            border.thickness="0" bgcolor="#00000000"
            bgimage="./vladstudio_xeroxplain_800x600_gray.png"
            opacity="255"<
<vbox>
    <menu class="default_menu" name="mymenu" >
        <menuitem widget.itemtext.text="Button 1"
                  widget.menubutton.data="Button Data 1" />
        <menuitem widget.itemtext.text="Button 2"
                  widget.menubutton.data="Button Data 2"/>
        <menuitem widget.itemtext.text="Button 3"
                  widget.menubutton.data="Button Data 3"/>
    </menu>
</vbox>
</mainwindow>

The labels for the items are set by the widget.itemtext.text attribute which corresponds to the menu item template in the theme.xml. The attribute widget.menubutton.data adds an identifier to the button that will be used in the application to distinguish between the different menuitems.

To load the dialog a dialog manager will be used. After the dialog is loaded, a pointer to the defined menu will be extracted from the window and the callback is assigned:

MMSWidget *wid = window->searchForWidget("mymenu");
wid->onReturn->connect(sigc::ptr_fun(onMenuReturn));

Giving an uniqe name to the widget is very important, to explicitly identify a widget within the dialog!

The callback looks as follows:

void onMenuReturn(MMSWidget *wid) {
    MMSMenuWidget *menu = dynamic_cast<MMSMenuWidget*>(wid);

    if(menu) {
        MMSWidget *button = menu->getSelectedItem();

        string widgetdata;
        if(button->getData(widgetdata)) {
            printf("Button pressed: %s\n", widgetdata.c_str());
        }
    }
}

This method extracts the selected menu item from the menu and prints the associated data string to stdout.

This is the basic principle of gui interaction there are other callbacks that could be connected like onClick or onSelectItem. The procedure is always the same.

Input subscription

The input subscription is utilzed when an input is not used or usable for screen interaction. The most obvious example would be the volume control of a device. This is somthing that is processed by a backend component rather than the GUI. Remember: this input bypasses the GUI compeletely!

An input is easily subscribed:

MMSInputSubscription subs(MMSKEY_SMALL_A);
subs.callback.connect(sigc::ptr_fun(onSubscription));
subs.registerMe();

This subscribes the key 'a' to the method onSubscription() which looks as follows:

void onSubscription(MMSInputSubscription *sub) {
    printf("subscribed key pressed...\n");
}

That should cover all basics that are needed to start using the inputs.