rotation.c

Go to the documentation of this file.
00001 /*
00002  * File Name: rotation.c
00003  */
00004 
00005 /*
00006  * This file is part of settings.
00007  *
00008  * settings is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * settings is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2010 IREX Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 //----------------------------------------------------------------------------
00028 // Include Files
00029 //----------------------------------------------------------------------------
00030 
00031 // system include files, between < >
00032 
00033 #include <gtk/gtk.h>
00034 #include <gdk/gdk.h>
00035 
00036 #include <libergtk/ergtk.h>
00037 
00038 #include "i18n.h"
00039 #include "log.h"
00040 #include "settings.h"
00041 #include "settings_utils.h"
00042 #include "settings_style.h"
00043 
00044 #include "rotation.h"
00045 
00046 
00047 //----------------------------------------------------------------------------
00048 // Type Declarations
00049 //----------------------------------------------------------------------------
00050   
00051 typedef enum
00052 {
00053     /* Has only effect in landscape orientation */
00054     Rotation_Clockwise,      /* normal: upkey -> next page */
00055     Rotation_Anti_Clockwise  /* normal: upkey -> prev page */
00056 } RotationDirection;
00057 
00058 
00059 //----------------------------------------------------------------------------
00060 // Global Constants
00061 //----------------------------------------------------------------------------
00062 
00063 #define NUM_ROTATION_MODES  2
00064 
00065 
00066 //----------------------------------------------------------------------------
00067 // Static Variables
00068 //----------------------------------------------------------------------------
00069 
00070 static RotationDirection g_orig_rotation_settings;
00071 static RotationDirection g_cur_rotation_settings;
00072 
00073 static GtkWidget* g_rotation_settings_radios[NUM_ROTATION_MODES];  
00074 
00075 static const GdkColor grey = { 0, 0x5500, 0x5500, 0x5500 }; //TODO define in settings_style.h
00076 
00077 //============================================================================
00078 // Local Function Definitions
00079 //============================================================================
00080 
00081 static GtkWidget* create_rotation_settings_widgets         (GtkBox* parent);
00082 
00083 static void on_rotation_settings_changed                   (GtkWidget *widget, gpointer data);
00084 static void init_widgets_with_settings          (void);
00085 static void on_listview_row_activated ( GtkTreeView       *view,
00086                                         GtkTreePath       *path,
00087                                         GtkTreeViewColumn *column,
00088                                         gpointer          user_data );
00089 
00090 
00091 static void on_listview_navigate_cursor ( 
00092         erGtkListView         *er_listview,
00093         erGtkListViewKeyPress keycode,
00094         gpointer              user_data );
00095 
00096 static gboolean on_focus_in(GtkWidget* widget, gpointer data );
00097 static gboolean on_focus_out(GtkWidget* widget, gpointer data );
00098 
00099 
00100 
00101 //============================================================================
00102 // Functions Implementation
00103 //============================================================================
00104 
00105 GtkWidget* create_rotation_window(GtkWidget* parent)
00106 {
00107     LOGPRINTF(" create_rotation_window \n");
00108 
00109     // create top window
00110     GtkWidget* top_window = parent;
00111     gtk_window_maximize(GTK_WINDOW(top_window));
00112     gtk_window_set_resizable(GTK_WINDOW(top_window), FALSE);
00113     gtk_container_set_border_width(GTK_CONTAINER(top_window), WINDOW_BORDER_PADDING );
00114     gtk_window_set_modal(GTK_WINDOW(top_window), TRUE);
00115 
00116     // top level vbox (vboxtop)
00117     GtkWidget* vboxtop = gtk_vbox_new(FALSE, 3);
00118     gtk_container_add(GTK_CONTAINER(top_window), vboxtop);
00119 
00120     // add header container the title and subtitle of this settings page
00121     create_title(GTK_VBOX(vboxtop), _("Settings"), _("Rotation Direction"));
00122     
00123     // add the back/exit bar below the title 
00124     GtkWidget* view = create_settingsview();
00125     gtk_box_pack_start(GTK_BOX(vboxtop), view, FALSE, FALSE,0 ); 
00126     g_signal_connect(view, "row-activated", G_CALLBACK(on_listview_row_activated), NULL ) ;
00127     g_signal_connect(view, "navigate-cursor", G_CALLBACK(on_listview_navigate_cursor), NULL ) ;
00128     g_signal_connect(view, "focus-in-event", G_CALLBACK(on_focus_in), NULL );
00129     g_signal_connect(view, "focus-out-event", G_CALLBACK(on_focus_out), NULL );
00130 
00131     // add an alignment below the exit bar
00132     GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 0.0);
00133     gtk_container_add(GTK_CONTAINER(vboxtop), alignment);
00134 
00135     // introdude a frame in the alignment
00136     GtkWidget* frame = gtk_frame_new(NULL);
00137     gtk_widget_set_name(frame, "irex-margins-frame");
00138     gtk_container_add(GTK_CONTAINER(alignment), frame);
00139     gtk_container_set_border_width(GTK_CONTAINER(frame), 3);
00140 
00141     // alignment in frame 
00142     GtkWidget* alignment2 = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
00143     gtk_container_add(GTK_CONTAINER(frame), alignment2);
00144     gtk_alignment_set_padding(GTK_ALIGNMENT(alignment2),
00145                               WINDOW_TOP_ALT_PADDING,
00146                               WINDOW_BOTTOM_PADDING,
00147                               WINDOW_H_PADDING,
00148                               WINDOW_H_PADDING);
00149    
00150     // vbox in alignment2
00151     GtkWidget* innervbox = gtk_vbox_new(FALSE, SMALL_SPACING);
00152     gtk_container_add(GTK_CONTAINER(alignment2), innervbox);
00153     
00154     // The margin settings section.
00155     create_rotation_settings_widgets(GTK_BOX(innervbox));
00156 
00157     // Update widget with current settings.
00158     init_widgets_with_settings();
00159 
00160     gtk_widget_grab_focus(view);
00161 
00162     gtk_widget_show_all(top_window);
00163     return top_window;
00164 }
00165 
00166 
00167 
00168 //============================================================================
00169 // Local Functions Implementation
00170 //============================================================================
00171 
00172 static void on_listview_row_activated ( GtkTreeView       *view,
00173                                         GtkTreePath       *path,
00174                                         GtkTreeViewColumn *column,
00175                                         gpointer          user_data )
00176 {
00177     LOGPRINTF(" on_listview_row_activated "); 
00178     save_rotation_settings();
00179 
00180     main_quit();
00181     return;
00182 }
00183 
00184 static void on_listview_navigate_cursor ( erGtkListView         *er_listview,
00185         erGtkListViewKeyPress keycode,
00186         gpointer              user_data )
00187 {
00188     LOGPRINTF(" on_listview_navigate_cursor "); printf(" on_listview_navigate_cursor \n");
00189 
00190     GtkTreeSelection* my_selection = gtk_tree_view_get_selection((GtkTreeView*) er_listview);
00191     g_assert( my_selection != NULL ) ;
00192 
00193     // determine new cursor position
00194     switch (keycode)
00195     {
00196         case ERGTK_LIST_VIEW_PRESS_SHORT_DOWN:
00197         case ERGTK_LIST_VIEW_PRESS_LONG_DOWN:
00198             gtk_widget_grab_focus(GTK_WIDGET(g_rotation_settings_radios[0])); // down: to first widget
00199             gtk_tree_selection_unselect_all(my_selection);
00200             break;
00201         default:
00202             LOGPRINTF("illegal erGtkListViewKeyPress [%d]", keycode);
00203             ;  // ignore
00204             break;
00205     }
00206 
00207 }
00208 
00209 static gboolean on_focus_in(GtkWidget* widget, gpointer data )
00210 {
00211     LOGPRINTF(" on_focus_in "); 
00212     g_assert(widget != NULL ) ;
00213     ergtk_list_view_set_cursor( ERGTK_LIST_VIEW(widget), 0); // row = 0;
00214     return FALSE;
00215 }
00216 
00217 static gboolean on_focus_out(GtkWidget* widget, gpointer data )
00218 {
00219     LOGPRINTF(" on_focus_out ");   
00220     g_assert(widget != NULL ) ;
00221     GtkTreeSelection* my_selection = gtk_tree_view_get_selection((GtkTreeView*) widget);
00222     g_assert( my_selection != NULL ) ;
00223     gtk_tree_selection_unselect_all(my_selection);
00224     return FALSE;
00225 }
00226 
00227 
00228 //============================================================================
00229 // Functions Implementation
00230 //============================================================================
00231 
00232 
00233 void load_rotation_settings()
00234 {
00235     LOGPRINTF(" load_rotation_settings "); 
00236     const char* rotation          = NULL;
00237     
00238     // Get rotation direction.
00239     rotation = get_value_string(GCONF_ROTATION_DIRECTION);
00240     if (strcmp(rotation, "clockwise") == 0)
00241     {
00242         g_orig_rotation_settings = Rotation_Clockwise;
00243     }
00244     else
00245     {
00246         g_orig_rotation_settings = Rotation_Anti_Clockwise;
00247     }
00248     
00249     g_cur_rotation_settings = g_orig_rotation_settings;
00250 }
00251 
00252 
00253 void save_rotation_settings()
00254 {
00255     LOGPRINTF(" save_rotation_settings ");  
00256     // Set rotation direction if necessary.
00257     if (g_cur_rotation_settings != g_orig_rotation_settings)
00258     {
00259         set_value_string(GCONF_ROTATION_DIRECTION,
00260             (g_cur_rotation_settings == Rotation_Clockwise) ? "clockwise" : "anticlockwise");
00261     }
00262 
00263     LOGPRINTF("Saving rotation settings, done.");
00264 }
00265 
00266 
00267 //============================================================================
00268 // Local Functions Implementation
00269 //============================================================================
00270 
00271 
00272 // radiobutton
00273 // |--align
00274 //    |--hbox
00275 //       |--icon
00276 //       |--align2
00277 //          |--vbox
00278 //             |-- title
00279 //             |-- subtitle 
00280 static GtkWidget* create_radio_button_icon_item(GtkWidget* group, gchar* title, gchar* subtitle, gchar* icon)
00281 {
00282     LOGPRINTF(" create_radio_button_icon_item "); 
00283     GtkWidget* radio_button = NULL;
00284 
00285 
00286     if ( group == NULL ) // create first radiobutton
00287     {
00288         radio_button = gtk_radio_button_new(NULL);  
00289     }
00290     else // create next radiobutton
00291     {
00292         radio_button = gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(group)); 
00293     }
00294     
00295     gtk_widget_set_name(radio_button, "irex-settings-checkbutton"); // sets style
00296 
00297     // alignment in radio button for some padding
00298     GtkWidget* align = gtk_alignment_new(0, 0.0, 1.0, 1.0);
00299     gtk_container_add(GTK_CONTAINER(radio_button), align);
00300     gtk_alignment_set_padding(GTK_ALIGNMENT(align),
00301                              WINDOW_TOP_ALT_PADDING,
00302                              WINDOW_BOTTOM_PADDING,
00303                              WINDOW_H_PADDING,
00304                              WINDOW_H_PADDING);
00305 
00306     // hbox in radio button for icon and labels.
00307     GtkWidget* radiohbox = gtk_hbox_new(FALSE, SMALL_SPACING * 3);
00308     gtk_container_add(GTK_CONTAINER(align), radiohbox);
00309 
00310     // Add icon image
00311     GtkWidget* image = gtk_image_new_from_file(icon);
00312     gtk_box_pack_start(GTK_BOX(radiohbox), image, FALSE, FALSE, 0);
00313 
00314     // For layout purposes of text lengths, add align container
00315     GtkWidget* align2 = gtk_alignment_new(0, 0, 1.0, 1.0); 
00316     gtk_container_add(GTK_CONTAINER(radiohbox), align2);
00317     gtk_alignment_set_padding(GTK_ALIGNMENT(align2),
00318                              WINDOW_TOP_ALT_PADDING,
00319                              WINDOW_BOTTOM_PADDING,
00320                              WINDOW_H_PADDING,
00321                              WINDOW_H_PADDING);
00322 
00323     // vbox for label and description
00324     GtkWidget* radiovbox = gtk_vbox_new(FALSE, SMALL_SPACING);
00325     gtk_container_add(GTK_CONTAINER(align2), radiovbox);
00326     
00327     // label for radio button 
00328     GtkWidget* item = subject_create();
00329     gtk_label_set_label(GTK_LABEL(item), title);
00330     gtk_box_pack_start(GTK_BOX(radiovbox), item, FALSE, FALSE, 0);
00331 
00332     // second level label for radio button : descriptive test 
00333     GtkWidget* desc = description_create();
00334     gtk_label_set_label(GTK_LABEL(desc), subtitle);
00335     gtk_widget_set_size_request(desc, SETTINGS_LABEL_MAX_WIDTH, -1); // force size calculation at maximum width, also in landscape
00336     gtk_widget_modify_fg(desc, GTK_STATE_ACTIVE, &grey); //keep grey on active choice
00337     gtk_box_pack_start(GTK_BOX(radiovbox), desc, FALSE, FALSE, 0);
00338 
00339     return radio_button;
00340 }
00341 
00342 
00343 
00344 // Widget Hierarchy
00345 // |--Top Level vbox
00346 //    |--label ("Choose the rotation direction")
00347 //    |--vbox
00348 //       |--radiobutton ("Clockwise")
00349 //       |--radiobutton ("Anticlockwise")
00350 static GtkWidget* create_rotation_settings_widgets(GtkBox* parent)
00351 {
00352     LOGPRINTF(" create_rotation_settings_widgets ");   
00353     // Top level vbox.
00354     GtkWidget* top_level_vbox = gtk_vbox_new(FALSE, ITEM_SPACING);
00355     gtk_box_pack_start(parent, top_level_vbox, FALSE, FALSE, 0);
00356 
00357     // The vbox containing radio buttons.
00358     GtkWidget* vbox = gtk_vbox_new(TRUE, 10);
00359     gtk_box_pack_start(GTK_BOX(top_level_vbox), vbox, FALSE, FALSE, 0);
00360 
00361     int i = 0 ;
00362     for (i=0; i<NUM_ROTATION_MODES; i++)
00363     {
00364         switch (i)
00365         {
00366             case 0:
00367             {
00368                 // the radio button "Clockwise Rotation"
00369                 g_rotation_settings_radios[i] = create_radio_button_icon_item(NULL, _("Clockwise")
00370                         , _("Rotate clockwise for left-handed use."),
00371                         DATADIR"/rotation-clockwise.png");
00372                 break;
00373             }
00374             case 1:
00375             {
00376                 // The radio button "Anticlockwise Rotation"
00377                 g_rotation_settings_radios[i] = create_radio_button_icon_item(g_rotation_settings_radios[0], _("Anticlockwise")
00378                         , _("Rotate anticlockwise for right-handed use"),
00379                         DATADIR"/rotation-anticlockwise.png");
00380                 break;
00381             }
00382             default:
00383             {
00384                 LOGPRINTF(" never happens ");
00385                 // never happens
00386                 break;
00387             }
00388         }
00389 
00390         // Add signal handler.
00391         g_signal_connect_after(G_OBJECT(g_rotation_settings_radios[i]),
00392             "toggled",
00393             G_CALLBACK(on_rotation_settings_changed),
00394             (gpointer)i);
00395 
00396         gtk_box_pack_start(GTK_BOX(vbox), g_rotation_settings_radios[i], FALSE, FALSE, 0);
00397     }
00398     
00399     return top_level_vbox;
00400 }
00401 
00402 
00403 static void on_rotation_settings_changed(GtkWidget *widget, gpointer data)
00404 {
00405     LOGPRINTF(" on_rotation_settings_changed "); 
00406     int index = (int)data;
00407 
00408     g_assert( 0 <= index );
00409     g_assert( index < NUM_ROTATION_MODES );
00410 
00411     gboolean is_active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
00412 
00413     if (is_active == TRUE )
00414     {
00415         switch (index)
00416         {
00417             case 0:     // CLOCKWISE
00418                 g_cur_rotation_settings = Rotation_Clockwise;
00419                 break;
00420             case 1:     // ANTI_CLOCKWISE
00421                 g_cur_rotation_settings = Rotation_Anti_Clockwise;
00422                 break;
00423             default:
00424                 ERRORPRINTF("Invalid index [%d]", index);
00425                 break;
00426         }
00427     }
00428 }
00429 
00430 static void init_widgets_with_settings()
00431 {
00432     LOGPRINTF(" init_widgets_with_settings "); 
00433 
00434     int i = 0;
00435     int to_be_activated = 0 ;
00436 
00437     if ( g_cur_rotation_settings == Rotation_Clockwise )
00438     {
00439         to_be_activated = 0; 
00440     } 
00441     else
00442     {
00443         to_be_activated = 1;
00444     }
00445 
00446     for (i = 0; i < NUM_ROTATION_MODES; i++)
00447     {
00448         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(g_rotation_settings_radios[i]),
00449                                       (i == to_be_activated) ? TRUE : FALSE );
00450     }
00451 }
00452 
Generated by  doxygen 1.6.2-20100208