statusbar.c

Go to the documentation of this file.
00001 /*
00002  * File Name: statusbar.c
00003  */
00004 
00005 /*
00006  * This file is part of popupmenu.
00007  *
00008  * popupmenu 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  * popupmenu 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 #include "config.h"
00032 
00033 // system include files, between < >
00034 #include <gtk/gtk.h>
00035 #include <string.h>
00036 
00037 // ereader include files, between < >
00038 #include <libergtk/ergtk.h>
00039 
00040 // local include files, between " "
00041 #include "log.h"
00042 #include "i18n.h"
00043 #include "ipc.h"
00044 #include "pixlist.h"
00045 #include "statusbar.h"
00046 #include "menustore.h"
00047 
00048 
00049 //----------------------------------------------------------------------------
00050 // Global Constants
00051 //----------------------------------------------------------------------------
00052 
00053 static const int  STATUSBAR_HEIGHT     = 43;
00054 static const int  TOOLBAR_MARGIN_LEFT  = 4;
00055 static const int  TOOLBAR_MARGIN_RIGHT = 6;
00056 #if MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00057 static const int  MENUBUTTON_MARGIN = 30;
00058 #endif
00059 
00060 
00061 //----------------------------------------------------------------------------
00062 // Type Declarations
00063 //----------------------------------------------------------------------------
00064 
00065 // for status items
00066 typedef struct  
00067 {
00068     gchar     *itemname;        // used to determine item
00069     GtkWidget *item;            // GTK toolitem, for show/hide functionality
00070     GtkWidget *eventbox;        // GTK eventbox, for click/activate functionality
00071     GtkWidget *image;           // GTK image, image from pixbuf
00072     gint       state;           // used to store the current state, index to stateArray
00073     GArray    *stateArray;      // used for the various images
00074 } statusEntry_t;
00075 
00076 typedef struct 
00077 {
00078     gchar     *statename;
00079     GtkWidget *image;
00080 } stateEntry_t;
00081 
00082 //----------------------------------------------------------------------------
00083 // Static Variables
00084 //----------------------------------------------------------------------------
00085 
00086 static GtkWidget   *statusbar        = NULL;
00087 static GtkWidget   *g_menu_button    = NULL;
00088 static GtkWidget   *g_right_spacer   = NULL;
00089 static int         g_status_width = 0;
00090 #if MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00091 static GtkWidget   *g_toolbar_img[MENUSTORE_NUM_TOOLS];
00092 #endif
00093 static GArray      *statusArray      = NULL;
00094 static GtkWidget   *g_pagecounter    = NULL;
00095 static GtkWidget   *g_leftbutton     = NULL;
00096 static GtkWidget   *g_rightbutton    = NULL;
00097 static gint        g_curpage         = 1;
00098 static gint        g_numpages        = 1;
00099 static gboolean    g_pagecounter_shown = FALSE;
00100 
00101 static GtkWidget   *g_icon_left_enabled   = NULL;
00102 static GtkWidget   *g_icon_left_disabled  = NULL;
00103 static GtkWidget   *g_icon_right_enabled  = NULL;
00104 static GtkWidget   *g_icon_right_disabled = NULL;
00105 static gboolean    g_has_left             = FALSE;
00106 static gboolean    g_has_right            = FALSE;
00107 static dialog_cb_t dialog_cb = NULL;
00108 
00109 
00110 //============================================================================
00111 // Local Function Definitions
00112 //============================================================================
00113 
00114 static stateEntry_t    *get_status_item_state   (statusEntry_t    *pStatusEntry, 
00115                                                  const char       *statename,
00116                                                  gint             *entry);
00117 
00118 static statusEntry_t   *get_status_item         (const char       *item);
00119 
00120 static gboolean         status_pressed_event    (GtkWidget        *widget,
00121                                                  GdkEventButton   *event,
00122                                                  gpointer          user_data);
00123 
00124 static gboolean         on_popup_button_press   (GtkWidget        *widget,
00125                                                  GdkEventButton   *event,
00126                                                  gpointer          data);
00127 
00128 static gboolean         on_leftbutton_press     (GtkWidget        *widget,
00129                                                  GdkEventButton   *event,
00130                                                  gpointer          data);
00131 
00132 static gboolean         on_rightbutton_press    (GtkWidget        *widget,
00133                                                  GdkEventButton   *event,
00134                                                  gpointer          data);
00135 
00136 static void             handle_status_item      (const char       *item,
00137                                                  const char       *state);
00138 
00139 static void             add_system_status_items (void);
00140 
00141 static void             update_pagecounter      (gint curpage, gint numpages);
00142 
00143 
00144 //============================================================================
00145 // Functions Implementation
00146 //============================================================================
00147 
00148 #if MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00149 static gboolean on_toolitem_press(GtkWidget* button, GdkEventButton* event, gpointer data)
00150 {
00151     if (ipc_is_enabled()) {
00152         menustore_activate_toolitem((int)data, ipc_send_item_activated);
00153     }
00154     return FALSE;
00155 }
00156 
00157 
00158 static void add_toolbar_item(int index)
00159 {
00160     if (index > 0) {
00161         GtkWidget *widget = (GtkWidget*) gtk_separator_tool_item_new();
00162         gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(widget), FALSE);
00163         gtk_tool_item_set_expand(GTK_TOOL_ITEM(widget), FALSE); 
00164         gtk_toolbar_insert(GTK_TOOLBAR(statusbar), GTK_TOOL_ITEM(widget), -1);
00165         gtk_widget_set_size_request(widget, 4, -1);
00166         gtk_widget_show(widget);
00167     }
00168     GtkWidget *toolitem = (GtkWidget*)gtk_tool_item_new();
00169 
00170     GtkWidget *eventbox = (GtkWidget *) gtk_event_box_new();
00171     gtk_container_add(GTK_CONTAINER(toolitem), eventbox);
00172     // gtk_widget_set_name(eventbox, "irex-popupmenu-toolitem");
00173     gtk_widget_set_events(eventbox, GDK_BUTTON_PRESS_MASK);
00174     g_signal_connect(eventbox, "button-press-event" , G_CALLBACK(on_toolitem_press), (gpointer)index);
00175     gtk_widget_show(eventbox);
00176 
00177     GtkWidget *image = gtk_image_new();
00178     gtk_container_add(GTK_CONTAINER(eventbox), image);
00179     gtk_widget_show(image);
00180     g_toolbar_img[index] = image;
00181 
00182     gtk_toolbar_insert(GTK_TOOLBAR(statusbar), GTK_TOOL_ITEM(toolitem), -1);
00183     gtk_widget_show(toolitem);
00184 }
00185 
00186 
00187 void statusbar_update_toolbar()
00188 {
00189     if (!menustore_toolbar_has_changed()) return;
00190 
00191     LOGPRINTF("entry");
00192     int limit = menustore_get_tool_limit();
00193     if (limit == MENUSTORE_NUM_TOOLS) {
00194         gtk_widget_hide(g_right_spacer);
00195     } else {
00196         gtk_widget_show(g_right_spacer);
00197     }
00198     int i;
00199     for (i=0; i<MENUSTORE_NUM_TOOLS; i++) {
00200         if (i < limit) {
00201             gtk_image_set_from_pixbuf(GTK_IMAGE(g_toolbar_img[i]), menustore_get_tool_icon(i));
00202             gtk_widget_show(g_toolbar_img[i]);
00203         } else {
00204             gtk_widget_hide(g_toolbar_img[i]);
00205         }
00206     }
00207     menustore_clear_toolbar_changed();
00208 }
00209 #endif
00210 
00211 
00212 static void fix_center_pagebar(int width)
00213 {
00214     LOGPRINTF("entry");
00215     int spacing = width / 2;
00216    // substract size of right hand icons
00217     spacing -= g_status_width;  
00218     GtkRequisition requisition;
00219     gtk_widget_size_request(g_pagecounter, &requisition);
00220     // substract half size of pagecounter widgets: button, text, button, margin
00221     spacing -= (32+requisition.width+32+40)/2; 
00222     if (spacing < 0) spacing = 0;
00223     gtk_widget_set_size_request(g_right_spacer, spacing, -1);
00224 }
00225 
00226 
00227 static void on_size_allocate(GtkWidget *widget, GtkAllocation *allocation, gpointer data)
00228 {
00229     fix_center_pagebar(allocation->width);
00230 }
00231 
00232 
00233 void statusbar_create(dialog_cb_t cb)
00234 {
00235     LOGPRINTF("entry");
00236     dialog_cb = cb;
00237     
00238     GdkColor color;
00239     gdk_color_parse ("#aaaaaa", &color);
00240     
00241     // window 
00242     //   |
00243     GtkWidget *widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00244     gtk_widget_set_name(widget, "irex-statusbar");
00245     GtkWindow *window = GTK_WINDOW(widget);
00246     g_statusbar_window = window;
00247 
00248     // use hint DOCK so it is hidden for fullscreen windows
00249     gtk_window_set_type_hint(window, GDK_WINDOW_TYPE_HINT_DOCK);
00250     gtk_window_set_decorated(window, FALSE);
00251     gtk_window_set_accept_focus(window, FALSE);
00252     gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &color);
00253 
00254     // resize and move to dock at the botton of the screen
00255     gtk_window_set_default_size(window, -1, STATUSBAR_HEIGHT);
00256     int bar_width  = 0;
00257     int bar_height = 0;
00258     gtk_window_get_size(window, &bar_width, &bar_height);
00259     gtk_widget_set_size_request(widget, bar_width, bar_height);
00260     gtk_window_resize(window, bar_width, bar_height);   
00261     gtk_window_move(window, 0, gdk_screen_height());
00262     
00263     gtk_window_set_resizable(window, FALSE);
00264     gtk_widget_show(widget);
00265 
00266     //   |
00267     //   +-- alignment
00268     //         |
00269     GtkWidget *alignment = gtk_alignment_new(0, 0.0, 1.0, 1.0); 
00270     gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 5, 
00271                               TOOLBAR_MARGIN_LEFT, TOOLBAR_MARGIN_RIGHT);
00272     gtk_container_add(GTK_CONTAINER(window), alignment);    
00273     gtk_widget_show(alignment);
00274 
00275     //         |
00276     //         +-- gtktoolbar
00277     //               |
00278     widget = gtk_toolbar_new();
00279     gtk_toolbar_set_orientation(GTK_TOOLBAR(widget), GTK_ORIENTATION_HORIZONTAL);
00280     
00281     gtk_toolbar_set_tooltips(GTK_TOOLBAR(widget), FALSE);
00282     gtk_toolbar_set_show_arrow(GTK_TOOLBAR(widget), FALSE);
00283     gtk_toolbar_set_style(GTK_TOOLBAR(widget), GTK_TOOLBAR_ICONS);
00284     gtk_container_add(GTK_CONTAINER(alignment), widget);
00285     gtk_widget_show(widget);
00286     statusbar = widget;    
00287 
00288     // Add menu button
00289     //               |
00290     //               +-- toolitem 
00291     //               |     |
00292     widget = (GtkWidget *) gtk_tool_item_new();
00293     
00294     //               |     |
00295     //               |     +-- eventbox
00296     //               |
00297     GtkWidget *eventbox = (GtkWidget *) gtk_event_box_new();
00298     gtk_widget_modify_fg (eventbox, GTK_STATE_NORMAL, &color);
00299     gtk_container_add(GTK_CONTAINER(widget), eventbox);
00300     
00301     //               |           |  
00302     //               |           +-- icon
00303     //               |
00304     GtkWidget *icon = gtk_image_new_from_file(PATH_IMG"statusbar_menu_button.png");
00305     gtk_container_add(GTK_CONTAINER(eventbox), icon);
00306     gtk_toolbar_insert(GTK_TOOLBAR(statusbar), GTK_TOOL_ITEM(widget), -1);
00307     g_signal_connect(G_OBJECT(eventbox), "button-release-event", G_CALLBACK(on_popup_button_press), NULL);
00308     gtk_widget_show(icon);
00309     gtk_widget_show(widget);
00310     gtk_widget_show(eventbox);
00311     
00312     //               |
00313     //               +-- toolitem
00314     //               |     |
00315     //               |     +-- button with label
00316     //               |
00317     widget = (GtkWidget *) gtk_tool_item_new();
00318     GtkWidget *button = gtk_button_new_with_label("");
00319     gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
00320     gtk_container_add(GTK_CONTAINER(widget), button);
00321     gtk_toolbar_insert(GTK_TOOLBAR(statusbar), GTK_TOOL_ITEM(widget), -1);
00322     g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_popup_button_press), NULL);
00323     gtk_widget_show(button);
00324     gtk_widget_show(widget);
00325 
00326     g_menu_button = button;
00327 
00328 #if MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00329     widget = (GtkWidget*) gtk_separator_tool_item_new();
00330     gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(widget), FALSE);
00331     gtk_tool_item_set_expand(GTK_TOOL_ITEM(widget), FALSE); 
00332     gtk_toolbar_insert(GTK_TOOLBAR(statusbar), GTK_TOOL_ITEM(widget), -1);
00333     gtk_widget_set_size_request(widget, MENUBUTTON_MARGIN, -1);
00334     gtk_widget_show(widget);
00335 
00336     int i;
00337     for (i=0; i<MENUSTORE_NUM_TOOLS; i++)
00338     {
00339         add_toolbar_item(i);
00340     }
00341 #endif
00342 
00343     // Add left separator
00344     //               |
00345     //               +-- separator
00346     //               |
00347     widget = (GtkWidget*) gtk_separator_tool_item_new();
00348     gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(widget), FALSE);
00349     gtk_tool_item_set_expand(GTK_TOOL_ITEM(widget), TRUE); 
00350     gtk_toolbar_insert(GTK_TOOLBAR(statusbar), GTK_TOOL_ITEM(widget), -1);
00351     gtk_widget_show(widget);
00352 
00353     // Add left button
00354     //               |
00355     //               +-- tool button
00356     //               |
00357     g_icon_left_enabled = gtk_image_new_from_file(PATH_IMG"statusbar_arrow_left.png");
00358     g_object_ref(G_OBJECT(g_icon_left_enabled));
00359     gtk_widget_show(g_icon_left_enabled);
00360 
00361     g_icon_left_disabled = gtk_image_new_from_file(PATH_IMG"statusbar_arrow_left_disabled.png");
00362     g_object_ref(G_OBJECT(g_icon_left_disabled));
00363     gtk_widget_show(g_icon_left_disabled);
00364 
00365     GtkToolItem *leftbutton = gtk_tool_button_new(g_icon_left_disabled, "");
00366     gtk_widget_show(GTK_WIDGET(leftbutton));
00367     gtk_toolbar_insert(GTK_TOOLBAR(statusbar), leftbutton, -1);
00368     g_signal_connect(G_OBJECT(leftbutton), "clicked", G_CALLBACK(on_leftbutton_press), NULL);
00369     g_leftbutton = GTK_WIDGET(leftbutton);
00370 
00371     // Add page counter
00372     //               |
00373     //               +-- toolitem
00374     //               |     |  
00375     //               |     +-- label
00376     //               |
00377     widget = (GtkWidget *) gtk_tool_item_new();
00378     GtkWidget* pageLabel = gtk_label_new("");
00379     gtk_widget_set_name(pageLabel, "irex-page-label");
00380     gtk_widget_show(pageLabel);
00381     gtk_container_add(GTK_CONTAINER(widget), pageLabel);
00382     gtk_toolbar_insert(GTK_TOOLBAR(statusbar), GTK_TOOL_ITEM(widget), -1);
00383     gtk_widget_show(widget);
00384     g_pagecounter = pageLabel;
00385 
00386     // Add right button
00387     //               |
00388     //               +-- tool button
00389     //               |
00390     g_icon_right_enabled = gtk_image_new_from_file(PATH_IMG"statusbar_arrow_right.png");
00391     g_object_ref(G_OBJECT(g_icon_right_enabled));
00392     gtk_widget_show(g_icon_right_enabled);
00393     
00394     g_icon_right_disabled = gtk_image_new_from_file(PATH_IMG"statusbar_arrow_right_disabled.png");
00395     g_object_ref(G_OBJECT(g_icon_right_disabled));
00396     gtk_widget_show(g_icon_right_disabled);
00397 
00398     GtkToolItem *rightbutton = gtk_tool_button_new(g_icon_right_disabled, "");
00399     gtk_widget_show(GTK_WIDGET(rightbutton));
00400     gtk_toolbar_insert(GTK_TOOLBAR(statusbar), rightbutton, -1);
00401     g_signal_connect(G_OBJECT(rightbutton), "clicked", G_CALLBACK(on_rightbutton_press), NULL);
00402     g_rightbutton = GTK_WIDGET(rightbutton);
00403 
00404     // Fill out with blank space
00405     //               |
00406     //               +-- separator
00407     //
00408     widget = (GtkWidget*) gtk_separator_tool_item_new();
00409     gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(widget), FALSE);
00410     gtk_tool_item_set_expand(GTK_TOOL_ITEM(widget), FALSE); 
00411     gtk_toolbar_insert(GTK_TOOLBAR(statusbar), GTK_TOOL_ITEM(widget), -1);
00412     gtk_widget_show(widget);
00413     g_right_spacer = widget;
00414     g_signal_connect(statusbar, "size-allocate", G_CALLBACK(on_size_allocate), NULL);
00415 
00416     // Add system icons here
00417     add_system_status_items();
00418 
00419     // Set defaults
00420     statusbar_set_text();
00421 }
00422 
00423 
00424 /**---------------------------------------------------------------------------
00425  *
00426  * Name :  statusbar_add_item
00427  *
00428  * @brief  Add an item to the status bar
00429  *
00430  * @param  item          Item name
00431  * @param  statename     Name of default state
00432  * @param  is_visible    Set to TRUE to show the item, FALSE to hide
00433  * @param  is_clickable  Set to TRUE to emit a signal when clicked, FALSE otherwise
00434  *
00435  * NOTE:   this function expects an icon image with the name <item>_<statename>.png 
00436  *         in the global icon directory; when <statename> is "normal", it loads <item>.png 
00437  *
00438  * @return Returns TRUE on success, FALSE otherwise
00439  *
00440  *--------------------------------------------------------------------------*/
00441 static gboolean statusbar_add_item(const char *item, const char *statename, gboolean is_visible, gboolean is_clickable)
00442 {
00443     LOGPRINTF("entry");
00444     
00445     GtkWidget     *icon         = NULL;
00446     GtkWidget     *toolitem     = NULL;
00447     GtkWidget     *eventbox     = NULL;
00448     statusEntry_t *pStatusEntry = NULL;
00449 
00450     g_return_val_if_fail(item != NULL, FALSE);
00451     
00452     if (statusArray == NULL)
00453     {
00454         // first item, create array
00455         statusArray = g_array_new(FALSE, TRUE, sizeof(statusEntry_t*));
00456     }
00457     else 
00458     {
00459         // lookup item (if exist, error)
00460         guint i = 0;
00461         for (i=0; i < statusArray->len; i++)
00462         {
00463             pStatusEntry = g_array_index(statusArray, statusEntry_t*, i);
00464             if (strcmp(pStatusEntry->itemname, item) == 0)
00465             {
00466                 WARNPRINTF("`%s` already defined", item);
00467                 return FALSE;
00468             }
00469         }
00470     }
00471 
00472     //  (toolbar) from statusbar_create
00473     //    |
00474     //    +-- toolitem
00475     //          |
00476     toolitem = (GtkWidget *) gtk_tool_item_new();
00477     
00478     //          |
00479     //          +-- eventbox
00480     //                |
00481     eventbox = (GtkWidget *) gtk_event_box_new();
00482     gtk_container_add(GTK_CONTAINER(toolitem), eventbox);
00483     gtk_widget_show(eventbox);
00484     
00485     //                |  
00486     //                +-- icon
00487     //
00488     icon = gtk_image_new_from_pixbuf(pixlist_icon_state(item, statename));
00489     
00490     // increase reference to avoid it being removed on state change
00491     g_object_ref(icon); 
00492     
00493     gtk_container_add(GTK_CONTAINER(eventbox), icon);
00494     gtk_widget_show(icon);
00495     
00496     if (is_clickable)
00497     {
00498         gtk_widget_set_events(eventbox, GDK_BUTTON_PRESS_MASK);
00499         g_signal_connect(G_OBJECT(eventbox), "button_press_event",
00500                          G_CALLBACK(status_pressed_event), NULL);
00501     }
00502 
00503     // add to item to the end of the toolbar
00504     gtk_toolbar_insert(GTK_TOOLBAR(statusbar), GTK_TOOL_ITEM(toolitem), -1);
00505     
00506     if (is_visible)
00507     {
00508         gtk_widget_show(toolitem);
00509     }
00510 
00511     // create, prepare and add state entry
00512     statusEntry_t  *statusEntry = NULL;
00513     statusEntry = g_new0(statusEntry_t, 1);
00514     statusEntry->stateArray = g_array_new(FALSE, TRUE, sizeof(stateEntry_t*));
00515     
00516     stateEntry_t *stateEntry = NULL;
00517     stateEntry = g_new0(stateEntry_t, 1);
00518     stateEntry->image = icon;
00519     stateEntry->statename = g_strdup(statename);
00520     g_array_append_val(statusEntry->stateArray, stateEntry);
00521 
00522     // prepare rest of tool entry and add
00523     statusEntry->itemname = g_strdup(item);
00524     statusEntry->image = icon;
00525     statusEntry->item = toolitem;
00526     statusEntry->eventbox = eventbox;
00527     g_array_append_val(statusArray, statusEntry);
00528 
00529     return TRUE;    
00530 }
00531 
00532 
00533 /**---------------------------------------------------------------------------
00534  *
00535  * Name :  statusbar_add_item_state
00536  *
00537  * @brief  Add a state to a status bar item
00538  *
00539  * @param  item          Item name
00540  * @param  statename     Name of new state
00541  *
00542  * NOTE:   this function expects an icon image with the name <item>_<statename>.png 
00543  *         in the global icon directory; when <statename> is "normal", it loads <item>.png 
00544  *
00545  * @return Returns TRUE on success, FALSE otherwise
00546  *
00547  *--------------------------------------------------------------------------*/
00548 static gboolean statusbar_add_item_state(const char *item, const char *statename)
00549 {
00550     LOGPRINTF("entry");
00551     
00552     GtkWidget     *icon         = NULL;
00553     statusEntry_t *pStatusEntry = NULL;
00554     stateEntry_t  *pStateEntry  = NULL;
00555     
00556     pStatusEntry = get_status_item(item);
00557     if (pStatusEntry == NULL)
00558     {
00559         WARNPRINTF("item `%s` not defined", item);
00560         return FALSE;
00561     }
00562     
00563     pStateEntry = get_status_item_state(pStatusEntry, statename, NULL);
00564     if (pStateEntry != NULL)
00565     {
00566         WARNPRINTF("state `%s.%s` already defined", item, statename);
00567         return FALSE;
00568     }
00569     
00570     // create image widget
00571     icon = gtk_image_new_from_pixbuf(pixlist_icon_state(item, statename));
00572     
00573     // increase reference to avoid it being removed on state change
00574     g_object_ref(icon); 
00575     
00576     // add icon/state
00577     stateEntry_t *stateEntry = NULL;
00578     stateEntry = g_new0(stateEntry_t, 1);
00579     stateEntry->image = icon;
00580     stateEntry->statename = g_strdup(statename);
00581 
00582     // store array
00583     g_array_append_val(pStatusEntry->stateArray, stateEntry);
00584     
00585     return TRUE;    
00586 }
00587 
00588 
00589 gboolean statusbar_item_set_state(const char *item, const char *statename)
00590 {
00591     TRACE("%s() item=%s  statename=%s\n", __func__, item, statename);
00592 
00593     statusEntry_t *pStatusEntry = get_status_item(item);
00594     if (pStatusEntry == NULL)
00595     {
00596         WARNPRINTF("item `%s` not defined", item);
00597         return FALSE;
00598     }
00599  
00600     gint state_index;
00601     stateEntry_t  *pStateEntry = get_status_item_state(pStatusEntry, statename, &state_index);
00602     if (pStateEntry == NULL)
00603     {
00604         WARNPRINTF("state `%s.%s` not defined", item, statename);
00605         return FALSE;
00606     }
00607 
00608     // remove old icon
00609     gtk_container_remove(GTK_CONTAINER(pStatusEntry->eventbox), pStatusEntry->image);
00610     
00611     // set new icon
00612     pStatusEntry->state = state_index;
00613     pStatusEntry->image = pStateEntry->image;
00614     gtk_widget_show(pStatusEntry->image);
00615     gtk_container_add(GTK_CONTAINER(pStatusEntry->eventbox), pStatusEntry->image);
00616     
00617     return TRUE;    
00618 }
00619 
00620 
00621 gboolean statusbar_item_show(const char *item, const char *mode)
00622 {
00623     TRACE("%s() item=%s  mode=%s\n", __func__, item, mode);
00624 
00625     statusEntry_t *pStatusEntry = get_status_item(item);
00626     if (pStatusEntry == NULL)
00627     {
00628         WARNPRINTF("item `%s` not defined", item);
00629         return FALSE;
00630     }
00631     
00632     if (g_ascii_strcasecmp(mode, "show") == 0)
00633     {
00634         gtk_widget_show(pStatusEntry->item);
00635     }
00636     else if (g_ascii_strcasecmp(mode, "hide") == 0)
00637     {
00638         gtk_widget_hide(pStatusEntry->item);
00639     }
00640     else
00641     {
00642         ERRORPRINTF("mode unknown: %s", mode);
00643         return FALSE;
00644     }
00645     
00646     return TRUE;
00647 }
00648 
00649 
00650 gboolean statusbar_remove_item(const char *item)
00651 {
00652     TRACE("%s() item=%s\n", __func__, item);
00653     
00654     statusEntry_t *pStatusEntry = get_status_item(item);
00655     if (pStatusEntry == NULL)
00656     {
00657         WARNPRINTF("item `%s` not defined", item);
00658         return FALSE;
00659     }
00660 
00661     // free state names
00662     guint i = 0;
00663     for (i=0; i < pStatusEntry->stateArray->len; i++)
00664     {
00665         g_free(g_array_index(pStatusEntry->stateArray, stateEntry_t*, i)->statename);
00666     }
00667     
00668     // free tool entry
00669     // icon will be freed automatically as it is toolitem container
00670     gtk_widget_destroy(pStatusEntry->item);
00671     g_array_free(pStatusEntry->stateArray, TRUE);
00672     g_free(pStatusEntry->itemname);
00673     
00674     return TRUE;
00675 }
00676 
00677    
00678 void statusbar_update_battery_state(gint level, const char *state)
00679 {
00680     g_return_if_fail(state!=NULL);
00681 
00682     gchar *item  = "statusbar_battery";
00683 
00684 #if MACHINE_IS_DR800SG || MACHINE_IS_DR800S || MACHINE_IS_DR800SW
00685     const gint four_bars_limit  = 88;
00686     const gint three_bars_limit = 63;
00687     const gint two_bars_limit   = 38;
00688     const gint one_bar_limit    = 13;
00689 #elif MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00690     const gint four_bars_limit  = 75;
00691     const gint three_bars_limit = 50;
00692     const gint two_bars_limit   = 25;
00693     const gint one_bar_limit    = 10;
00694 #else
00695 #error "Unhandled machine type"
00696 #endif
00697     
00698     static const gchar *last_icon = NULL;
00699     const gchar *icon = NULL;
00700     
00701     if (strcmp(state, "charging") == 0)
00702     {
00703         // charging, show level
00704         if (level >= four_bars_limit)
00705         {
00706             icon = "100_charging";
00707         }
00708         else if (level >= three_bars_limit)
00709         {
00710             icon = "75_charging";
00711         }
00712         else if (level >= two_bars_limit)
00713         {
00714             icon = "50_charging";
00715         }
00716         else if (level >= one_bar_limit)
00717         {
00718             icon = "25_charging";
00719         }
00720         else 
00721         {
00722             icon = "charging";
00723         }
00724     }
00725     else if (strcmp(state, "discharging") == 0)
00726     {
00727         // discharging, show level
00728         if (level > four_bars_limit)
00729         {
00730             icon = "100";
00731         }
00732         else if (level > three_bars_limit)
00733         {
00734             icon = "75";
00735         }
00736         else if (level > two_bars_limit)
00737         {
00738             icon = "50";
00739         }
00740         else if (level > one_bar_limit)
00741         {
00742             icon = "25";
00743         }
00744         else
00745         {
00746             icon = "normal";
00747         }
00748     }
00749     else if (strcmp(state, "low") == 0)
00750     {
00751         icon = "verylow";
00752     }
00753     else if (strcmp(state, "full") == 0)
00754     {
00755         icon = "100";
00756     }
00757     else
00758     {
00759         ERRORPRINTF("unhandled state [%s] level [%d]", state, level);
00760     }
00761         
00762     if (icon && (icon != last_icon))
00763     {
00764         // update icon to reflect new state
00765         statusbar_item_set_state(item, icon);
00766         last_icon = icon;
00767     }
00768 }
00769 
00770 
00771 void statusbar_update_signal_strength(const char *medium, gint strength)
00772 {
00773     gchar *item = NULL;
00774     const gchar *icon = NULL;
00775     if (strcmp(medium,"3g")==0) {
00776         item  = "statusbar_3g"; 
00777     } else {
00778         WARNPRINTF("Unhandled signal strength update on medium %s", medium);
00779         return;
00780     }
00781 
00782     if (strength>=90)
00783         icon = "connected_5b";
00784     else if (strength>=70)
00785         icon = "connected_4b";
00786     else if (strength>=50)
00787         icon = "connected_3b";
00788     else if (strength>=30)
00789         icon = "connected_2b";
00790     else if (strength>=10)
00791         icon = "connected_1b";
00792     else
00793         icon = "connected";
00794         
00795     statusbar_item_set_state(item, icon);
00796 }
00797 static void enable_left(gboolean enabled)
00798 {
00799     if (g_has_left == enabled) return;
00800     g_has_left = enabled;
00801     if (enabled) {
00802         gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(g_leftbutton), g_icon_left_enabled);
00803     } else {
00804         gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(g_leftbutton), g_icon_left_disabled);
00805     }
00806 }
00807 
00808 
00809 static void enable_right(gboolean enabled)
00810 {
00811     if (g_has_right == enabled) return;
00812     g_has_right = enabled;
00813     if (enabled) {
00814         gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(g_rightbutton), g_icon_right_enabled);
00815     } else {
00816         gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(g_rightbutton), g_icon_right_disabled);
00817     }
00818 }
00819 
00820 
00821 void statusbar_update_pagecounter(gint curpage, gint numpages, gboolean boundary_check)
00822 {
00823     LOGPRINTF("entry curpage [%d] numpages [%d] boundary_check [%d] has_left [%d] has_right [%d] g_pagecounter_shown [%d]", curpage, numpages, boundary_check, g_has_left, g_has_right, g_pagecounter_shown);
00824 
00825     if ((curpage == 0) && (numpages == 0))
00826     {
00827         if (g_pagecounter_shown)
00828         {
00829             statusbar_hide_pagecounter();
00830         }
00831     }
00832     else if ((curpage == -1) && (numpages == -1))   // magic value for Counting pages...
00833     {
00834         update_pagecounter(curpage, numpages);
00835         gtk_widget_show(g_pagecounter);
00836 
00837         // Ignore parameter boundary_check.
00838         // Enable previous-/next-page arrows.
00839         enable_left(TRUE);
00840         enable_right(TRUE);
00841         gtk_widget_show(g_leftbutton);
00842         gtk_widget_show(g_rightbutton);
00843     }
00844     else
00845     {
00846         update_pagecounter(curpage, numpages);
00847         
00848         if (curpage == 1 && boundary_check)
00849         {
00850             enable_left(FALSE);
00851         } else {
00852             enable_left(TRUE);
00853         }
00854         
00855         if (curpage == numpages && boundary_check)
00856         {
00857             enable_right(FALSE);
00858         } else {
00859             enable_right(TRUE);
00860         }
00861 
00862         if (!g_pagecounter_shown)
00863         {
00864             gtk_widget_show(g_pagecounter);
00865             gtk_widget_show(g_leftbutton);
00866             gtk_widget_show(g_rightbutton);
00867             g_pagecounter_shown = TRUE;
00868         }
00869     }
00870         
00871     // save for possible update on locale change
00872     g_curpage = curpage;
00873     g_numpages = numpages;
00874     
00875     LOGPRINTF("leave has_left [%d] has_right [%d] g_pagecounter_shown [%d]", g_has_left, g_has_right, g_pagecounter_shown);
00876 }
00877 
00878 
00879 void statusbar_hide_pagecounter()
00880 {
00881     LOGPRINTF("entry");
00882 
00883     gtk_widget_hide(g_pagecounter);
00884     gtk_widget_hide(g_leftbutton);
00885     gtk_widget_hide(g_rightbutton);
00886     g_pagecounter_shown = FALSE;
00887 }
00888 
00889 
00890 void statusbar_set_text(void)
00891 {
00892     update_pagecounter(g_curpage, g_numpages);
00893     gtk_button_set_label(GTK_BUTTON(g_menu_button), _("Menu"));
00894     
00895     GtkRequisition requisition;
00896     gtk_widget_size_request(statusbar, &requisition);
00897     fix_center_pagebar(requisition.width);
00898 }
00899 
00900 
00901 //============================================================================
00902 // Local Functions Implementation
00903 //============================================================================
00904 
00905 static void add_system_status_items()
00906 {
00907     LOGPRINTF("entry");
00908     
00909     const char *item = NULL;
00910     
00911     // NOTE: add items left to right
00912     // notifications go first to so they are leftmost
00913     
00914     static gboolean has_stylus    = FALSE;
00915     static gboolean has_wifi      = FALSE;
00916     static gboolean has_bluetooth = FALSE;
00917     static gboolean has_3g        = FALSE;
00918     ipc_get_device_capabilities(&has_stylus, &has_wifi, &has_bluetooth, &has_3g);
00919 
00920     int width = 0;
00921 
00922     // stylus selection mode - show only when stylus is available
00923     item = "statusbar_stylus";
00924     statusbar_add_item(      item, "none", has_stylus, TRUE);
00925     statusbar_add_item_state(item, "pointer");
00926     statusbar_add_item_state(item, "eraser");
00927     statusbar_add_item_state(item, "pan");
00928     statusbar_add_item_state(item, "pen");
00929     statusbar_add_item_state(item, "zoom");
00930     statusbar_add_item_state(item, "lookup");
00931     width += 50;    // NOTE hardcoded from icon
00932 
00933 #if MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00934     // sensor lock status
00935     item = "statusbar_lock";
00936     statusbar_add_item(      item, "normal", TRUE, TRUE);
00937     statusbar_add_item_state(item, "locked");
00938     width += 50;    // NOTE hardcoded from icon
00939 #endif
00940 
00941     if (has_3g || has_wifi || has_bluetooth)
00942     {
00943         // download manager status
00944         item = "statusbar_downloadmgr";
00945         statusbar_add_item(      item, "normal", TRUE, TRUE);
00946         statusbar_add_item_state(item, "downloading");
00947         statusbar_add_item_state(item, "notify");
00948         statusbar_add_item_state(item, "error");
00949         width += 50;    // NOTE hardcoded from icon
00950     }
00951 
00952     if (has_3g)
00953     {
00954         // 3g connection status
00955         item = "statusbar_3g";
00956         statusbar_add_item(      item, "disconnected", TRUE, TRUE);
00957         statusbar_add_item_state(item, "connected");
00958         statusbar_add_item_state(item, "flightmode");
00959         statusbar_add_item_state(item, "disabled");
00960         statusbar_add_item_state(item, "connected_1b");
00961         statusbar_add_item_state(item, "connected_2b");
00962         statusbar_add_item_state(item, "connected_3b");
00963         statusbar_add_item_state(item, "connected_4b");
00964         statusbar_add_item_state(item, "connected_5b");
00965         width += 50;    // NOTE hardcoded from icon
00966     }
00967 
00968     // battery status
00969     item = "statusbar_battery";
00970     statusbar_add_item(      item, "normal", TRUE, TRUE);
00971     statusbar_add_item_state(item, "100_charging");
00972     statusbar_add_item_state(item, "75_charging");
00973     statusbar_add_item_state(item, "50_charging");
00974     statusbar_add_item_state(item, "25_charging");
00975     statusbar_add_item_state(item, "100");
00976     statusbar_add_item_state(item, "75");
00977     statusbar_add_item_state(item, "50");
00978     statusbar_add_item_state(item, "25");
00979     statusbar_add_item_state(item, "charging");
00980     statusbar_add_item_state(item, "verylow");
00981     width += 50;    // NOTE hardcoded from icon
00982 
00983     g_status_width = width;
00984 }
00985 
00986 
00987 static statusEntry_t *get_status_item(const char *item)
00988 {
00989     if ((item == NULL) || (statusArray == NULL))
00990     {
00991         return NULL;
00992     }
00993     
00994     // lookup item
00995     guint i = 0;
00996     for (i=0; i < statusArray->len; i++)
00997     {
00998         statusEntry_t *pStatusEntry = g_array_index(statusArray, statusEntry_t*, i);
00999         if (strcmp(pStatusEntry->itemname, item) == 0)
01000         {
01001             return pStatusEntry;
01002         }
01003     }
01004     return NULL;
01005 }
01006 
01007 
01008 static stateEntry_t *get_status_item_state(statusEntry_t *pStatusEntry, const char *statename, gint *entry)
01009 {
01010     guint i = 0;
01011     for (i=0; i < pStatusEntry->stateArray->len; i++)
01012     {
01013         stateEntry_t *pStateEntry = g_array_index(pStatusEntry->stateArray, stateEntry_t*, i);
01014         if (strcmp(pStateEntry->statename, statename) == 0)
01015         {
01016             if (entry != NULL)
01017             {
01018                 *entry = i;
01019             }
01020             return pStateEntry;
01021         }
01022     }
01023     return NULL;
01024 }
01025 
01026 
01027 static gboolean status_pressed_event(GtkWidget      *widget,
01028                                      GdkEventButton *event,
01029                                      gpointer        user_data)
01030 {
01031     LOGPRINTF("entry");
01032 
01033     if (!ipc_is_enabled()) return FALSE;
01034 
01035     statusEntry_t *pStatusEntry = NULL;
01036     
01037     if (statusArray != NULL)
01038     {
01039         guint i;
01040         for (i=0; i < statusArray->len; i++)
01041         {
01042             pStatusEntry = g_array_index(statusArray, statusEntry_t*, i);
01043              
01044             if (pStatusEntry->eventbox == widget)
01045             {
01046                 stateEntry_t *pStateEntry = NULL;
01047                 pStateEntry = g_array_index(pStatusEntry->stateArray, stateEntry_t*, pStatusEntry->state);
01048                 LOGPRINTF("pressed %s, state %d (%s)", pStatusEntry->itemname, pStatusEntry->state, pStateEntry->statename);
01049                 
01050                 handle_status_item(pStatusEntry->itemname, pStateEntry->statename);
01051                   
01052                 // don't propagate 
01053                 return TRUE;
01054             }
01055         }
01056     }
01057 
01058     // propagate further
01059     return FALSE;
01060 }
01061 
01062 
01063 static gboolean on_popup_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data)
01064 {
01065     LOGPRINTF("entry");
01066     if (ipc_is_enabled()) ipc_send_request_popup("toggle");
01067     LOGPRINTF("leave");
01068     // event handled
01069     return TRUE;
01070 }
01071 
01072 
01073 static gboolean on_leftbutton_press(GtkWidget *widget, GdkEventButton *event, gpointer data)
01074 {
01075     LOGPRINTF("entry");
01076     
01077     if (ipc_is_enabled() && g_has_left)
01078     {
01079         ipc_send_page_change("prev");
01080     }
01081     // event handled
01082     return TRUE;
01083 }
01084 
01085 
01086 static gboolean on_rightbutton_press(GtkWidget *widget, GdkEventButton *event, gpointer data)
01087 {
01088     LOGPRINTF("entry");
01089     
01090     if (ipc_is_enabled() && g_has_right)
01091     {
01092         ipc_send_page_change("next");
01093     }
01094     // event handled
01095     return TRUE;
01096 }
01097 
01098 
01099 static void update_pagecounter(int curpage, int numpages)
01100 {
01101     if (curpage == -1 && numpages == -1) {
01102         // magic numbers for counting pages
01103         gtk_label_set_text(GTK_LABEL(g_pagecounter), _("Counting pages..."));
01104     } else {
01105         /* TRANSLATORS: %1$d is replaced by the current page
01106          *              %2$d is replaced by the total number of pages
01107          *              Example: 'page 9 of 40' */
01108         gchar *cp = g_strdup_printf( _("page %1$d of %2$d"), curpage, numpages);
01109         gtk_label_set_text(GTK_LABEL(g_pagecounter), cp);
01110         g_free(cp);
01111     }
01112 }
01113 
01114 
01115 static void handle_status_item(const char *item, const char *state)
01116 {
01117     LOGPRINTF("entry: item [%s] state [%s]", item, state);
01118 
01119 #if MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
01120     if (strcmp(item, "statusbar_lock") == 0)
01121     {
01122         // toggle sensor lock
01123         //
01124         if (strcmp(state, "normal") == 0)
01125         {
01126           ipc_send_item_activated("lock", "general", menustore_get_current_menu(), "normal", DBUS_SERVICE_SYSTEM_CONTROL);
01127         }
01128         else if (strcmp(state, "locked") == 0)
01129         {
01130           ipc_send_item_activated("lock", "general", menustore_get_current_menu(), "selected", DBUS_SERVICE_SYSTEM_CONTROL);
01131         }
01132         else
01133         {
01134             LOGPRINTF("unknown state `%s` for %s", state, item);
01135         }
01136     } else
01137 #endif
01138     if (strcmp(item, "statusbar_stylus") == 0)
01139     {
01140         // send statusItemActivated message to application
01141         //
01142         const gchar *service = menustore_get_current_service();
01143         if (service && (service[0]!='\0'))
01144         {
01145             ipc_send_status_item_activated(item, state, service);
01146         }
01147     }        
01148     else if ( (strcmp(item, "statusbar_downloadmgr") == 0)
01149            || (strcmp(item, "statusbar_3g") == 0) )
01150     {
01151         // send statusItemActivated message to System Daemon
01152         //
01153         ipc_send_status_item_activated(item, state, DBUS_SERVICE_SYSTEM_CONTROL);
01154     }
01155     else if (strcmp(item, "statusbar_battery") == 0)
01156     {
01157         // get battery info and show dialog
01158         //
01159         gchar *charge_state = NULL;
01160         gchar *message      = NULL;
01161         gint  batt_level    = 0;
01162         
01163         if (ipc_get_battery_state(&batt_level, &charge_state, NULL))
01164         {
01165             if ((strcmp(charge_state, "charging")==0) || (strcmp(charge_state, "discharging")==0))
01166             {
01167                 if (batt_level == 100)
01168                 {
01169                     message = g_strdup_printf(_("Fully charged (100%%%%)"));
01170                 }
01171                 else
01172                 {
01173                     message = g_strdup_printf(_("%d%%%% available"), batt_level);
01174                 }
01175             }
01176             else if (strcmp(charge_state, "full")==0)
01177             {
01178                 message = g_strdup_printf(_("Fully charged (100%%%%)"));
01179             }
01180             else if (strcmp(charge_state, "low")==0)
01181             {
01182                 message = g_strdup_printf(_("Almost empty, %d%%%% remaining"), batt_level);
01183             }
01184             
01185             if (message)
01186             {
01187                 dialog_cb(GTK_MESSAGE_INFO, _("Battery"), message, NULL, NULL);
01188             }
01189             
01190             g_free(charge_state);
01191             g_free(message);
01192         }
01193     }
01194 }
01195 
Generated by  doxygen 1.6.2-20100208