margins.c

Go to the documentation of this file.
00001 /*
00002  * File Name: margins.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) 2008 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 //----------------------------------------------------------------------------
00028 // Include Files
00029 //----------------------------------------------------------------------------
00030 
00031 // system include files, between < >
00032 #include <string.h>
00033 #include <stdlib.h>
00034 #include <unistd.h>
00035 #include <stdio.h>
00036 
00037 #include <gtk/gtk.h>
00038 #include <gdk/gdk.h>
00039 #include <glib.h>
00040 
00041 #include <libergtk/ergtk.h>
00042 
00043 #include "i18n.h"
00044 #include "log.h"
00045 #include "ipc.h"
00046 #include "settings.h"
00047 #include "settings_utils.h"
00048 #include "settings_style.h"
00049 #include "margins.h"
00050 
00051 
00052 //----------------------------------------------------------------------------
00053 // Type Declarations
00054 //----------------------------------------------------------------------------
00055 
00056 typedef struct
00057 {
00058     int margin_horizontal;
00059     int margin_vertical;
00060 } UdsSettings;
00061 
00062 enum
00063 {
00064     MARGIN_NONE = 0,
00065     MARGIN_NORMAL,
00066     MARGIN_MEDIUM,
00067     MARGIN_LARGE,
00068     NUM_MARGINS
00069 } UdsMargins_e;
00070 
00071 
00072 //----------------------------------------------------------------------------
00073 // Global Constants
00074 //----------------------------------------------------------------------------
00075 
00076 static const int  DEFAULT_MARGIN = 20;
00077 
00078 //----------------------------------------------------------------------------
00079 // Static Variables
00080 //----------------------------------------------------------------------------
00081 
00082 static UdsSettings g_orig_uds_settings;
00083 static UdsSettings g_cur_uds_settings;
00084 
00085 static GtkWidget* g_margin_radios[NUM_MARGINS];  // Note: rely on compiler to initialise these to 0x00 == NULL
00086 
00087 // Margins at 160dpi:
00088 // 20 = 1/8" (~3mm)
00089 // 40 = 1/4" (~6mm)
00090 // 80 = 1/2" (~1.2mm)
00091 
00092 static int g_margins_horizontal[NUM_MARGINS] = { 0,  20,  40,  80 };  // pixels
00093 static int g_margins_vertical  [NUM_MARGINS] = { 0,  20,  40,  80 };  // pixels
00094 
00095 //============================================================================
00096 // Local Function Definitions
00097 //============================================================================
00098 
00099 static GtkWidget* create_margin_widgets         (GtkBox* parent);
00100 
00101 static void on_margin_changed                   (GtkWidget *widget, gpointer data);
00102 static void init_widgets_with_settings          (void);
00103 static void on_listview_row_activated ( GtkTreeView       *view,
00104                                         GtkTreePath       *path,
00105                                         GtkTreeViewColumn *column,
00106                                         gpointer          user_data );
00107 
00108 
00109 static void on_listview_navigate_cursor ( erGtkListView         *er_listview,
00110         erGtkListViewKeyPress keycode,
00111         gpointer              user_data );
00112 
00113 static gboolean on_focus_in(GtkWidget* widget, gpointer data );
00114 static gboolean on_focus_out(GtkWidget* widget, gpointer data );
00115 
00116 //============================================================================
00117 // Functions Implementation
00118 //============================================================================
00119 
00120 GtkWidget* create_margins_window(GtkWidget* parent)
00121 {
00122     LOGPRINTF("entry");
00123 
00124     bzero(g_margin_radios, 2);
00125 
00126     // create top window
00127     GtkWidget* top_window = parent;
00128     gtk_window_maximize(GTK_WINDOW(top_window));
00129     gtk_window_set_resizable(GTK_WINDOW(top_window), FALSE);
00130     gtk_container_set_border_width(GTK_CONTAINER(top_window),WINDOW_BORDER_PADDING  );
00131     gtk_window_set_modal(GTK_WINDOW(top_window), TRUE);
00132 
00133     // top level vbox (vboxtop)
00134     GtkWidget* vboxtop = gtk_vbox_new(FALSE, 3);
00135     gtk_container_add(GTK_CONTAINER(top_window), vboxtop);
00136 
00137     // add header container the title and subtitle of this settings page
00138     create_title(GTK_VBOX(vboxtop), _("Settings"), _("Page Margins"));
00139     
00140     // add the back/exit bar below the title 
00141     GtkWidget* view = create_settingsview();
00142     gtk_box_pack_start(GTK_BOX(vboxtop), view, FALSE, FALSE,0 ); 
00143     g_signal_connect(view, "row-activated", G_CALLBACK(on_listview_row_activated), NULL ) ;
00144     g_signal_connect(view, "navigate-cursor", G_CALLBACK(on_listview_navigate_cursor), NULL ) ;
00145     g_signal_connect(view, "focus-in-event", G_CALLBACK(on_focus_in), NULL );
00146     g_signal_connect(view, "focus-out-event", G_CALLBACK(on_focus_out), NULL );
00147 
00148     // add an alignment below the exit bar
00149     GtkWidget* alignment = gtk_alignment_new(0, 0, 1.0, 0.0);
00150     gtk_container_add(GTK_CONTAINER(vboxtop), alignment);
00151 
00152     // introdude a frame in the alignment
00153     GtkWidget* frame = gtk_frame_new(NULL);
00154     gtk_widget_set_name(frame, "irex-margins-frame");
00155     gtk_container_add(GTK_CONTAINER(alignment), frame);
00156     gtk_container_set_border_width(GTK_CONTAINER(frame), 3);
00157 
00158     // alignment in frame 
00159     GtkWidget* alignment2 = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
00160     gtk_container_add(GTK_CONTAINER(frame), alignment2);
00161     gtk_alignment_set_padding(GTK_ALIGNMENT(alignment2),
00162                               WINDOW_TOP_ALT_PADDING,
00163                               WINDOW_BOTTOM_PADDING,
00164                               WINDOW_H_PADDING,
00165                               WINDOW_H_PADDING);
00166    
00167     // vbox in alignment2
00168     GtkWidget* innervbox = gtk_vbox_new(FALSE, SMALL_SPACING);
00169     gtk_container_add(GTK_CONTAINER(alignment2), innervbox);
00170     
00171     // The margin settings section.
00172     create_margin_widgets(GTK_BOX(innervbox));
00173 
00174     // Update widget with current settings.
00175     init_widgets_with_settings();
00176 
00177     gtk_widget_grab_focus(view);
00178 
00179     gtk_widget_show_all(top_window);
00180     return top_window;
00181 }
00182 
00183 
00184 
00185 //============================================================================
00186 // Local Functions Implementation
00187 //============================================================================
00188 
00189 static void on_listview_row_activated ( GtkTreeView       *view,
00190                                         GtkTreePath       *path,
00191                                         GtkTreeViewColumn *column,
00192                                         gpointer          user_data )
00193 {
00194     LOGPRINTF("entry");
00195 
00196     save_margins_settings();
00197 
00198     main_quit();
00199 
00200     return;
00201 }
00202 
00203 static void on_listview_navigate_cursor ( erGtkListView         *er_listview,
00204         erGtkListViewKeyPress keycode,
00205         gpointer              user_data )
00206 {
00207     LOGPRINTF("entry");
00208 
00209     GtkTreeSelection* my_selection = gtk_tree_view_get_selection((GtkTreeView*) er_listview);
00210     g_assert( my_selection != NULL ) ;
00211 
00212     // determine new cursor position
00213     switch (keycode)
00214     {
00215         case ERGTK_LIST_VIEW_PRESS_SHORT_DOWN:
00216         case ERGTK_LIST_VIEW_PRESS_LONG_DOWN:
00217             gtk_widget_grab_focus(GTK_WIDGET(g_margin_radios[0]));
00218             gtk_tree_selection_unselect_all(my_selection);
00219             break;
00220         default:
00221             LOGPRINTF("illegal erGtkListViewKeyPress [%d]", keycode);
00222             ;  // ignore
00223             break;
00224     }
00225 }
00226 
00227 //============================================================================
00228 // Functions Implementation
00229 //============================================================================
00230 
00231 
00232 void load_margins_settings()
00233 {
00234     int val;
00235     int margins[] = { DEFAULT_MARGIN,
00236                       DEFAULT_MARGIN,
00237                       DEFAULT_MARGIN,
00238                       DEFAULT_MARGIN };
00239     GArray *values = NULL;
00240     
00241     LOGPRINTF("entry");
00242 
00243     values = get_int_array(GCONF_PAGE_MARGINS);
00244     if (values && values->len > 0)
00245     {
00246         unsigned int i;
00247         for ( i = 0 ;
00248               i < sizeof(margins)/sizeof(margins[0])  &&  i < values->len ;
00249               i++ )
00250         {
00251             val = g_array_index(values, int, i);
00252             if (val >= 0)
00253             {
00254                 // valid margin setting
00255                 margins[i] = val;
00256             }
00257         }
00258     }
00259 
00260     // Note: gconf margin left   -> use as horizontal margin
00261     //       gconf margin right  -> ignore (for now)
00262     //       gconf margin top    -> use as vertical margin
00263     //       gconf margin bottom -> ignore (for now)
00264     g_orig_uds_settings.margin_horizontal = margins[0];
00265     g_orig_uds_settings.margin_vertical   = margins[2];
00266 
00267     g_cur_uds_settings = g_orig_uds_settings;
00268 
00269     // clean up
00270     if (values) { g_array_free(values, TRUE); }
00271 }
00272 
00273 
00274 void save_margins_settings()
00275 {
00276     GArray *values = NULL;
00277     
00278     LOGPRINTF("entry");
00279 
00280     if (   g_cur_uds_settings.margin_horizontal != g_orig_uds_settings.margin_horizontal
00281         || g_cur_uds_settings.margin_vertical   != g_orig_uds_settings.margin_vertical  )
00282     {
00283         values = g_array_new(FALSE, FALSE, sizeof(int));
00284         g_array_append_val(values, g_cur_uds_settings.margin_horizontal);  // left
00285         g_array_append_val(values, g_cur_uds_settings.margin_horizontal);  // right
00286         g_array_append_val(values, g_cur_uds_settings.margin_vertical);    // top
00287         g_array_append_val(values, g_cur_uds_settings.margin_vertical);    // bottom
00288 
00289         set_int_array(GCONF_PAGE_MARGINS, values);
00290         g_orig_uds_settings =  g_cur_uds_settings;
00291     }
00292 
00293     LOGPRINTF("Saving margin settings, done.");
00294 
00295     // clean up
00296     if (values) { g_array_free(values, TRUE); }
00297 }
00298 
00299 
00300 //============================================================================
00301 // Local Functions Implementation
00302 //============================================================================
00303 
00304 
00305 static GtkWidget* create_radio_button_item(GtkWidget* group, gchar* title, gchar* subtitle)
00306 {
00307     LOGPRINTF("entry");
00308 
00309     GtkWidget* radio_button = NULL ;
00310     if ( group == NULL ) 
00311     {
00312         radio_button = gtk_radio_button_new(NULL); 
00313     }
00314     else {
00315         radio_button = gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(group)); 
00316 
00317     }
00318     gtk_widget_set_name(radio_button, "irex-settings-checkbutton");
00319 
00320     // alignment in radio button for some padding
00321     GtkWidget* align = gtk_alignment_new(0, 0.0, 1.0, 1.0);
00322     gtk_container_add(GTK_CONTAINER(radio_button), align);
00323     gtk_alignment_set_padding(GTK_ALIGNMENT(align)
00324                                 , 6 // top
00325                                 , 6 // bottom
00326                                 , 6 // left
00327                                 , 6 // right
00328             );
00329  
00330     // vbox in radio button
00331     GtkWidget* radiovbox = gtk_vbox_new( FALSE, 0);
00332     gtk_container_add(GTK_CONTAINER(align), radiovbox);
00333 
00334     // top level label for radio button ( no margins )
00335     GtkWidget* label = gtk_label_new( title );
00336     gtk_widget_set_name(label, "irex-radio-title");
00337     gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
00338     gtk_box_pack_start(GTK_BOX(radiovbox), label, FALSE, FALSE, 0);
00339 
00340     // second level label for radio button ( descriptive test )
00341     label = gtk_label_new( subtitle  );
00342     gtk_widget_set_name(label, "irex-radio-subtitle");
00343     gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
00344     gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
00345     gtk_widget_set_size_request(label, SETTINGS_LABEL_MAX_WIDTH - 40 , -1);
00346     gtk_box_pack_start(GTK_BOX(radiovbox), label, FALSE, FALSE, 0);
00347 
00348     return radio_button;
00349 }
00350 
00351 
00352 
00353 // Widget Hierarchy
00354 // |--Top Level vbox
00355 //    |--label ("UDS settings")
00356 //    |--label ("Choose the page margin")
00357 //    |--vbox
00358 //       |--radio
00359 //       |--radio
00360 //       |--radio
00361 //       |--radio
00362 static GtkWidget* create_margin_widgets(GtkBox* parent)
00363 {
00364     LOGPRINTF("entry");
00365 
00366     // Top level vbox.
00367     GtkWidget* top_level_vbox = gtk_vbox_new(FALSE, ITEM_SPACING);
00368     gtk_box_pack_start(parent, top_level_vbox, FALSE, FALSE, 0);
00369 
00370     // The vbox containing radio buttons.
00371     GtkWidget* vbox = gtk_vbox_new(TRUE, 10);
00372     gtk_box_pack_start(GTK_BOX(top_level_vbox), vbox, FALSE, FALSE, 0);
00373 
00374     int i = 0 ;
00375     for (i=0; i<NUM_MARGINS; i++)
00376     {
00377         switch (i)
00378         {
00379             case 0:
00380             {
00381                 // the radio button "No Margins"
00382                 g_margin_radios[i] = create_radio_button_item(NULL, _("No Margins"), _("Allows the text in a book to run to the edges of the screen."));
00383                 
00384                 break;
00385             }
00386             case 1:
00387             {
00388                 // The radio button "Normal margins".
00389                 g_margin_radios[i] = create_radio_button_item(g_margin_radios[0], _("Normal Margins")
00390                         , _("Leaves 1/8\" of white space around the text in a book."));
00391                 
00392                 break;
00393             }
00394             case 2:
00395             {
00396                 // The radio button "Medium Margins".
00397                 g_margin_radios[i] = create_radio_button_item(g_margin_radios[0], _("Medium Margins")
00398                         , _("Leaves 1/4\" of white space around the text in a book."));
00399                 break;
00400             }
00401             case 3:
00402             {
00403                 // The radio button "Large Margins".
00404                 g_margin_radios[i] = create_radio_button_item(g_margin_radios[0], _("Large Margins")
00405                         , _("Leaves 1/2\" of white space around the text in a book."));
00406                 break;
00407             }
00408             default:
00409             {
00410                 // never happens
00411                 break;
00412             }
00413         }
00414 
00415         // Add signal handler.
00416         g_signal_connect_after(G_OBJECT(g_margin_radios[i]),
00417             "toggled",
00418             G_CALLBACK(on_margin_changed),
00419             (gpointer)i);
00420 
00421         gtk_box_pack_start(GTK_BOX(vbox), g_margin_radios[i], FALSE, FALSE, 0);
00422     }
00423 
00424     return top_level_vbox;
00425 }
00426 
00427 
00428 static void on_margin_changed(GtkWidget *widget, gpointer data)
00429 {
00430     int index = (int)data;
00431     gboolean is_active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
00432 
00433     LOGPRINTF("entry");
00434 
00435     if (is_active == TRUE )
00436     {
00437         if (index >= 0 && index < NUM_MARGINS)
00438         {
00439             g_cur_uds_settings.margin_horizontal = g_margins_horizontal[index];
00440             g_cur_uds_settings.margin_vertical   = g_margins_vertical  [index];
00441         }
00442         else
00443         {
00444             ERRORPRINTF("Invalid index [%d]", index);
00445         }
00446     }
00447 }
00448 
00449 static void init_widgets_with_settings()
00450 {
00451     int i;
00452     int to_be_activated = MARGIN_NORMAL;
00453 
00454     LOGPRINTF("entry");
00455 
00456     for (i = 0; i < NUM_MARGINS; i++)
00457     {
00458         if (   g_cur_uds_settings.margin_horizontal == g_margins_horizontal[i]
00459             && g_cur_uds_settings.margin_vertical   == g_margins_vertical  [i] )
00460         {
00461             to_be_activated = i;
00462             break;  // exit for
00463         }
00464     }
00465 
00466     for (i = 0; i < NUM_MARGINS; i++)
00467     {
00468         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(g_margin_radios[i]),
00469                                       (i == to_be_activated) ? TRUE : FALSE );
00470     }
00471 }
00472 
00473 static gboolean on_focus_in(GtkWidget* widget, gpointer data )
00474 {
00475     LOGPRINTF("entry");
00476 
00477     g_assert(widget != NULL ) ;
00478     ergtk_list_view_set_cursor( ERGTK_LIST_VIEW(widget), 0); // row = 0;
00479     return FALSE;
00480 }
00481 
00482 static gboolean on_focus_out(GtkWidget* widget, gpointer data )
00483 {
00484     LOGPRINTF("entry");
00485 
00486     g_assert(widget != NULL ) ;
00487     GtkTreeSelection* my_selection = gtk_tree_view_get_selection((GtkTreeView*) widget);
00488     g_assert( my_selection != NULL ) ;
00489     gtk_tree_selection_unselect_all(my_selection);
00490     return FALSE;
00491 }
00492 
Generated by  doxygen 1.6.2-20100208