Documentation/Maemo 5 Developer Guide/Porting Software/Migration

=Migration = 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.

Menus
Hildon app menu represents a big difference from the normal menus. If your application is to be finger-friendly, an app menu is mandatory.

Because the app menu uses buttons, you can easily add them with the functions that the original menu items were assigned. On top of that, given the menu limited size (ten items), the items to be added must be carefully divided. For example, consider an advanced text edition 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

A few decisions of what menus to include and which ones to divide or leave out need to be taken. For example, the "File" menu is a mandatory one and should be accessible from the main window's menu. On the other hand, the "Quit" sub menu is not really necessary, because the user can quit the application using the upper right corner's cross. Considering that the device has "+" and "-" keys, those can be assigned the functions of zooming in and out of the "View" menu. The "Copy", "Paste" and "Cut" actions from the "Edit" menu are also present in the application's toolbar as well as by using keyboard shortcuts so, they are not included in the menu. The "Indent Type" menu can be accomplished using app menu filters being, for this, removed from the "Edit" menu as well. This results in the "Edit" menu having only a sub menu "Preferences" which can be added to the app menu directly instead.

The following example shows the implementation of the menu following the above decisions. Figure @@IMAGE@@ shows the final result of the app menu. Figures @@IMAGE@@ and @@IMAGE@@ show the sub views activated by the menus "View" and "Help", respectively.

'''Example 10.2. Migrating a menu'''

static void normal_zoom_cb {   /* Code to set normal zoom... */   hildon_window_stack_pop_1 (hildon_window_stack_get_default); } static void view_subview {   HildonStackableWindow *view_window; view_window = HILDON_STACKABLE_WINDOW (hildon_stackable_window_new ); gtk_window_set_title (GTK_WINDOW (view_window), "View"); GtkButton *normal_zoom_button = GTK_BUTTON (hildon_gtk_button_new ( HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH)); gtk_button_set_label (normal_zoom_button, "Normal Zoom"); g_signal_connect (G_OBJECT (normal_zoom_button), "clicked",                     G_CALLBACK (normal_zoom_cb), NULL); HildonTouchSelector *highlight_selector; highlight_selector = HILDON_TOUCH_SELECTOR (hildon_touch_selector_new_text ); hildon_touch_selector_append_text (highlight_selector, "C"); hildon_touch_selector_append_text (highlight_selector, "JAVA"); hildon_touch_selector_append_text (highlight_selector, "Python"); HildonPickerButton *highlight_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 (highlight_picker), "Syntax highlight:"); hildon_picker_button_set_selector (highlight_picker, highlight_selector); hildon_picker_button_set_active (highlight_picker, 0); GtkVBox *contents = GTK_VBOX (gtk_vbox_new (12, FALSE)); gtk_box_pack_end (GTK_BOX (contents), GTK_WIDGET (highlight_picker), FALSE, FALSE, 0); gtk_box_pack_end (GTK_BOX (contents), GTK_WIDGET (normal_zoom_button), FALSE, FALSE, 0); gtk_container_add (GTK_CONTAINER (view_window), GTK_WIDGET (contents)); gtk_widget_show_all (GTK_WIDGET (view_window)); } static void help_contents_cb (GtkButton *widget, gpointer data) {   /* Code to set show help contents... */   hildon_window_stack_pop_1 (hildon_window_stack_get_default); } static void help_about_cb (GtkButton *widget, gpointer data) {   /* Code to set show about information... */   hildon_window_stack_pop_1 (hildon_window_stack_get_default); } static void help_subview {   HildonStackableWindow *view_window; view_window = HILDON_STACKABLE_WINDOW (hildon_stackable_window_new ); gtk_window_set_title (GTK_WINDOW (view_window), "Help"); GtkButton *help_contents_button = GTK_BUTTON (hildon_gtk_button_new ( HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH)); gtk_button_set_label (help_contents_button, "Contents"); g_signal_connect (G_OBJECT (help_contents_button), "clicked",                     G_CALLBACK (help_contents_cb), NULL); GtkButton *help_about_button = GTK_BUTTON (hildon_gtk_button_new ( HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH)); gtk_button_set_label (help_about_button, "About"); g_signal_connect (G_OBJECT (help_about_button), "clicked",                     G_CALLBACK (help_about_cb), NULL); GtkVBox *contents = GTK_VBOX (gtk_vbox_new (12, FALSE)); gtk_box_pack_end (GTK_BOX (contents), GTK_WIDGET (help_contents_button), FALSE, FALSE, 0); gtk_box_pack_end (GTK_BOX (contents), GTK_WIDGET (help_about_button), FALSE, FALSE, 0); gtk_container_add (GTK_CONTAINER (view_window), GTK_WIDGET (contents)); gtk_widget_show_all (GTK_WIDGET (view_window)); } static HildonAppMenu * build_menu (void) {   HildonSizeType button_size = HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH; HildonAppMenu *menu = HILDON_APP_MENU (hildon_app_menu_new ); GtkButton *button; GtkRadioButton *filter; /* 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 As"); hildon_app_menu_append (menu, GTK_BUTTON (button)); button = GTK_BUTTON (hildon_gtk_button_new (button_size)); gtk_button_set_label (button, "Preferences"); hildon_app_menu_append (menu, GTK_BUTTON (button)); button = GTK_BUTTON (hildon_gtk_button_new (button_size)); gtk_button_set_label (button, "View"); g_signal_connect (G_OBJECT (button), "clicked",                     G_CALLBACK (view_subview), NULL); hildon_app_menu_append (menu, GTK_BUTTON (button)); filter = GTK_RADIO_BUTTON (hildon_gtk_radio_button_new (button_size, NULL)); gtk_button_set_label (GTK_BUTTON (filter), "Indentation: Spaces"); hildon_app_menu_add_filter (menu, GTK_BUTTON (filter)); gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (filter), FALSE); button = GTK_BUTTON (hildon_gtk_button_new (button_size)); gtk_button_set_label (button, "Help"); g_signal_connect (G_OBJECT (button), "clicked",                     G_CALLBACK (help_subview), NULL); hildon_app_menu_append (menu, GTK_BUTTON (button)); filter = GTK_RADIO_BUTTON (hildon_gtk_radio_button_new_from_widget (button_size, GTK_RADIO_BUTTON (filter))); gtk_button_set_label (GTK_BUTTON (filter), "Indentation: Tabs"); hildon_app_menu_add_filter (menu, GTK_BUTTON (filter)); gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (filter), FALSE); 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 ; hildon_stackable_window_set_main_menu (HILDON_STACKABLE_WINDOW (window),    menu); GtkWidget *contents = gtk_label_new ("This example shows how an app menu could be "                                        "divided.\nMenus that would open new dialogs "                                         "are not assigned any action."); 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; }
 * 1) include 

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. @@IMAGE@@ shows a screenshot of the resulting graphical user interface.

'''Figure 10.1. Three radio buttons'''



'''Example 10.3. Migrating choice widgets'''

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

Notebooks
Because the use of notebooks is not advised in Hildon, this widget does not have to be replaced to be updated.

Imagine a preferences dialog that has a notebook to divide the preferences in "General", "Colors" and "Tools" like depicted in Figure 10.2 “Typical Notebook”. The way to accomplish the same functionality without having a notebook is to use a window with buttons that open other windows as subviews. Each window opened using the buttons should have the content that the respective page in the notebook had.

'''Figure 10.2. Typical Notebook'''



The example shows the code to produce a replacement for the notebook (see @@IMAGE@@).

'''Example 10.4. Migrating a notebook'''

<tt>  <font color="#000080"> #include  <font color="#FF0000">&lt;hildon/hildon.h&gt;  <font color="#0000FF">static  HildonStackableWindow <font color="#990000"> *  <font color="#000000">new_preferences_window  <font color="#990000">( gchar <font color="#990000"> * title <font color="#990000">) <font color="#FF0000">{ HildonStackableWindow <font color="#990000"> * pref_window <font color="#990000"> ; pref_window <font color="#990000"> =  <font color="#000000">HILDON_STACKABLE_WINDOW   <font color="#990000">(   <font color="#000000">hildon_stackable_window_new   <font color="#990000">);  <font color="#000000">gtk_window_set_title  <font color="#990000">(   <font color="#000000">GTK_WINDOW   <font color="#990000">( pref_window <font color="#990000">), title <font color="#990000">); GtkWidget <font color="#990000"> * content <font color="#990000"> =  <font color="#000000">gtk_label_new   <font color="#990000">(   <font color="#000000">g_strdup_printf   <font color="#990000">(  <font color="#FF0000">"Set the %s Preferences"  <font color="#990000">, title <font color="#990000">));  <font color="#000000">gtk_widget_show  <font color="#990000">( content <font color="#990000">);  <font color="#000000">gtk_container_add  <font color="#990000">(   <font color="#000000">GTK_CONTAINER   <font color="#990000">( pref_window <font color="#990000">), content <font color="#990000">);  <font color="#0000FF">return  pref_window <font color="#990000"> ; <font color="#FF0000">}  <font color="#0000FF">static  <font color="#009900">void  <font color="#000000">button_clicked_cb  <font color="#990000">( GtkWidget <font color="#990000"> * button <font color="#990000">, gchar <font color="#990000"> * title <font color="#990000">) <font color="#FF0000">{ HildonStackableWindow <font color="#990000"> * sw <font color="#990000"> =  <font color="#000000">new_preferences_window   <font color="#990000">( title <font color="#990000">);  <font color="#000000">gtk_widget_show_all  <font color="#990000">(   <font color="#000000">GTK_WIDGET   <font color="#990000">( sw <font color="#990000">)); <font color="#FF0000">} <font color="#009900">int  <font color="#000000">main  <font color="#990000">(  <font color="#009900">int argc <font color="#990000">,  <font color="#009900">char  <font color="#990000"> ** argv <font color="#990000">) <font color="#FF0000">{  <font color="#000000">hildon_gtk_init  <font color="#990000">(&amp; argc <font color="#990000">,  <font color="#990000">&amp; argv <font color="#990000">); GtkWidget <font color="#990000"> * window <font color="#990000"> ; GtkButton <font color="#990000"> * general_pref_button <font color="#990000">, <font color="#990000"> * colors_pref_button <font color="#990000">,  <font color="#990000"> * tools_pref_button <font color="#990000"> ; window <font color="#990000"> =  <font color="#000000">hildon_stackable_window_new   <font color="#990000">;  <font color="#000000">gtk_window_set_title  <font color="#990000">(   <font color="#000000">GTK_WINDOW   <font color="#990000">( window <font color="#990000">),  <font color="#FF0000">"Preferences"  <font color="#990000">); general_pref_button <font color="#990000"> =  <font color="#000000">GTK_BUTTON   <font color="#990000">(   <font color="#000000">hildon_gtk_button_new   <font color="#990000">( HILDON_SIZE_AUTO_HEIGHT <font color="#990000">));  <font color="#000000">gtk_button_set_label  <font color="#990000">( general_pref_button <font color="#990000">,  <font color="#FF0000">"General"  <font color="#990000">);  <font color="#000000">g_signal_connect  <font color="#990000">( general_pref_button <font color="#990000">,  <font color="#FF0000">"clicked"  <font color="#990000">,                           <font color="#000000">G_CALLBACK   <font color="#990000">( button_clicked_cb <font color="#990000">),  <font color="#FF0000">"General"  <font color="#990000">); colors_pref_button <font color="#990000"> =  <font color="#000000">GTK_BUTTON   <font color="#990000">(   <font color="#000000">hildon_gtk_button_new   <font color="#990000">( HILDON_SIZE_AUTO_HEIGHT <font color="#990000">));  <font color="#000000">gtk_button_set_label  <font color="#990000">( colors_pref_button <font color="#990000">,  <font color="#FF0000">"Colors"  <font color="#990000">);  <font color="#000000">g_signal_connect  <font color="#990000">( colors_pref_button <font color="#990000">,  <font color="#FF0000">"clicked"  <font color="#990000">,                           <font color="#000000">G_CALLBACK   <font color="#990000">( button_clicked_cb <font color="#990000">),  <font color="#FF0000">"Colors"  <font color="#990000">); tools_pref_button <font color="#990000"> =  <font color="#000000">GTK_BUTTON   <font color="#990000">(   <font color="#000000">hildon_gtk_button_new   <font color="#990000">( HILDON_SIZE_AUTO_HEIGHT <font color="#990000">));  <font color="#000000">gtk_button_set_label  <font color="#990000">( tools_pref_button <font color="#990000">,  <font color="#FF0000">"Tools"  <font color="#990000">);  <font color="#000000">g_signal_connect  <font color="#990000">( tools_pref_button <font color="#990000">,  <font color="#FF0000">"clicked"  <font color="#990000">,                           <font color="#000000">G_CALLBACK   <font color="#990000">( button_clicked_cb <font color="#990000">),  <font color="#FF0000">"Tools"  <font color="#990000">); GtkVBox <font color="#990000"> * contents <font color="#990000"> =  <font color="#000000">GTK_VBOX   <font color="#990000">(   <font color="#000000">gtk_vbox_new   <font color="#990000">( TRUE <font color="#990000">,  <font color="#993399">12  <font color="#990000">));  <font color="#000000">gtk_container_add  <font color="#990000">(   <font color="#000000">GTK_CONTAINER   <font color="#990000">( contents <font color="#990000">),   <font color="#000000">GTK_WIDGET   <font color="#990000">( general_pref_button <font color="#990000">));  <font color="#000000">gtk_container_add  <font color="#990000">(   <font color="#000000">GTK_CONTAINER   <font color="#990000">( contents <font color="#990000">),   <font color="#000000">GTK_WIDGET   <font color="#990000">( colors_pref_button <font color="#990000">));  <font color="#000000">gtk_container_add  <font color="#990000">(   <font color="#000000">GTK_CONTAINER   <font color="#990000">( contents <font color="#990000">),   <font color="#000000">GTK_WIDGET   <font color="#990000">( tools_pref_button <font color="#990000">));  <font color="#000000">gtk_container_add  <font color="#990000">(   <font color="#000000">GTK_CONTAINER   <font color="#990000">( window <font color="#990000">),   <font color="#000000">GTK_WIDGET   <font color="#990000">( contents <font color="#990000">));  <font color="#000000">g_signal_connect  <font color="#990000">(   <font color="#000000">G_OBJECT   <font color="#990000">( window <font color="#990000">),  <font color="#FF0000">"destroy"  <font color="#990000">,                         <font color="#000000">G_CALLBACK   <font color="#990000">( gtk_main_quit <font color="#990000">), NULL <font color="#990000">);  <font color="#000000">gtk_widget_show_all  <font color="#990000">( window <font color="#990000">);  <font color="#000000">gtk_main  <font color="#990000">;  <font color="#0000FF">return  <font color="#993399">0  <font color="#990000"> ; <font color="#FF0000">} </tt>