libergtk/src/erGtkEntry.c File Reference

ereader gtk library - GtkEntry object adapted for ereader system More...

#include <string.h>
#include <ctype.h>
#include <gtk/gtk.h>
#include "ergtklog.h"
#include "erGtkEntry.h"
#include "erGtkEntryFilter.h"

Go to the source code of this file.

Enumerations

enum  { SIGNAL_CHANGED_STABLE = 0, SIGNAL_SCREEN_REFRESH, LAST_SIGNAL }

Functions

static void ergtk_entry_grab_focus (GtkWidget *widget)
static void ergtk_entry_notify (GObject *object, GParamSpec *pspec)
static gboolean ergtk_entry_focus_in (GtkWidget *widget, GdkEventFocus *event)
static gboolean ergtk_entry_focus_out (GtkWidget *widget, GdkEventFocus *event)
static gboolean ergtk_entry_focus (GtkWidget *widget, GtkDirectionType arg1)
static gboolean ergtk_entry_button_release (GtkWidget *widget, GdkEventButton *event)
static void ergtk_entry_move_cursor (GtkEntry *widget, GtkMovementStep arg1, gint arg2, gboolean arg3)
static void ergtk_entry_changed (GtkEditable *widget)
static void ergtk_entry_real_set_text (erGtkEntry *er_entry, const gchar *text)
static void ergtk_entry_class_init (erGtkEntryClass *klass)
static void ergtk_entry_editable_init (GtkEditableClass *iface)
static void ergtk_entry_init (erGtkEntry *input_entry)
static gboolean ergtk_entry_delayed_changed_or_movecursor (gpointer user_data)
GtkWidget * ergtk_entry_new ()
void ergtk_entry_set_ipv4_filter (erGtkEntry *er_entry)
void ergtk_entry_set_integer_filter (erGtkEntry *er_entry)
gboolean ergtk_entry_check_field (erGtkEntry *er_entry)
GType ergtk_entry_get_type (void)
void ergtk_entry_set_text (erGtkEntry *er_entry, const gchar *text)

Variables

static GtkEntryClass * g_parent_class = NULL
static gint g_signals [LAST_SIGNAL]


Detailed Description

ereader gtk library - GtkEntry object adapted for ereader system

Emits signal "changed-stable" shortly after the latest change of the entry text. Emits signal "screen-refresh" when a screen refresh is needed for the entry object.

Copyright (C) 2007 iRex Technologies B.V. All rights reserved.

Definition in file erGtkEntry.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
SIGNAL_CHANGED_STABLE 
SIGNAL_SCREEN_REFRESH 
LAST_SIGNAL 

Definition at line 49 of file erGtkEntry.c.

00050 {
00051     SIGNAL_CHANGED_STABLE = 0,       // changed + additional delay to wait for next signal
00052     SIGNAL_SCREEN_REFRESH,           // request screen refresh
00053     LAST_SIGNAL
00054 };


Function Documentation

static gboolean ergtk_entry_button_release ( GtkWidget *  widget,
GdkEventButton *  event 
) [static]

Definition at line 460 of file erGtkEntry.c.

00461 {
00462     g_return_val_if_fail(ERGTK_IS_ENTRY(widget), FALSE);
00463 
00464     gboolean    rc = FALSE;
00465     erGtkEntry* er_entry = (erGtkEntry*)widget;
00466 
00467     // chain to parent class
00468     if (g_parent_class->parent_class.button_release_event)
00469     {
00470         rc = g_parent_class->parent_class.button_release_event(widget, event);
00471     }
00472     
00473     g_signal_emit(er_entry, g_signals[SIGNAL_SCREEN_REFRESH], 0, GTK_WIDGET(er_entry), NULL);
00474     return rc;
00475 }

static void ergtk_entry_changed ( GtkEditable *  widget  )  [static]

Definition at line 403 of file erGtkEntry.c.

00404 {
00405     g_return_if_fail(ERGTK_IS_ENTRY(editable));
00406 
00407     erGtkEntry* er_entry = (erGtkEntry*)editable;
00408     GtkEntry*   entry    = (GtkEntry*)editable;
00409     GtkWidget*  widget   = (GtkWidget*)editable;
00410 
00411     // for protected object, show content when empty
00412     if (   er_entry->visible == FALSE
00413         && gtk_widget_is_focus(widget) )
00414     {
00415         const gchar* text = gtk_entry_get_text(entry);
00416         if (text[0] == '\0')
00417         {
00418             gtk_entry_set_visibility(entry, TRUE);
00419         }
00420     }
00421 
00422     if (er_entry->changed_pending)
00423     {
00424         // changed event from ..set_text() -> ignore
00425         er_entry->changed_pending = FALSE;
00426     }
00427     else
00428     {
00429         // (re)start timer that will do the display update
00430         if (er_entry->timeout_id > 0)
00431         {
00432             g_source_remove(er_entry->timeout_id);
00433         }
00434         er_entry->timeout_id = g_timeout_add(300, ergtk_entry_delayed_changed_or_movecursor, er_entry);
00435         er_entry->changed_occurred = TRUE;
00436     }
00437 }

Here is the call graph for this function:

gboolean ergtk_entry_check_field ( erGtkEntry er_entry  ) 

Definition at line 103 of file erGtkEntry.c.

00104 {
00105     GtkEntry    *entry;
00106     const gchar *text;
00107     gint         i, len, ret;
00108     gboolean     valid = FALSE;
00109 
00110     g_return_val_if_fail(ERGTK_IS_ENTRY(er_entry), FALSE);
00111 
00112     entry = GTK_ENTRY(er_entry);
00113     text = gtk_entry_get_text(entry);
00114     if (text && (text[0] != '\0'))
00115     {
00116         switch (er_entry->filter)
00117         {
00118             case ipAddress_e:
00119                 ret = ipv4_filter_check_address(text);
00120                 if (ret == ipv4Complete_e)
00121                 {
00122                     valid = TRUE;
00123                 }
00124                 break;
00125 
00126             case integer_e:
00127                 valid = TRUE;
00128                 len = strlen(text);
00129                 for (i = 0; i < len; i++)
00130                 {
00131                     if (!isdigit(text[i]))
00132                     {
00133                         valid = FALSE;
00134                         break;
00135                     }
00136                 }
00137                 break;
00138             case string_e:
00139             default:
00140                 valid = TRUE;
00141                 break;
00142         }
00143     }
00144 
00145     LOGPRINTF("return %d", valid);
00146     return valid;
00147 }

Here is the call graph for this function:

static void ergtk_entry_class_init ( erGtkEntryClass klass  )  [static]

Definition at line 182 of file erGtkEntry.c.

00183 {
00184     LOGPRINTF("entry");
00185 
00186     GObjectClass*   object_class = (GObjectClass*  )klass;
00187     GtkWidgetClass* widget_class = (GtkWidgetClass*)klass;
00188     GtkEntryClass*  entry_class  = (GtkEntryClass* )klass;
00189 
00190     // remember parent class struct, needed for chaining up to parent class
00191     g_parent_class = g_type_class_peek_parent(klass);
00192 
00193     // overload some virtual methods
00194     object_class->notify = ergtk_entry_notify;
00195     //
00196     widget_class->button_release_event = ergtk_entry_button_release;
00197     widget_class->focus_in_event       = ergtk_entry_focus_in;
00198     widget_class->focus_out_event      = ergtk_entry_focus_out;
00199     widget_class->focus                = ergtk_entry_focus;
00200     widget_class->grab_focus           = ergtk_entry_grab_focus;
00201     //
00202     entry_class->move_cursor = ergtk_entry_move_cursor;
00203     //
00204     klass->set_text          = ergtk_entry_real_set_text;
00205 
00206     // event to notify entry text has changed
00207     g_signals[SIGNAL_CHANGED_STABLE] = g_signal_new( "changed-stable",
00208                                                      G_OBJECT_CLASS_TYPE(object_class),
00209                                                      G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
00210                                                      G_STRUCT_OFFSET(erGtkEntryClass, changed_stable),   // class closure
00211                                                      NULL,         // accumulator
00212                                                      NULL,         // accu data
00213                                                      gtk_marshal_VOID__VOID,
00214                                                      G_TYPE_NONE,  // return type
00215                                                      0,            // #params
00216                                                      0 );          // param types
00217     // event to notify screen refresh is needed
00218     g_signals[SIGNAL_SCREEN_REFRESH] = g_signal_new( "screen-refresh",
00219                                                      G_OBJECT_CLASS_TYPE(object_class),
00220                                                      G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
00221                                                      G_STRUCT_OFFSET(erGtkEntryClass, screen_refresh),   // class closure
00222                                                      NULL,         // accumulator
00223                                                      NULL,         // accu data
00224                                                      gtk_marshal_VOID__VOID,
00225                                                      G_TYPE_NONE,  // return type
00226                                                      0,            // #params
00227                                                      0 );          // param types
00228 }

Here is the call graph for this function:

static gboolean ergtk_entry_delayed_changed_or_movecursor ( gpointer  user_data  )  [static]

Definition at line 477 of file erGtkEntry.c.

00478 {
00479     g_assert(ERGTK_IS_ENTRY(user_data));
00480 
00481     erGtkEntry* er_entry = (erGtkEntry*)user_data;
00482 
00483     // inform clients
00484     if (er_entry->movecursor_occurred)
00485     {
00486         er_entry->movecursor_occurred = FALSE; 
00487         g_signal_emit(er_entry, g_signals[SIGNAL_SCREEN_REFRESH], 0, GTK_WIDGET(er_entry), NULL);
00488     }
00489     if (er_entry->changed_occurred)
00490     {
00491         er_entry->changed_occurred = FALSE;
00492         g_signal_emit(er_entry, g_signals[SIGNAL_CHANGED_STABLE], 0, GTK_WIDGET(er_entry), NULL);
00493         g_signal_emit(er_entry, g_signals[SIGNAL_SCREEN_REFRESH], 0, GTK_WIDGET(er_entry), NULL);
00494     }
00495 
00496     er_entry->timeout_id = 0;
00497     return FALSE;  // FALSE = don't call again
00498 }

static void ergtk_entry_editable_init ( GtkEditableClass *  iface  )  [static]

Definition at line 231 of file erGtkEntry.c.

00232 {
00233     iface->changed = ergtk_entry_changed;
00234 }

Here is the call graph for this function:

static gboolean ergtk_entry_focus ( GtkWidget *  widget,
GtkDirectionType  arg1 
) [static]

Definition at line 374 of file erGtkEntry.c.

00375 {
00376     g_return_val_if_fail(ERGTK_IS_ENTRY(widget), FALSE);
00377 
00378     gboolean    rc = FALSE;
00379     erGtkEntry* er_entry = (erGtkEntry*)widget;
00380 
00381     // chain to parent class
00382     if (g_parent_class->parent_class.focus)
00383     {
00384         rc = g_parent_class->parent_class.focus(widget, arg1);
00385     }
00386 
00387     g_signal_emit(er_entry, g_signals[SIGNAL_SCREEN_REFRESH], 0, GTK_WIDGET(er_entry), NULL);
00388     return rc;
00389 }

static gboolean ergtk_entry_focus_in ( GtkWidget *  widget,
GdkEventFocus *  event 
) [static]

Definition at line 320 of file erGtkEntry.c.

00321 {
00322     g_return_val_if_fail(ERGTK_IS_ENTRY(widget), FALSE);
00323 
00324     gboolean    rc = FALSE;
00325     GtkEntry*   entry    = (GtkEntry*)widget;
00326     erGtkEntry* er_entry = (erGtkEntry*)widget;
00327 
00328     // chain to parent class
00329     if (g_parent_class->parent_class.focus_in_event)
00330     {
00331         rc = g_parent_class->parent_class.focus_in_event(widget, event);
00332     }
00333 
00334     // if protected, show content when empty
00335     er_entry->visible = gtk_entry_get_visibility(entry);
00336     if (er_entry->visible == FALSE)
00337     {
00338         const gchar* text = gtk_entry_get_text(entry);
00339         if (text[0] == '\0')
00340         {
00341             gtk_entry_set_visibility(entry, TRUE);
00342         }
00343     }
00344     
00345     return rc;
00346 }

static gboolean ergtk_entry_focus_out ( GtkWidget *  widget,
GdkEventFocus *  event 
) [static]

Definition at line 348 of file erGtkEntry.c.

00349 {
00350     g_return_val_if_fail(ERGTK_IS_ENTRY(widget), FALSE);
00351 
00352     gboolean    rc = FALSE;
00353     GtkEntry*   entry    = GTK_ENTRY(widget);
00354     erGtkEntry* er_entry = ERGTK_ENTRY(widget);
00355 
00356     // chain to parent class
00357     if (g_parent_class->parent_class.focus_out_event)
00358     {
00359         rc = g_parent_class->parent_class.focus_out_event(widget, event);
00360     }
00361 
00362     // de-select characters
00363     gtk_editable_select_region(GTK_EDITABLE(entry), -1, -1);
00364 
00365     // if protected, hide content
00366     if (er_entry->visible == FALSE)
00367     {
00368         gtk_entry_set_visibility(entry, FALSE);
00369     }
00370     
00371     return rc;
00372 }

GType ergtk_entry_get_type ( void   ) 

get type of erGtkEntry widget

Returns:
type

Definition at line 149 of file erGtkEntry.c.

00150 {
00151     static GType class_type = 0;
00152 
00153     if (class_type == 0)
00154     {
00155         static const GTypeInfo class_info =
00156         {
00157             sizeof(erGtkEntryClass),
00158             NULL,               /* base_init */
00159             NULL,               /* base_finalize */
00160             (GClassInitFunc) ergtk_entry_class_init,
00161             NULL,               /* class_finalize */
00162             NULL,               /* class_data */
00163             sizeof(erGtkEntry),
00164             0,                  /* n_preallocs */
00165             (GInstanceInitFunc) ergtk_entry_init,
00166         };
00167         class_type = g_type_register_static(GTK_TYPE_ENTRY, "erGtkEntry", &class_info, 0);
00168 
00169         static const GInterfaceInfo editable_info =
00170         {
00171             (GInterfaceInitFunc)ergtk_entry_editable_init, /* interface_init */
00172             NULL, /* interface_finalize */
00173             NULL  /* interface_data */
00174         };
00175         g_type_add_interface_static(class_type, GTK_TYPE_EDITABLE, &editable_info);
00176     }
00177 
00178     return class_type;
00179 }

Here is the call graph for this function:

static void ergtk_entry_grab_focus ( GtkWidget *  widget  )  [static]

Definition at line 391 of file erGtkEntry.c.

00392 {
00393     g_return_if_fail(ERGTK_IS_ENTRY(widget));
00394 
00395     // chain to parent class
00396     if (   gtk_widget_is_focus(widget) == FALSE
00397         && g_parent_class->parent_class.grab_focus )
00398     {
00399         g_parent_class->parent_class.grab_focus(widget);
00400     }
00401 }

static void ergtk_entry_init ( erGtkEntry input_entry  )  [static]

Definition at line 237 of file erGtkEntry.c.

00238 {
00239     g_return_if_fail(ERGTK_IS_ENTRY(er_entry));
00240 
00241     GtkEntry*  entry  = (GtkEntry*) er_entry;
00242     GtkWidget* widget = (GtkWidget*)er_entry;
00243     
00244     // E-ink display requires a non-blinking cursur
00245     g_object_set(gtk_widget_get_settings(widget), "gtk-cursor-blink", FALSE, NULL);
00246     
00247     // set default size and attributes
00248     gtk_entry_set_editable(entry, TRUE);
00249     gtk_widget_set_size_request(widget, ERGTK_ENTRY_DEFAULT_WIDTH, ERGTK_ENTRY_DEFAULT_HEIGHT);
00250     gtk_entry_set_visibility(entry, TRUE);
00251    
00252     // instance-private data
00253     er_entry->timeout_id          = 0;
00254     er_entry->changed_pending     = FALSE;
00255     er_entry->changed_occurred    = FALSE;
00256     er_entry->movecursor_occurred = FALSE;
00257     er_entry->visible             = TRUE;
00258     er_entry->filter              = string_e;
00259 }

static void ergtk_entry_move_cursor ( GtkEntry *  widget,
GtkMovementStep  arg1,
gint  arg2,
gboolean  arg3 
) [static]

Definition at line 439 of file erGtkEntry.c.

00440 {
00441     g_return_if_fail(ERGTK_IS_ENTRY(widget));
00442 
00443     erGtkEntry* er_entry = (erGtkEntry*)widget;
00444 
00445     // chain to parent class
00446     if (g_parent_class->move_cursor)
00447     {
00448         g_parent_class->move_cursor(widget, arg1, arg2, arg3);
00449     }
00450 
00451     // (re)start timer that triggers ..-stable signal
00452     if (er_entry->timeout_id > 0)
00453     {
00454         g_source_remove(er_entry->timeout_id);
00455     }
00456     er_entry->timeout_id = g_timeout_add(300, ergtk_entry_delayed_changed_or_movecursor, er_entry);
00457     er_entry->movecursor_occurred = TRUE;
00458 }

Here is the call graph for this function:

GtkWidget* ergtk_entry_new (  ) 

creates a new erGtkEntry widget

Parameters:
- 
Returns:
reference to created widget

Definition at line 80 of file erGtkEntry.c.

00081 {
00082     erGtkEntry* item = (erGtkEntry*) g_object_new(ERGTK_ENTRY_TYPE, NULL);
00083 
00084     return GTK_WIDGET(item);
00085 }

static void ergtk_entry_notify ( GObject *  object,
GParamSpec *  pspec 
) [static]

Definition at line 297 of file erGtkEntry.c.

00298 {
00299     g_return_if_fail(ERGTK_IS_ENTRY(object));
00300 
00301     GtkWidget* widget = (GtkWidget*)object;
00302 
00303     // chain to parent class
00304     GObjectClass* parent_object_class = G_OBJECT_CLASS(g_parent_class);
00305     if (parent_object_class->notify)
00306     {
00307         parent_object_class->notify(object, pspec);
00308     }
00309 
00310     gboolean     b;
00311     const gchar* name = pspec->name;
00312 
00313     if (strcmp(name, "editable") == 0)
00314     {
00315         g_object_get(object, name, &b, NULL);
00316         gtk_widget_set_sensitive(widget, b);
00317     }
00318 }

static void ergtk_entry_real_set_text ( erGtkEntry er_entry,
const gchar *  text 
) [static]

Definition at line 276 of file erGtkEntry.c.

00277 {
00278     g_return_if_fail(ERGTK_IS_ENTRY(er_entry));
00279     g_return_if_fail(text != NULL);
00280 
00281     GtkEntry* entry = (GtkEntry*)er_entry;
00282 
00283     if (strcmp(text, gtk_entry_get_text(entry)) != 0)
00284     {
00285         // remember we expect a "changed" signal
00286         // Note: set changed_pending before calling parent class method,
00287         //       so we are sure that ergtk_entry_changed() callback reads it correctly.
00288         er_entry->changed_pending = TRUE;
00289 
00290         // chain to parent class
00291         gtk_entry_set_text(entry, text);
00292     }
00293 }

void ergtk_entry_set_integer_filter ( erGtkEntry er_entry  ) 

Definition at line 95 of file erGtkEntry.c.

00096 {
00097     g_return_if_fail(ERGTK_IS_ENTRY(er_entry));
00098 
00099     er_entry->filter = integer_e;
00100     integer_filter_init(GTK_ENTRY(er_entry));
00101 }

Here is the call graph for this function:

void ergtk_entry_set_ipv4_filter ( erGtkEntry er_entry  ) 

Definition at line 87 of file erGtkEntry.c.

00088 {
00089     g_return_if_fail(ERGTK_IS_ENTRY(er_entry));
00090 
00091     er_entry->filter = ipAddress_e;
00092     ipv4_filter_init(GTK_ENTRY(er_entry));
00093 }

Here is the call graph for this function:

void ergtk_entry_set_text ( erGtkEntry er_entry,
const gchar *  text 
)

set the user input text

Parameters:
er_entry the erGtkEntry widget
text the user input text
Returns:
- the user input text

Definition at line 263 of file erGtkEntry.c.

00264 {
00265     g_return_if_fail(ERGTK_IS_ENTRY(er_entry));
00266 
00267     erGtkEntryClass* klass = ERGTK_ENTRY_GET_CLASS(er_entry);
00268 
00269     // chain to real method, which may be overloaded
00270     if (klass->set_text)
00271     {
00272         klass->set_text(er_entry, text);
00273     }
00274 }


Variable Documentation

GtkEntryClass* g_parent_class = NULL [static]

Definition at line 46 of file erGtkEntry.c.

gint g_signals[LAST_SIGNAL] [static]

Definition at line 55 of file erGtkEntry.c.


Generated on Sun Dec 14 17:12:34 2008 by  doxygen 1.5.6