Documentation/Maemo 5 Developer Guide/Porting Software/Migration

m (Migration)
(reformat images, add __FORCETOC__)
 
(2 intermediate revisions not shown)
Line 1: Line 1:
-
=Migration to Hildon 2.2=
 
Because Hildon 2.2 is a big step up from previous versions, many approaches in the development of your program's graphical user interface may need to be migrated to this new interface type.
Because Hildon 2.2 is a big step up from previous versions, many approaches in the development of your program's graphical user interface may need to be migrated to this new interface type.
 +
__FORCETOC__
== Menus ==
== Menus ==
-
Hildon app menu represents a big difference from the normal menus. If your application is to be finger-friendly, a view specific menu, instead of application menu, is mandatory.
+
 
 +
<code>HildonAppMenu</code> represents a big difference from the normal menus. If your application is to be finger-friendly, a view specific menu, instead of application menu, is mandatory.
The Maemo 4 application menu typically contains most or the full set of functionality of the application, organized in hierarchical menus.
The Maemo 4 application menu typically contains most or the full set of functionality of the application, organized in hierarchical menus.
-
In Maemo 5, there is a strict limit of maximum 10 items in a view menu, and there is no menu hierarchy.
+
In Maemo 5, there is a strict maximum limit 10 items in a view menu, and there is no menu hierarchy.
The Maemo 5 View menus are not application menus, in the sense that a view menu only contains commands relevant to that particular view. The only exception to this is the Root view menu, which additionally contains menu item(s) for application settings.
The Maemo 5 View menus are not application menus, in the sense that a view menu only contains commands relevant to that particular view. The only exception to this is the Root view menu, which additionally contains menu item(s) for application settings.
-
Because also the view menu uses buttons, you can easily add them with the callback functions that the original menu items had.
+
Because the view menu also uses buttons, you can easily add them with the callback functions that the original menu items had.
-
For example, consider an advanced text edition program. The original menu bar had the following menus:
+
For example, consider an advanced text editing program. The original menu bar had the following menus:
'''Example 10.1. Menu example'''
'''Example 10.1. Menu example'''
-
<div class="graybox">
+
<pre>
-
 
+
File
-
File
+
    \ New
-
    \ New
+
    \ Open
-
    \ Open
+
    \ Save
-
    \ Save
+
    \ Save As
-
    \ Save As
+
    \ Quit
-
    \ Quit
+
Edit
-
Edit
+
    \ Copy
-
    \ Copy
+
    \ Paste
-
    \ Paste
+
    \ Cut
-
    \ Cut
+
    \ Indent Type
-
    \ Indent Type
+
        \ Tabs
-
        \ Tabs
+
        \ Spaces
-
        \ Spaces
+
    \ Preferences
-
    \ Preferences
+
View
-
View
+
    \ Zoom In
-
    \ Zoom In
+
    \ Zoom Out
-
    \ Zoom Out
+
    \ Normal Size
-
    \ Normal Size
+
    \ Highlight
-
    \ Highlight
+
        \ C
-
        \ C
+
        \ Python
-
        \ Python
+
        \ JAVA
-
        \ JAVA
+
Help
-
Help
+
    \ Contents
-
    \ Contents
+
    \ About
-
    \ About
+
</pre>
-
 
+
-
</div>
+
Guidelines:
Guidelines:
Line 53: Line 52:
* Additional menu commands can be made accessible via dialogs opened from the view menu, if those commands cannot be presented directly in the UI or simply removed.
* Additional menu commands can be made accessible via dialogs opened from the view menu, if those commands cannot be presented directly in the UI or simply removed.
-
A text editor does not need subviews, so more or less all commands need to fit in a single view. See [[Documentation/Maemo_5_Developer_Guide/Human_Interface_Guidelines/Redesigning_From_Maemo_4_to_Maemo_5 | Redesigning From Maemo 4 to Maemo 5]] for details about sub view redesign.
+
A text editor does not need subviews, so more or less all commands need to fit in a single view. See [[Documentation/Maemo 5 Developer Guide/Human Interface Guidelines/Redesigning From Maemo 4 to Maemo 5|Redesigning From Maemo 4 to Maemo 5]] for details about sub view redesign.
Changes:
Changes:
Line 64: Line 63:
The following example shows the implementation of the menu following the above decisions. The first figure below shows the final result of the app menu. The other showd the dialog activated by the menu command "Settings".
The following example shows the implementation of the menu following the above decisions. The first figure below shows the final result of the app menu. The other showd the dialog activated by the menu command "Settings".
-
[[Image:example-migrating-menu1.png|400px]]
+
[[Image:example-migrating-menu1.png|frame|center|alt=Screenshot of a HildonAppMenu|HildonAppMenu example]]
   
   
-
[[Image:example-migrating-menu-view.png|400px]]  
+
[[Image:example-migrating-menu-view.png|frame|center|alt=Screenshot of the settings dialog|Settings dialog example]]  
'''Example 10.2. Migrating a menu'''
'''Example 10.2. Migrating a menu'''
-
#include <hildon/hildon.h>
+
<source lang="c">
-
#include <libintl.h>
+
#include <hildon/hildon.h>
-
+
#include <libintl.h>
-
static void
+
 
-
menu_settings_cb (GtkButton *widget, gpointer data)
+
static void
-
{
+
menu_settings_cb (GtkButton *widget, gpointer data)
-
    /* Code to set show settings dialog... */
+
{
-
    g_assert(data);
+
  /* Code to set show settings dialog... */
-
    GtkDialog *dialog = GTK_DIALOG(
+
  g_assert(data);
-
      gtk_dialog_new_with_buttons("Settings",
+
  GtkDialog *dialog = GTK_DIALOG(
-
                                  GTK_WINDOW(data),
+
      gtk_dialog_new_with_buttons("Settings",
-
                                  GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+
                                  GTK_WINDOW(data),
-
                                  dgettext("hildon-libs", "wdgt_bd_save"),
+
                                  GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
-
                                  GTK_RESPONSE_OK,
+
                                  dgettext("hildon-libs", "wdgt_bd_save"),
-
                                  NULL));
+
                                  GTK_RESPONSE_OK,
-
    gint response = 0;
+
                                  NULL));
-
    GtkSizeGroup *titlegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+
  gint response = 0;
-
    GtkSizeGroup *valuegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+
  GtkSizeGroup *titlegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
-
 
+
  GtkSizeGroup *valuegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
-
    /* Syntax highlight */
+
 
-
    GtkWidget *syntax_selector = hildon_touch_selector_new_text ();
+
  /* Syntax highlight */
-
    hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (syntax_selector), "C");
+
  GtkWidget *syntax_selector = hildon_touch_selector_new_text ();
-
    hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (syntax_selector), "JAVA");
+
  hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (syntax_selector), "C");
-
    hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (syntax_selector), "Python");
+
  hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (syntax_selector), "JAVA");
-
    GtkWidget *syntax_picker = hildon_picker_button_new (HILDON_SIZE_THUMB_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
+
  hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (syntax_selector), "Python");
-
                                                        HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
+
  GtkWidget *syntax_picker = hildon_picker_button_new (HILDON_SIZE_THUMB_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
-
    hildon_button_set_title (HILDON_BUTTON (syntax_picker), "Syntax highlight");
+
                                                        HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
-
    hildon_picker_button_set_selector (HILDON_PICKER_BUTTON(syntax_picker),
+
  hildon_button_set_title (HILDON_BUTTON (syntax_picker), "Syntax highlight");
-
                                      HILDON_TOUCH_SELECTOR(syntax_selector));
+
  hildon_picker_button_set_selector (HILDON_PICKER_BUTTON(syntax_picker),
-
    hildon_picker_button_set_active (HILDON_PICKER_BUTTON(syntax_picker), 0);
+
                                      HILDON_TOUCH_SELECTOR(syntax_selector));
-
   
+
  hildon_picker_button_set_active (HILDON_PICKER_BUTTON(syntax_picker), 0);
-
    gtk_button_set_alignment (GTK_BUTTON (syntax_picker), 0.0, 0.5);
+
 
-
    hildon_button_add_size_groups (HILDON_BUTTON (syntax_picker), titlegroup, valuegroup, NULL);
+
  gtk_button_set_alignment (GTK_BUTTON (syntax_picker), 0.0, 0.5);
-
    gtk_container_add (GTK_CONTAINER (dialog->vbox), syntax_picker);
+
  hildon_button_add_size_groups (HILDON_BUTTON (syntax_picker), titlegroup, valuegroup, NULL);
-
   
+
  gtk_container_add (GTK_CONTAINER (dialog->vbox), syntax_picker);
-
    /* Indent type */
+
 
-
    GtkWidget *indent_selector = hildon_touch_selector_new_text ();
+
  /* Indent type */
-
    hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (indent_selector), "Tabs");
+
  GtkWidget *indent_selector = hildon_touch_selector_new_text ();
-
    hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (indent_selector), "Spaces");
+
  hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (indent_selector), "Tabs");
-
    GtkWidget *indent_picker = hildon_picker_button_new (HILDON_SIZE_THUMB_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
+
  hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (indent_selector), "Spaces");
-
                                                        HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
+
  GtkWidget *indent_picker = hildon_picker_button_new (HILDON_SIZE_THUMB_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
-
    hildon_button_set_title (HILDON_BUTTON (indent_picker), "Indent type");
+
                                                        HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
-
    hildon_picker_button_set_selector (HILDON_PICKER_BUTTON(indent_picker),  
+
  hildon_button_set_title (HILDON_BUTTON (indent_picker), "Indent type");
-
                                      HILDON_TOUCH_SELECTOR(indent_selector));
+
  hildon_picker_button_set_selector (HILDON_PICKER_BUTTON(indent_picker),  
-
    hildon_picker_button_set_active (HILDON_PICKER_BUTTON(indent_picker), 0);
+
                                      HILDON_TOUCH_SELECTOR(indent_selector));
-
   
+
  hildon_picker_button_set_active (HILDON_PICKER_BUTTON(indent_picker), 0);
-
    gtk_button_set_alignment (GTK_BUTTON (indent_picker), 0.0, 0.5);
+
 
-
    hildon_button_add_size_groups (HILDON_BUTTON (indent_picker), titlegroup, valuegroup, NULL);
+
  gtk_button_set_alignment (GTK_BUTTON (indent_picker), 0.0, 0.5);
-
    gtk_container_add (GTK_CONTAINER (dialog->vbox), indent_picker);
+
  hildon_button_add_size_groups (HILDON_BUTTON (indent_picker), titlegroup, valuegroup, NULL);
-
   
+
  gtk_container_add (GTK_CONTAINER (dialog->vbox), indent_picker);
-
    gtk_widget_show_all (GTK_WIDGET (dialog));
+
 
-
   
+
  gtk_widget_show_all (GTK_WIDGET (dialog));
-
    response = gtk_dialog_run(dialog);
+
 
-
    if (response == GTK_RESPONSE_OK) {   
+
  response = gtk_dialog_run(dialog);
-
        /* "Save" button has been pressed, save/update the settings here */
+
  if (response == GTK_RESPONSE_OK) {   
-
       
+
      /* "Save" button has been pressed, save/update the settings here */
-
        /* ... */
+
 
-
    }
+
      /* ... */
-
   
+
  }
-
    /* close the dialog */
+
 
-
    gtk_widget_destroy(GTK_WIDGET(dialog));
+
  /* close the dialog */
-
}
+
  gtk_widget_destroy(GTK_WIDGET(dialog));
-
+
}
-
+
 
-
+
static HildonAppMenu *
-
static HildonAppMenu *
+
build_menu (GtkWidget *window)
-
build_menu (GtkWidget *window)
+
{
-
{
+
  HildonSizeType button_size = HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH;
-
    HildonSizeType button_size = HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH;
+
  HildonAppMenu *menu = HILDON_APP_MENU (hildon_app_menu_new ());
-
    HildonAppMenu *menu = HILDON_APP_MENU (hildon_app_menu_new ());
+
  GtkButton *button;
-
    GtkButton *button;
+
 
-
 
+
  /* Menus like New, Open, etc that would open new dialogs (no submenus)
-
    /* Menus like New, Open, etc that would open new dialogs (no submenus)
+
    * are not assigned any action in this example
-
    * are not assigned any action in this example
+
    */
-
    */
+
 
-
+
  button = GTK_BUTTON (hildon_gtk_button_new (button_size));
-
    button = GTK_BUTTON (hildon_gtk_button_new (button_size));
+
  gtk_button_set_label (button, "New");
-
    gtk_button_set_label (button, "New");
+
  hildon_app_menu_append (menu, GTK_BUTTON (button));
-
    hildon_app_menu_append (menu, GTK_BUTTON (button));
+
 
-
+
  button = GTK_BUTTON (hildon_gtk_button_new (button_size));
-
    button = GTK_BUTTON (hildon_gtk_button_new (button_size));
+
  gtk_button_set_label (button, "Open");
-
    gtk_button_set_label (button, "Open");
+
  hildon_app_menu_append (menu, GTK_BUTTON (button));
-
    hildon_app_menu_append (menu, GTK_BUTTON (button));
+
 
-
+
  button = GTK_BUTTON (hildon_gtk_button_new (button_size));
-
    button = GTK_BUTTON (hildon_gtk_button_new (button_size));
+
  gtk_button_set_label (button, "Save");
-
    gtk_button_set_label (button, "Save");
+
  hildon_app_menu_append (menu, GTK_BUTTON (button));
-
    hildon_app_menu_append (menu, GTK_BUTTON (button));
+
 
-
+
  button = GTK_BUTTON (hildon_gtk_button_new (button_size));
-
    button = GTK_BUTTON (hildon_gtk_button_new (button_size));
+
  gtk_button_set_label (button, "Settings");
-
    gtk_button_set_label (button, "Settings");
+
  g_signal_connect (G_OBJECT (button), "clicked",
-
    g_signal_connect (G_OBJECT (button), "clicked",
+
                    G_CALLBACK (menu_settings_cb), window);
-
                      G_CALLBACK (menu_settings_cb), window);
+
  hildon_app_menu_append (menu, GTK_BUTTON (button));
-
    hildon_app_menu_append (menu, GTK_BUTTON (button));
+
 
-
+
  gtk_widget_show_all (GTK_WIDGET (menu));
-
    gtk_widget_show_all (GTK_WIDGET (menu));
+
 
-
+
  return menu;
-
    return menu;
+
}
-
}
+
 
-
+
int
-
int
+
main (int argc, char **argv)
-
main (int argc, char **argv)
+
{
-
{
+
  hildon_gtk_init (&argc, &argv);
-
    hildon_gtk_init (&argc, &argv);
+
 
-
+
  GtkWidget *window;
-
    GtkWidget *window;
+
  window = hildon_stackable_window_new ();
-
    window = hildon_stackable_window_new ();
+
  gtk_window_set_title (GTK_WINDOW (window), "Editor");
-
    gtk_window_set_title (GTK_WINDOW (window), "Editor");
+
 
-
+
  HildonAppMenu *menu = build_menu (window);
-
    HildonAppMenu *menu = build_menu (window);
+
  hildon_window_set_app_menu (HILDON_WINDOW (window),    menu);
-
    hildon_window_set_app_menu (HILDON_WINDOW (window),    menu);
+
 
-
+
  GtkWidget *contents = gtk_label_new ("This example shows how an app menu could be "\
-
    GtkWidget *contents = gtk_label_new ("This example shows how an app menu could be "\
+
                                        "migrated.\nMenu item callbacks "\
-
                                        "migrated.\nMenu item callbacks "\
+
                                        "are not fully implemented.");
-
                                        "are not fully implemented.");
+
  gtk_container_add (GTK_CONTAINER (window), contents);
-
    gtk_container_add (GTK_CONTAINER (window), contents);
+
 
-
+
  /* ... other widgets in the application */
-
    /* ... other widgets in the application */
+
 
-
+
  g_signal_connect (G_OBJECT (window), "destroy",
-
    g_signal_connect (G_OBJECT (window), "destroy",
+
                    G_CALLBACK (gtk_main_quit), NULL);
-
                      G_CALLBACK (gtk_main_quit), NULL);
+
 
-
+
  gtk_widget_show_all (window);
-
    gtk_widget_show_all (window);
+
 
-
+
  gtk_main ();
-
    gtk_main ();
+
  return 0;
-
    return 0;
+
}
-
}
+
</source>
==Choices ==
==Choices ==
 +
Some widgets for choosing options also need to be adapted to the new Hildon way of designing interfaces. If you have several radio buttons to express a choice, replacing them with a picker button is a good idea.
Some widgets for choosing options also need to be adapted to the new Hildon way of designing interfaces. If you have several radio buttons to express a choice, replacing them with a picker button is a good idea.
Consider a dialog that includes, among other widgets, a frame labeled "Proxy Preferences" and three radio buttons: "None", "Auto" and "Manual", displayed vertically like Figure 10.1 "Three radio buttons" shows. The following example shows how such task could be accomplished using a picker button. The frame label becomes the picker button's title and the three radio buttons' labels become the choices in the picker's touch selector. The screenshot below shows  the resulting graphical user interface.
Consider a dialog that includes, among other widgets, a frame labeled "Proxy Preferences" and three radio buttons: "None", "Auto" and "Manual", displayed vertically like Figure 10.1 "Three radio buttons" shows. The following example shows how such task could be accomplished using a picker button. The frame label becomes the picker button's title and the three radio buttons' labels become the choices in the picker's touch selector. The screenshot below shows  the resulting graphical user interface.
-
[[Image:choices.png|Image choices|400px]]
+
[[Image:choices.png|frame|center|alt=Screenshot of a picker button dialog|Example of choices in a picker button]]
'''Example 10.3. Migrating choice widgets'''
'''Example 10.3. Migrating choice widgets'''
-
<tt><span>'''<span><font color="#000080"><nowiki>#include</nowiki></font></span>'''</span> <span><font color="#FF0000">&lt;hildon/hildon.h&gt;</font></span>
+
<source lang="c">
-
<span><font color="#009900">int</font></span>
+
#include <hildon/hildon.h>
-
<span>'''<span><font color="#000000">main</font></span>'''</span> <span><font color="#990000">(</font></span><span><font color="#009900">int</font></span> argc<span><font color="#990000">,</font></span> <span><font color="#009900">char</font></span> <span><font color="#990000"><nowiki>**</nowiki></font></span>argv<span><font color="#990000">)</font></span>
+
int
-
<span><font color="#FF0000">{</font></span>
+
main (int argc, char **argv)
-
    <span>'''<span><font color="#000000">hildon_gtk_init</font></span>'''</span> <span><font color="#990000">(&amp;</font></span>argc<span><font color="#990000">,</font></span> <span><font color="#990000">&amp;</font></span>argv<span><font color="#990000">);</font></span>
+
{
-
    GtkWidget <span><font color="#990000"><nowiki>*</nowiki></font></span>window<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
    hildon_gtk_init (&argc, &argv);
-
    window <span><font color="#990000"><nowiki>=</nowiki></font></span> <span>'''<span><font color="#000000">hildon_window_new</font></span>'''</span> <span><font color="#990000">();</font></span>
+
    GtkWidget *window;
-
    <span>'''<span><font color="#000000">gtk_window_set_title</font></span>'''</span> <span><font color="#990000">(</font></span><span>'''<span><font color="#000000">GTK_WINDOW</font></span>'''</span> <span><font color="#990000">(</font></span>window<span><font color="#990000">),</font></span> <span><font color="#FF0000">"Preferences"</font></span><span><font color="#990000">);</font></span>
+
    window = hildon_window_new ();
-
    <span>'''<span><font color="#000000">g_signal_connect</font></span>'''</span> <span><font color="#990000">(</font></span><span>'''<span><font color="#000000">G_OBJECT</font></span>'''</span> <span><font color="#990000">(</font></span>window<span><font color="#990000">),</font></span> <span><font color="#FF0000">"destroy"</font></span><span><font color="#990000">,</font></span>
+
    gtk_window_set_title (GTK_WINDOW (window), "Preferences");
-
                      <span>'''<span><font color="#000000">G_CALLBACK</font></span>'''</span> <span><font color="#990000">(</font></span>gtk_main_quit<span><font color="#990000">),</font></span> NULL<span><font color="#990000">);</font></span>
+
    g_signal_connect (G_OBJECT (window), "destroy",
-
    HildonPickerButton <span><font color="#990000"><nowiki>*</nowiki></font></span>picker <span><font color="#990000"><nowiki>=</nowiki></font></span> <span>'''<span><font color="#000000">HILDON_PICKER_BUTTON</font></span>'''</span> <span><font color="#990000">(</font></span><span>'''<span><font color="#000000">hildon_picker_button_new</font></span>'''</span> <span><font color="#990000">(</font></span>
+
                      G_CALLBACK (gtk_main_quit), NULL);
-
                            HILDON_SIZE_THUMB_HEIGHT <span><font color="#990000"><nowiki>|</nowiki></font></span> HILDON_SIZE_HALFSCREEN_WIDTH<span><font color="#990000">,</font></span>
+
    HildonPickerButton *picker = HILDON_PICKER_BUTTON (hildon_picker_button_new (
-
                                                HILDON_BUTTON_ARRANGEMENT_VERTICAL<span><font color="#990000">));</font></span>
+
                            HILDON_SIZE_THUMB_HEIGHT | HILDON_SIZE_HALFSCREEN_WIDTH,
-
    <span>'''<span><font color="#000000">hildon_button_set_title</font></span>'''</span> <span><font color="#990000">(</font></span><span>'''<span><font color="#000000">HILDON_BUTTON</font></span>'''</span> <span><font color="#990000">(</font></span>picker<span><font color="#990000">),</font></span> <span><font color="#FF0000">"Proxy preferences:"</font></span><span><font color="#990000">);</font></span>
+
                                                HILDON_BUTTON_ARRANGEMENT_VERTICAL));
-
    HildonTouchSelector <span><font color="#990000"><nowiki>*</nowiki></font></span>selector <span><font color="#990000"><nowiki>=</nowiki></font></span> <span>'''<span><font color="#000000">HILDON_TOUCH_SELECTOR</font></span>'''</span> <span><font color="#990000">(</font></span><span>'''<span><font color="#000000">hildon_touch_selector_new_text</font></span>'''</span> <span><font color="#990000">());</font></span>
+
    hildon_button_set_title (HILDON_BUTTON (picker), "Proxy preferences:");
-
    <span>'''<span><font color="#000000">hildon_picker_button_set_selector</font></span>'''</span> <span><font color="#990000">(</font></span>picker<span><font color="#990000">,</font></span> selector<span><font color="#990000">);</font></span>
+
    HildonTouchSelector *selector = HILDON_TOUCH_SELECTOR (hildon_touch_selector_new_text ());
-
    <span>'''<span><font color="#000000">hildon_touch_selector_append_text</font></span>'''</span> <span><font color="#990000">(</font></span>selector<span><font color="#990000">,</font></span> <span><font color="#FF0000">"None"</font></span><span><font color="#990000">);</font></span>
+
    hildon_picker_button_set_selector (picker, selector);
-
    <span>'''<span><font color="#000000">hildon_touch_selector_append_text</font></span>'''</span> <span><font color="#990000">(</font></span>selector<span><font color="#990000">,</font></span> <span><font color="#FF0000">"Auto"</font></span><span><font color="#990000">);</font></span>
+
    hildon_touch_selector_append_text (selector, "None");
-
    <span>'''<span><font color="#000000">hildon_touch_selector_append_text</font></span>'''</span> <span><font color="#990000">(</font></span>selector<span><font color="#990000">,</font></span> <span><font color="#FF0000">"Manual"</font></span><span><font color="#990000">);</font></span>
+
    hildon_touch_selector_append_text (selector, "Auto");
-
    <span>'''<span><font color="#000000">hildon_picker_button_set_active</font></span>'''</span> <span><font color="#990000">(</font></span>picker<span><font color="#990000">,</font></span> <span><font color="#993399">0</font></span><span><font color="#990000">);</font></span>
+
    hildon_touch_selector_append_text (selector, "Manual");
-
    GtkVBox <span><font color="#990000"><nowiki>*</nowiki></font></span>contents <span><font color="#990000"><nowiki>=</nowiki></font></span> <span>'''<span><font color="#000000">GTK_VBOX</font></span>'''</span> <span><font color="#990000">(</font></span><span>'''<span><font color="#000000">gtk_vbox_new</font></span>'''</span> <span><font color="#990000">(</font></span><span><font color="#993399">12</font></span><span><font color="#990000">,</font></span> FALSE<span><font color="#990000">));</font></span>
+
    hildon_picker_button_set_active (picker, 0);
-
    <span>''<span><font color="#9A1900">/* ... other widgets placed here */</font></span>''</span>
+
    GtkVBox *contents = GTK_VBOX (gtk_vbox_new (12, FALSE));
-
    <span>'''<span><font color="#000000">gtk_box_pack_end</font></span>'''</span> <span><font color="#990000">(</font></span><span>'''<span><font color="#000000">GTK_BOX</font></span>'''</span> <span><font color="#990000">(</font></span>contents<span><font color="#990000">),</font></span> <span>'''<span><font color="#000000">GTK_WIDGET</font></span>'''</span> <span><font color="#990000">(</font></span>picker<span><font color="#990000">),</font></span> FALSE<span><font color="#990000">,</font></span> FALSE<span><font color="#990000">,</font></span> <span><font color="#993399">0</font></span><span><font color="#990000">);</font></span>
+
    /* ... other widgets placed here */
-
    <span>'''<span><font color="#000000">gtk_container_add</font></span>'''</span> <span><font color="#990000">(</font></span><span>'''<span><font color="#000000">GTK_CONTAINER</font></span>'''</span> <span><font color="#990000">(</font></span>window<span><font color="#990000">),</font></span> <span>'''<span><font color="#000000">GTK_WIDGET</font></span>'''</span> <span><font color="#990000">(</font></span>contents<span><font color="#990000">));</font></span>
+
    gtk_box_pack_end (GTK_BOX (contents), GTK_WIDGET (picker), FALSE, FALSE, 0);
-
    <span>'''<span><font color="#000000">gtk_widget_show_all</font></span>'''</span> <span><font color="#990000">(</font></span>window<span><font color="#990000">);</font></span>
+
    gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (contents));
-
    <span>'''<span><font color="#000000">gtk_main</font></span>'''</span> <span><font color="#990000">();</font></span>
+
    gtk_widget_show_all (window);
-
    <span>'''<span><font color="#0000FF">return</font></span>'''</span> <span><font color="#993399">0</font></span><span><font color="#990000"><nowiki>;</nowiki></font></span>
+
    gtk_main ();
-
<span><font color="#FF0000">}</font></span>
+
    return 0;
-
</tt>
+
}
-
 
+
</source>
==Notebooks ==
==Notebooks ==
-
Because the use of notebooks is not advised in Hildon, the way to migrate a Maemo 4 dialog with notebook to Maemo 5, is to simply put all the items inside a single pannable dialog.
+
 
 +
Because the use of notebooks is not advised in Hildon, the way to migrate a Maemo 4 dialog with a notebook to Maemo 5, is to simply put all the items inside a single pannable dialog.
 +
 
 +
[[Category:Development]]
 +
[[Category:Documentation]]
 +
[[Category:Fremantle]]

Latest revision as of 09:31, 18 August 2010

Because Hildon 2.2 is a big step up from previous versions, many approaches in the development of your program's graphical user interface may need to be migrated to this new interface type.


Contents

[edit] Menus

HildonAppMenu represents a big difference from the normal menus. If your application is to be finger-friendly, a view specific menu, instead of application menu, is mandatory.

The Maemo 4 application menu typically contains most or the full set of functionality of the application, organized in hierarchical menus.

In Maemo 5, there is a strict maximum limit 10 items in a view menu, and there is no menu hierarchy.

The Maemo 5 View menus are not application menus, in the sense that a view menu only contains commands relevant to that particular view. The only exception to this is the Root view menu, which additionally contains menu item(s) for application settings.

Because the view menu also uses buttons, you can easily add them with the callback functions that the original menu items had.

For example, consider an advanced text editing program. The original menu bar had the following menus:

Example 10.1. Menu example

File
    \ New
    \ Open
    \ Save
    \ Save As
    \ Quit
Edit
    \ Copy
    \ Paste
    \ Cut
    \ Indent Type
        \ Tabs
        \ Spaces
    \ Preferences
View
    \ Zoom In
    \ Zoom Out
    \ Normal Size
    \ Highlight
        \ C
        \ Python
        \ JAVA
Help
    \ Contents
    \ About

Guidelines:

  • In general, commands are specific to their view
  • The initial view (root view) is the only access point to application settings
  • Additional menu commands can be made accessible via dialogs opened from the view menu, if those commands cannot be presented directly in the UI or simply removed.

A text editor does not need subviews, so more or less all commands need to fit in a single view. See Redesigning From Maemo 4 to Maemo 5 for details about sub view redesign.

Changes:

  • File menu commands: keep "New", "Open" and "Save". Remove "Save as" and "Quit". The "Save" command can function as "Save as" in cases where the source file is read only or the folder is no longer accessible.
    • NOTE: the document should be automatically saved (and re-opened) whenever the application is closed (or re-opened). There is no need to show any confirmation notes for this process.
  • Edit menu commands: remove "Cut/Copy/Paste", those should be used with keyboard shortcuts. Put all the rest inside "Preferences" dialog and rename it to "Settings"
  • View menu commands: "Zoom" in a text editor is not very useful so remove it (for changing the font size, simply HW +/- keys would be enough). Put "Highlight mode" in to "Settings".
  • Help menu commands: Remove help. It's not part of the Hildon 2.2 UI Style.

The following example shows the implementation of the menu following the above decisions. The first figure below shows the final result of the app menu. The other showd the dialog activated by the menu command "Settings".

Screenshot of a HildonAppMenu
HildonAppMenu example


Screenshot of the settings dialog
Settings dialog example


Example 10.2. Migrating a menu

#include <hildon/hildon.h>
#include <libintl.h>
 
static void
menu_settings_cb (GtkButton *widget, gpointer data)
{
   /* Code to set show settings dialog... */
   g_assert(data);
   GtkDialog *dialog = GTK_DIALOG(
      gtk_dialog_new_with_buttons("Settings",
                                  GTK_WINDOW(data),
                                  GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                  dgettext("hildon-libs", "wdgt_bd_save"),
                                  GTK_RESPONSE_OK,
                                  NULL));
   gint response = 0;
   GtkSizeGroup *titlegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
   GtkSizeGroup *valuegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
 
   /* Syntax highlight */
   GtkWidget *syntax_selector = hildon_touch_selector_new_text ();
   hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (syntax_selector), "C");
   hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (syntax_selector), "JAVA");
   hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (syntax_selector), "Python");
   GtkWidget *syntax_picker = hildon_picker_button_new (HILDON_SIZE_THUMB_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
                                                        HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
   hildon_button_set_title (HILDON_BUTTON (syntax_picker), "Syntax highlight");
   hildon_picker_button_set_selector (HILDON_PICKER_BUTTON(syntax_picker),
                                      HILDON_TOUCH_SELECTOR(syntax_selector));
   hildon_picker_button_set_active (HILDON_PICKER_BUTTON(syntax_picker), 0);
 
   gtk_button_set_alignment (GTK_BUTTON (syntax_picker), 0.0, 0.5);
   hildon_button_add_size_groups (HILDON_BUTTON (syntax_picker), titlegroup, valuegroup, NULL);
   gtk_container_add (GTK_CONTAINER (dialog->vbox), syntax_picker);
 
   /* Indent type */
   GtkWidget *indent_selector = hildon_touch_selector_new_text ();
   hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (indent_selector), "Tabs");
   hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (indent_selector), "Spaces");
   GtkWidget *indent_picker = hildon_picker_button_new (HILDON_SIZE_THUMB_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
                                                        HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
   hildon_button_set_title (HILDON_BUTTON (indent_picker), "Indent type");
   hildon_picker_button_set_selector (HILDON_PICKER_BUTTON(indent_picker), 
                                      HILDON_TOUCH_SELECTOR(indent_selector));
   hildon_picker_button_set_active (HILDON_PICKER_BUTTON(indent_picker), 0);
 
   gtk_button_set_alignment (GTK_BUTTON (indent_picker), 0.0, 0.5);
   hildon_button_add_size_groups (HILDON_BUTTON (indent_picker), titlegroup, valuegroup, NULL);
   gtk_container_add (GTK_CONTAINER (dialog->vbox), indent_picker);
 
   gtk_widget_show_all (GTK_WIDGET (dialog));
 
   response = gtk_dialog_run(dialog);
   if (response == GTK_RESPONSE_OK) {   
       /* "Save" button has been pressed, save/update the settings here */
 
       /* ... */
   }
 
   /* close the dialog */
   gtk_widget_destroy(GTK_WIDGET(dialog));
}
 
static HildonAppMenu *
build_menu (GtkWidget *window)
{
   HildonSizeType button_size = HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH;
   HildonAppMenu *menu = HILDON_APP_MENU (hildon_app_menu_new ());
   GtkButton *button;
 
   /* Menus like New, Open, etc that would open new dialogs (no submenus)
    * are not assigned any action in this example
    */
 
   button = GTK_BUTTON (hildon_gtk_button_new (button_size));
   gtk_button_set_label (button, "New");
   hildon_app_menu_append (menu, GTK_BUTTON (button));
 
   button = GTK_BUTTON (hildon_gtk_button_new (button_size));
   gtk_button_set_label (button, "Open");
   hildon_app_menu_append (menu, GTK_BUTTON (button));
 
   button = GTK_BUTTON (hildon_gtk_button_new (button_size));
   gtk_button_set_label (button, "Save");
   hildon_app_menu_append (menu, GTK_BUTTON (button));
 
   button = GTK_BUTTON (hildon_gtk_button_new (button_size));
   gtk_button_set_label (button, "Settings");
   g_signal_connect (G_OBJECT (button), "clicked",
                     G_CALLBACK (menu_settings_cb), window);
   hildon_app_menu_append (menu, GTK_BUTTON (button));
 
   gtk_widget_show_all (GTK_WIDGET (menu));
 
   return menu;
}
 
int
main (int argc, char **argv)
{
   hildon_gtk_init (&argc, &argv);
 
   GtkWidget *window;
   window = hildon_stackable_window_new ();
   gtk_window_set_title (GTK_WINDOW (window), "Editor");
 
   HildonAppMenu *menu = build_menu (window);
   hildon_window_set_app_menu (HILDON_WINDOW (window),     menu);
 
   GtkWidget *contents = gtk_label_new ("This example shows how an app menu could be "\
                                        "migrated.\nMenu item callbacks "\
                                        "are not fully implemented.");
   gtk_container_add (GTK_CONTAINER (window), contents);
 
   /* ... other widgets in the application */
 
   g_signal_connect (G_OBJECT (window), "destroy",
                     G_CALLBACK (gtk_main_quit), NULL);
 
   gtk_widget_show_all (window);
 
   gtk_main ();
   return 0;
}

[edit] Choices

Some widgets for choosing options also need to be adapted to the new Hildon way of designing interfaces. If you have several radio buttons to express a choice, replacing them with a picker button is a good idea.

Consider a dialog that includes, among other widgets, a frame labeled "Proxy Preferences" and three radio buttons: "None", "Auto" and "Manual", displayed vertically like Figure 10.1 "Three radio buttons" shows. The following example shows how such task could be accomplished using a picker button. The frame label becomes the picker button's title and the three radio buttons' labels become the choices in the picker's touch selector. The screenshot below shows the resulting graphical user interface.

Screenshot of a picker button dialog
Example of choices in a picker button

Example 10.3. Migrating choice widgets

#include <hildon/hildon.h>
int
main (int argc, char **argv)
{
    hildon_gtk_init (&argc, &argv);
    GtkWidget *window;
    window = hildon_window_new ();
    gtk_window_set_title (GTK_WINDOW (window), "Preferences");
    g_signal_connect (G_OBJECT (window), "destroy",
                      G_CALLBACK (gtk_main_quit), NULL);
    HildonPickerButton *picker = HILDON_PICKER_BUTTON (hildon_picker_button_new (
                            HILDON_SIZE_THUMB_HEIGHT | HILDON_SIZE_HALFSCREEN_WIDTH,
                                                HILDON_BUTTON_ARRANGEMENT_VERTICAL));
    hildon_button_set_title (HILDON_BUTTON (picker), "Proxy preferences:");
    HildonTouchSelector *selector = HILDON_TOUCH_SELECTOR (hildon_touch_selector_new_text ());
    hildon_picker_button_set_selector (picker, selector);
    hildon_touch_selector_append_text (selector, "None");
    hildon_touch_selector_append_text (selector, "Auto");
    hildon_touch_selector_append_text (selector, "Manual");
    hildon_picker_button_set_active (picker, 0);
    GtkVBox *contents = GTK_VBOX (gtk_vbox_new (12, FALSE));
    /* ... other widgets placed here */
    gtk_box_pack_end (GTK_BOX (contents), GTK_WIDGET (picker), FALSE, FALSE, 0);
    gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (contents));
    gtk_widget_show_all (window);
    gtk_main ();
    return 0;
}

[edit] Notebooks

Because the use of notebooks is not advised in Hildon, the way to migrate a Maemo 4 dialog with a notebook to Maemo 5, is to simply put all the items inside a single pannable dialog.