00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00029
00030 #include <string.h>
00031 #include <ctype.h>
00032 #include <gtk/gtk.h>
00033
00034
00035
00036
00037 #include "ergtklog.h"
00038 #include "erGtkEntry.h"
00039 #include "erGtkEntryFilter.h"
00040
00041
00042 #undef gtk_entry_set_text
00043
00044
00045
00046 static GtkEntryClass* g_parent_class = NULL;
00047
00048
00049 enum
00050 {
00051 SIGNAL_CHANGED_STABLE = 0,
00052 SIGNAL_SCREEN_REFRESH,
00053 LAST_SIGNAL
00054 };
00055 static gint g_signals[LAST_SIGNAL];
00056
00057
00058
00059 static void ergtk_entry_grab_focus(GtkWidget* widget);
00060
00061
00062 static void ergtk_entry_notify(GObject* object, GParamSpec* pspec);
00063 static gboolean ergtk_entry_focus_in(GtkWidget* widget, GdkEventFocus* event);
00064 static gboolean ergtk_entry_focus_out(GtkWidget* widget, GdkEventFocus* event);
00065 static gboolean ergtk_entry_focus(GtkWidget* widget, GtkDirectionType arg1);
00066 static gboolean ergtk_entry_button_release(GtkWidget* widget, GdkEventButton* event);
00067 static void ergtk_entry_move_cursor(GtkEntry* widget, GtkMovementStep arg1, gint arg2, gboolean arg3);
00068 static void ergtk_entry_changed(GtkEditable* widget);
00069
00070
00071 static void ergtk_entry_real_set_text(erGtkEntry* er_entry, const gchar* text);
00072
00073
00074 static void ergtk_entry_class_init(erGtkEntryClass* klass);
00075 static void ergtk_entry_editable_init(GtkEditableClass*iface);
00076 static void ergtk_entry_init(erGtkEntry* input_entry);
00077 static gboolean ergtk_entry_delayed_changed_or_movecursor(gpointer user_data);
00078
00079
00080 GtkWidget* ergtk_entry_new()
00081 {
00082 erGtkEntry* item = (erGtkEntry*) g_object_new(ERGTK_ENTRY_TYPE, NULL);
00083
00084 return GTK_WIDGET(item);
00085 }
00086
00087 void ergtk_entry_set_ipv4_filter(erGtkEntry* er_entry)
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 }
00094
00095 void ergtk_entry_set_integer_filter(erGtkEntry* er_entry)
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 }
00102
00103 gboolean ergtk_entry_check_field(erGtkEntry *er_entry)
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 }
00148
00149 GType ergtk_entry_get_type(void)
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,
00159 NULL,
00160 (GClassInitFunc) ergtk_entry_class_init,
00161 NULL,
00162 NULL,
00163 sizeof(erGtkEntry),
00164 0,
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,
00172 NULL,
00173 NULL
00174 };
00175 g_type_add_interface_static(class_type, GTK_TYPE_EDITABLE, &editable_info);
00176 }
00177
00178 return class_type;
00179 }
00180
00181
00182 static void ergtk_entry_class_init(erGtkEntryClass* klass)
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
00191 g_parent_class = g_type_class_peek_parent(klass);
00192
00193
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
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),
00211 NULL,
00212 NULL,
00213 gtk_marshal_VOID__VOID,
00214 G_TYPE_NONE,
00215 0,
00216 0 );
00217
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),
00222 NULL,
00223 NULL,
00224 gtk_marshal_VOID__VOID,
00225 G_TYPE_NONE,
00226 0,
00227 0 );
00228 }
00229
00230
00231 static void ergtk_entry_editable_init(GtkEditableClass* iface)
00232 {
00233 iface->changed = ergtk_entry_changed;
00234 }
00235
00236
00237 static void ergtk_entry_init(erGtkEntry* er_entry)
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
00245 g_object_set(gtk_widget_get_settings(widget), "gtk-cursor-blink", FALSE, NULL);
00246
00247
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
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 }
00260
00261
00262
00263 void ergtk_entry_set_text(erGtkEntry* er_entry, const gchar* text)
00264 {
00265 g_return_if_fail(ERGTK_IS_ENTRY(er_entry));
00266
00267 erGtkEntryClass* klass = ERGTK_ENTRY_GET_CLASS(er_entry);
00268
00269
00270 if (klass->set_text)
00271 {
00272 klass->set_text(er_entry, text);
00273 }
00274 }
00275
00276 static void ergtk_entry_real_set_text(erGtkEntry* er_entry, const gchar* text)
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
00286
00287
00288 er_entry->changed_pending = TRUE;
00289
00290
00291 gtk_entry_set_text(entry, text);
00292 }
00293 }
00294
00295
00296
00297 static void ergtk_entry_notify(GObject* object, GParamSpec* pspec)
00298 {
00299 g_return_if_fail(ERGTK_IS_ENTRY(object));
00300
00301 GtkWidget* widget = (GtkWidget*)object;
00302
00303
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 }
00319
00320 static gboolean ergtk_entry_focus_in(GtkWidget* widget, GdkEventFocus* event)
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
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
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 }
00347
00348 static gboolean ergtk_entry_focus_out(GtkWidget* widget, GdkEventFocus* event)
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
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
00363 gtk_editable_select_region(GTK_EDITABLE(entry), -1, -1);
00364
00365
00366 if (er_entry->visible == FALSE)
00367 {
00368 gtk_entry_set_visibility(entry, FALSE);
00369 }
00370
00371 return rc;
00372 }
00373
00374 static gboolean ergtk_entry_focus(GtkWidget* widget, GtkDirectionType arg1)
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
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 }
00390
00391 static void ergtk_entry_grab_focus(GtkWidget* widget)
00392 {
00393 g_return_if_fail(ERGTK_IS_ENTRY(widget));
00394
00395
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 }
00402
00403 static void ergtk_entry_changed(GtkEditable* editable)
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
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
00425 er_entry->changed_pending = FALSE;
00426 }
00427 else
00428 {
00429
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 }
00438
00439 static void ergtk_entry_move_cursor(GtkEntry* widget, GtkMovementStep arg1, gint arg2, gboolean arg3)
00440 {
00441 g_return_if_fail(ERGTK_IS_ENTRY(widget));
00442
00443 erGtkEntry* er_entry = (erGtkEntry*)widget;
00444
00445
00446 if (g_parent_class->move_cursor)
00447 {
00448 g_parent_class->move_cursor(widget, arg1, arg2, arg3);
00449 }
00450
00451
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 }
00459
00460 static gboolean ergtk_entry_button_release(GtkWidget* widget, GdkEventButton* event)
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
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 }
00476
00477 static gboolean ergtk_entry_delayed_changed_or_movecursor(gpointer user_data)
00478 {
00479 g_assert(ERGTK_IS_ENTRY(user_data));
00480
00481 erGtkEntry* er_entry = (erGtkEntry*)user_data;
00482
00483
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;
00498 }
00499