00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <string.h>
00030 #include <ctype.h>
00031 #include <gtk/gtk.h>
00032 #include <math.h>
00033 #include <gdk/gdkkeysyms.h>
00034 #include <gtk/gtkprivate.h>
00035
00036
00037
00038
00039 #include "ergtk_log.h"
00040 #include "eri18n.h"
00041 #include "erGtkIconView.h"
00042 #include "gtkiconview_private.h"
00043
00044 #define UNUSED(x) (void)(x)
00045
00046
00047
00048 const gchar *type_name = "erGtkIconView";
00049
00050
00051 typedef enum
00052 {
00053 PROP_NOT_USED = 0,
00054 PROP_NAVIGATE_MODE,
00055 NUM_PROPS
00056 } prop_t;
00057
00058
00059 typedef struct
00060 {
00061 gchar *navigate_mode;
00062
00063 } erGtkIconViewPrivate;
00064
00065 static const gchar *PROPNAME_NAVIGATE_MODE = "navigate-mode";
00066
00067 static const gchar *normal_navigate_mode = "normal-navigate-mode";
00068 static const gchar *simple_navigate_mode = "simple-navigate-mode";
00069
00070
00071 static GtkIconViewClass* g_parent_class = NULL;
00072 static guint pre_move_signal = 0;
00073 static guint navigate_cursor_signal = 0;
00074
00075
00076 static void add_move_bindings (GtkBindingSet *binding_set,
00077 const gchar *navigate_mode);
00078 static void add_move_binding (GtkBindingSet *binding_set,
00079 guint keyval,
00080 GdkModifierType modmask,
00081 erGtkIconViewKeyPress navigate);
00082
00083 static void remove_move_bindings(GtkBindingSet *binding_set);
00084 static void remove_move_binding(GtkBindingSet *binding_set,
00085 guint keyval,
00086 GdkModifierType modmask);
00087
00088 static void force_cursor_present (erGtkIconView *er_iconview);
00089
00090 static void destroy_impl (GtkObject *object);
00091
00092
00093 static gboolean on_pre_move_cursor (erGtkIconView *er_iconview,
00094 erGtkIconViewKeyPress navigate);
00095
00096 static void on_style_set (GtkWidget *widget,
00097 GtkStyle *previous_style);
00098
00099 static void on_size_allocate (GtkWidget *widget,
00100 GtkAllocation *allocation);
00101
00102 static gboolean on_button_press_event (GtkWidget *widget,
00103 GdkEventButton *event);
00104
00105 static gboolean on_button_release_event (GtkWidget *widget,
00106 GdkEventButton *event);
00107
00108 static void get_property_impl ( GObject *object,
00109 guint param_id,
00110 GValue *value,
00111 GParamSpec *pspec );
00112
00113 static void set_property_impl ( GObject *object,
00114 guint param_id,
00115 const GValue *value,
00116 GParamSpec *pspec );
00117
00118 static void finalize_impl (GObject *object);
00119
00120
00121 static void on_model_row_changed (GtkTreeModel *model,
00122 GtkTreePath *path,
00123 GtkTreeIter *iter,
00124 gpointer user_data);
00125
00126 static void on_model_row_inserted (GtkTreeModel *model,
00127 GtkTreePath *path,
00128 GtkTreeIter *iter,
00129 gpointer user_data);
00130
00131 static gboolean on_focus_out (GtkWidget *widget,
00132 gpointer data);
00133
00134
00135
00136
00137 static void scale_pixbuf (erGtkIconView *er_iconview,
00138 GtkTreeModel *model,
00139 GtkTreeIter *iter);
00140
00141
00142
00143
00144
00145
00146 static void ergtk_icon_view_class_init(erGtkIconViewClass* klass)
00147 {
00148 LOGPRINTF("entry");
00149
00150 GObjectClass *object_class = (GObjectClass* )klass;
00151 GtkObjectClass *gtk_object_class = (GtkObjectClass*)klass;
00152 GtkWidgetClass *widget_class = (GtkWidgetClass*)klass;
00153
00154 GParamSpec *pspec;
00155
00156 GtkBindingSet *binding_set;
00157 binding_set = gtk_binding_set_by_class (klass);
00158
00159
00160 g_parent_class = g_type_class_peek_parent(klass);
00161
00162
00163 gtk_object_class->destroy = destroy_impl;
00164 widget_class->style_set = on_style_set;
00165 widget_class->size_allocate = on_size_allocate;
00166 widget_class->button_press_event = on_button_press_event;
00167 widget_class->button_release_event = on_button_release_event;
00168
00169 object_class->get_property = get_property_impl;
00170 object_class->set_property = set_property_impl;
00171 object_class->finalize = finalize_impl;
00172
00173
00174 g_type_class_add_private (klass, sizeof(erGtkIconViewPrivate));
00175
00176
00177
00178 const gchar * default_navigate_mode = normal_navigate_mode;
00179 pspec = g_param_spec_string( PROPNAME_NAVIGATE_MODE,
00180 PROPNAME_NAVIGATE_MODE,
00181 "Normal or simple navigate mode?",
00182 default_navigate_mode,
00183 G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
00184 g_object_class_install_property(object_class, PROP_NAVIGATE_MODE, pspec);
00185
00186
00187 klass->pre_move_cursor = on_pre_move_cursor;
00188
00189
00190 gtk_widget_class_install_style_property (widget_class,
00191 g_param_spec_int ("item-width",
00192 P_("Item width"),
00193 P_("Width in pixels occupied by text and pixbuf"),
00194 G_MININT, G_MAXINT, 0,
00195 GTK_PARAM_READABLE));
00196
00197 gtk_widget_class_install_style_property (widget_class,
00198 g_param_spec_int ("item-height",
00199 P_("Item height"),
00200 P_("Height in pixels occupied by text and pixbuf"),
00201 G_MININT, G_MAXINT, 0,
00202 GTK_PARAM_READABLE));
00203
00204 gtk_widget_class_install_style_property (widget_class,
00205 g_param_spec_int ("item-n-textlines",
00206 P_("Textlines for item"),
00207 P_("Number of textlines in item"),
00208 G_MININT, G_MAXINT, 0,
00209 GTK_PARAM_READABLE));
00210
00211
00212 pre_move_signal = g_signal_new ("pre-move-cursor",
00213 G_TYPE_FROM_CLASS (object_class),
00214 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
00215 G_STRUCT_OFFSET (erGtkIconViewClass, pre_move_cursor),
00216 NULL, NULL,
00217 gtk_marshal_VOID__ENUM,
00218 G_TYPE_NONE,
00219 1,
00220 G_TYPE_INT);
00221
00222 navigate_cursor_signal = g_signal_new("navigate-cursor",
00223 G_TYPE_FROM_CLASS (object_class),
00224 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
00225 0,
00226 NULL, NULL,
00227 gtk_marshal_VOID__ENUM,
00228 G_TYPE_NONE,
00229 1,
00230 G_TYPE_INT);
00231
00232
00233
00234 }
00235
00236
00237 static void ergtk_icon_view_init(erGtkIconView *er_iconview)
00238 {
00239 LOGPRINTF("entry");
00240 g_return_if_fail(ERGTK_IS_ICON_VIEW(er_iconview));
00241
00242 GtkIconView* iconview = (GtkIconView*) er_iconview;
00243
00244
00245 er_iconview->previous = NULL;
00246 er_iconview->next = NULL;
00247 er_iconview->num_rows = 0;
00248 er_iconview->num_cols = 0;
00249
00250
00251 gtk_icon_view_set_margin(iconview, 0);
00252 gtk_icon_view_set_row_spacing(iconview, 0);
00253 gtk_icon_view_set_column_spacing(iconview, 0);
00254 }
00255
00256
00257 GType ergtk_icon_view_get_type(void)
00258 {
00259 static GType class_type = 0;
00260
00261 if (class_type == 0)
00262 {
00263 static const GTypeInfo class_info =
00264 {
00265 sizeof(erGtkIconViewClass),
00266 NULL,
00267 NULL,
00268 (GClassInitFunc) ergtk_icon_view_class_init,
00269 NULL,
00270 NULL,
00271 sizeof(erGtkIconView),
00272 0,
00273 (GInstanceInitFunc) ergtk_icon_view_init,
00274 NULL
00275 };
00276 class_type = g_type_register_static(GTK_TYPE_ICON_VIEW, type_name, &class_info, 0);
00277 }
00278
00279 return class_type;
00280 }
00281
00282
00283 GtkWidget *ergtk_icon_view_new()
00284 {
00285 LOGPRINTF("entry");
00286
00287 return g_object_new (ERGTK_TYPE_ICON_VIEW, NULL);
00288 }
00289
00290
00291 GtkWidget *ergtk_icon_view_new_with_model (GtkTreeModel *model)
00292 {
00293 GtkWidget* widget;
00294
00295 LOGPRINTF("entry");
00296 g_return_val_if_fail(model, NULL);
00297
00298 widget = g_object_new (ERGTK_TYPE_ICON_VIEW, NULL);
00299 ergtk_icon_view_set_model( ERGTK_ICON_VIEW(widget), model);
00300
00301 return widget;
00302 }
00303
00304
00305
00306
00307
00308 void ergtk_icon_view_set_model (erGtkIconView *er_iconview, GtkTreeModel *model)
00309 {
00310 LOGPRINTF("entry");
00311 g_return_if_fail(ERGTK_IS_ICON_VIEW(er_iconview));
00312
00313 GtkIconView *iconview = (GtkIconView*) er_iconview;
00314 GtkTreeModel *iconview_model = gtk_icon_view_get_model(iconview);
00315
00316
00317 if (iconview_model)
00318 {
00319 g_signal_handlers_disconnect_by_func(iconview_model, on_model_row_changed, er_iconview);
00320 g_signal_handlers_disconnect_by_func(iconview_model, on_model_row_inserted, er_iconview);
00321 }
00322
00323
00324 gtk_icon_view_set_model(iconview, model);
00325 iconview_model = model;
00326
00327
00328 if (iconview_model)
00329 {
00330 g_signal_connect_after(model, "row-changed", G_CALLBACK(on_model_row_changed), er_iconview);
00331 g_signal_connect_after(model, "row-inserted", G_CALLBACK(on_model_row_inserted), er_iconview);
00332 }
00333 }
00334
00335
00336 static void on_model_row_changed(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data)
00337 {
00338 UNUSED(path);
00339 LOGPRINTF("entry");
00340 g_return_if_fail(ERGTK_IS_ICON_VIEW(user_data));
00341
00342 erGtkIconView *er_iconview = (erGtkIconView *) user_data;
00343
00344
00345 scale_pixbuf(er_iconview, model, iter);
00346 }
00347
00348
00349 static void on_model_row_inserted(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data)
00350 {
00351 UNUSED(path);
00352 LOGPRINTF("entry");
00353 g_return_if_fail(ERGTK_IS_ICON_VIEW(user_data));
00354
00355 erGtkIconView *er_iconview = (erGtkIconView *) user_data;
00356
00357
00358 scale_pixbuf(er_iconview, model, iter);
00359 }
00360
00361
00362 static gboolean on_focus_out(GtkWidget *widget, gpointer data)
00363 {
00364 UNUSED(widget);
00365 UNUSED(data);
00366 LOGPRINTF("entry");
00367
00368
00369 return TRUE;
00370 }
00371
00372
00373 static gboolean on_focus_in(GtkWidget *widget, gpointer data)
00374 {
00375 UNUSED(widget);
00376 UNUSED(data);
00377 LOGPRINTF("entry");
00378
00379
00380 return TRUE;
00381 }
00382
00383
00384 static void scale_pixbuf(erGtkIconView *er_iconview, GtkTreeModel *model, GtkTreeIter *iter)
00385 {
00386 LOGPRINTF("entry");
00387
00388 GtkIconView *iconview = (GtkIconView *) er_iconview;
00389 gint pixbuf_column = gtk_icon_view_get_pixbuf_column(iconview);
00390 gint pixbuf_width = 0;
00391 gint pixbuf_height = 0;
00392 gint icon_width = 0;
00393 gint icon_height = 0;
00394 gint x;
00395 gint y;
00396 gint w;
00397 gint h;
00398 float scale_horizontal;
00399 float scale_vertical;
00400 GdkPixbuf *pixbuf_old = NULL;
00401 GdkPixbuf *pixbuf_new = NULL;
00402 GtkListStore *list_store = NULL;
00403 GtkTreeStore *tree_store = NULL;
00404
00405
00406 LOGPRINTF("pixbuf_column [%d]", pixbuf_column);
00407 if (pixbuf_column >= 0)
00408 {
00409
00410 ergtk_icon_view_get_icon_size(er_iconview, &icon_width, &icon_height);
00411 if (icon_width > 0 && icon_height > 0)
00412 {
00413
00414 gtk_tree_model_get( model, iter,
00415 pixbuf_column, &pixbuf_old,
00416 -1 );
00417 if (pixbuf_old)
00418 {
00419 pixbuf_width = gdk_pixbuf_get_width(pixbuf_old);
00420 pixbuf_height = gdk_pixbuf_get_height(pixbuf_old);
00421 }
00422
00423
00424 if ( pixbuf_width <= icon_width
00425 && pixbuf_height <= icon_height )
00426 {
00427
00428 }
00429 else if ( 10 * pixbuf_width <= 12 * icon_width
00430 && 10 * pixbuf_height <= 12 * icon_height )
00431 {
00432
00433 if (pixbuf_width <= icon_width)
00434 {
00435 x = 0;
00436 w = pixbuf_width;
00437 }
00438 else
00439 {
00440 x = (pixbuf_width - icon_width ) / 2;
00441 w = icon_width;
00442 }
00443 if (pixbuf_height <= icon_height)
00444 {
00445 y = 0;
00446 h = pixbuf_height;
00447 }
00448 else
00449 {
00450 y = (pixbuf_height - icon_height) / 2;
00451 h = icon_height;
00452 }
00453 pixbuf_new = gdk_pixbuf_new_subpixbuf(pixbuf_old, x, y, w, h);
00454 }
00455 else
00456 {
00457
00458 scale_horizontal = ((float) icon_width ) / ((float) pixbuf_width );
00459 scale_vertical = ((float) icon_height) / ((float) pixbuf_height);
00460 if (scale_horizontal < scale_vertical)
00461 {
00462 w = ((float) pixbuf_width ) * scale_horizontal;
00463 h = ((float) pixbuf_height) * scale_horizontal;
00464 }
00465 else
00466 {
00467 w = ((float) pixbuf_width ) * scale_vertical;
00468 h = ((float) pixbuf_height) * scale_vertical;
00469 }
00470 pixbuf_new = gdk_pixbuf_scale_simple(pixbuf_old, w, h, GDK_INTERP_BILINEAR);
00471 }
00472
00473
00474 if (pixbuf_new)
00475 {
00476 if ( GTK_IS_LIST_STORE(model) )
00477 {
00478 list_store = GTK_LIST_STORE(model);
00479 g_assert(list_store);
00480 gtk_list_store_set( list_store, iter,
00481 pixbuf_column, pixbuf_new,
00482 -1 );
00483 }
00484 else if ( GTK_IS_TREE_STORE(model) )
00485 {
00486 tree_store = GTK_TREE_STORE(model);
00487 g_assert(tree_store);
00488 gtk_tree_store_set( tree_store, iter,
00489 pixbuf_column, pixbuf_new,
00490 -1 );
00491 }
00492 else
00493 {
00494 ERRORPRINTF("unexpected model type, cannot set new pixbuf");
00495 }
00496 }
00497 }
00498 }
00499
00500
00501 if (pixbuf_old) { g_object_unref(pixbuf_old); }
00502 if (pixbuf_new) { g_object_unref(pixbuf_new); }
00503 }
00504
00505
00506 static void destroy_impl(GtkObject *object)
00507 {
00508 LOGPRINTF("entry");
00509 g_return_if_fail(ERGTK_IS_ICON_VIEW(object));
00510
00511 erGtkIconView* er_iconview = (erGtkIconView*) object;
00512 GtkObjectClass* parent_object_class = GTK_OBJECT_CLASS(g_parent_class);
00513
00514
00515 ergtk_icon_view_set_model(er_iconview, NULL);
00516
00517
00518 if (parent_object_class->destroy)
00519 {
00520 parent_object_class->destroy(object);
00521 }
00522 }
00523
00524
00525 static void on_style_set(GtkWidget *widget, GtkStyle *previous_style)
00526 {
00527 LOGPRINTF("entry");
00528 g_return_if_fail(ERGTK_IS_ICON_VIEW(widget));
00529
00530 GtkIconView *iconview = (GtkIconView*) widget;
00531 GtkIconViewCellInfo *info;
00532
00533 gint icon_width = 0;
00534 gint icon_height = 0;
00535 gint text_height = 0;
00536 gint spacing = 0;
00537 gint item_width = 0;
00538 gint item_height = 0;
00539 gint item_n_textlines = 0;
00540
00541 GtkWidgetClass* parent_widget_class = GTK_WIDGET_CLASS(g_parent_class);
00542
00543
00544 if (parent_widget_class->style_set)
00545 {
00546 parent_widget_class->style_set(widget, previous_style);
00547 }
00548
00549 gtk_widget_style_get(widget,
00550 "item-width", &item_width,
00551 "item-height", &item_height,
00552 "item-n-textlines", &item_n_textlines,
00553 NULL);
00554
00555
00556
00557 if ((item_width > 0) && (item_height > 0))
00558 {
00559 gtk_icon_view_set_item_width(iconview, item_width);
00560 }
00561
00562
00563
00564 info = g_list_nth_data (iconview->priv->cell_list, iconview->priv->text_cell);
00565 if (info != NULL)
00566 {
00567
00568 gtk_object_set( GTK_OBJECT(info->cell),
00569 "xpad", 0,
00570 NULL );
00571
00572
00573 if (item_n_textlines > 0)
00574 {
00575 gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT(info->cell), item_n_textlines);
00576 }
00577 gtk_cell_renderer_get_size(GTK_CELL_RENDERER(info->cell), widget, NULL, NULL, NULL, NULL, &text_height);
00578 }
00579
00580
00581
00582 info = g_list_nth_data (iconview->priv->cell_list, iconview->priv->pixbuf_cell);
00583 if ((info != NULL) && (item_width > 0) && (item_height > 0))
00584 {
00585 spacing = gtk_icon_view_get_spacing(iconview);
00586 icon_width = item_width;
00587 icon_height = item_height - text_height - spacing;
00588
00589 gtk_cell_renderer_set_fixed_size(GTK_CELL_RENDERER(info->cell), icon_width, icon_height);
00590 }
00591 }
00592
00593
00594 static void on_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
00595 {
00596 LOGPRINTF("entry");
00597 g_return_if_fail(ERGTK_IS_ICON_VIEW(widget));
00598
00599 GtkWidgetClass *parent_widget_class = GTK_WIDGET_CLASS(g_parent_class);
00600
00601 erGtkIconView *er_iconview = (erGtkIconView*) widget;
00602 GtkIconView *iconview = (GtkIconView *) widget;
00603 gint item_width = 0;
00604 gint item_height = 0;
00605 gint focus_line_width = 0;
00606 gint row_space = 0;
00607 gint col_space = 0;
00608
00609
00610 if (parent_widget_class->size_allocate)
00611 {
00612 parent_widget_class->size_allocate(widget, allocation);
00613 }
00614
00615 gtk_widget_style_get(widget,
00616 "item-width", &item_width,
00617 "item-height", &item_height,
00618 "focus-line-width", &focus_line_width,
00619 NULL);
00620
00621 if ((item_width > 0) && (item_height > 0))
00622 {
00623
00624 item_height += 2 * focus_line_width;
00625 item_width += 2 * focus_line_width;
00626
00627
00628 row_space = gtk_icon_view_get_row_spacing(iconview);
00629 er_iconview->num_rows = (allocation->height + row_space) / (item_height + row_space);
00630
00631
00632 col_space = gtk_icon_view_get_column_spacing(iconview);
00633 er_iconview->num_cols = (allocation->width + col_space) / (item_width + col_space);
00634 }
00635 }
00636
00637
00638 static gboolean on_button_press_event (GtkWidget *widget,
00639 GdkEventButton *event)
00640 {
00641 LOGPRINTF("entry");
00642 g_return_val_if_fail(ERGTK_IS_ICON_VIEW(widget), FALSE);
00643
00644 GtkWidgetClass *parent_widget_class = GTK_WIDGET_CLASS(g_parent_class);
00645 GtkIconView *iconview = (GtkIconView*) widget;
00646
00647
00648 if ((event->button == 1) && (event->type != GDK_BUTTON_PRESS))
00649 {
00650 event->type = GDK_NOTHING;
00651 iconview->priv->last_single_clicked = NULL;
00652 iconview->priv->pressed_button = -1;
00653 }
00654
00655
00656 if (parent_widget_class->button_press_event)
00657 {
00658 parent_widget_class->button_press_event(widget, event);
00659 }
00660
00661 return TRUE;
00662 }
00663
00664
00665 static gboolean on_button_release_event(GtkWidget *widget,
00666 GdkEventButton *event)
00667 {
00668 LOGPRINTF("entry");
00669 g_return_val_if_fail(ERGTK_IS_ICON_VIEW(widget), FALSE);
00670
00671 GtkTreePath *path = NULL;
00672 GtkIconViewItem *item = NULL;
00673 gint index = 0;
00674 GtkWidgetClass *parent_widget_class = GTK_WIDGET_CLASS(g_parent_class);
00675 GtkIconView *iconview = (GtkIconView*) widget;
00676
00677
00678
00679 if ( (iconview->priv->pressed_button == event->button) &&
00680 ((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == 0) )
00681 {
00682
00683 path = gtk_icon_view_get_path_at_pos(iconview, event->x, event->y);
00684 if (path)
00685 {
00686
00687 index = gtk_tree_path_get_indices(path)[0];
00688 item = g_list_nth_data(iconview->priv->items, index);
00689
00690
00691 if (item == iconview->priv->last_single_clicked)
00692 {
00693
00694 gtk_icon_view_item_activated(iconview, path);
00695 }
00696 }
00697
00698 iconview->priv->last_single_clicked = NULL;
00699 }
00700
00701
00702 if (parent_widget_class->button_release_event)
00703 {
00704 parent_widget_class->button_release_event(widget, event);
00705 }
00706
00707
00708 if (path) { gtk_tree_path_free(path); }
00709
00710 return TRUE;
00711 }
00712
00713
00714 void ergtk_icon_view_set_next(erGtkIconView *er_iconview, erGtkIconView *next)
00715 {
00716 LOGPRINTF("entry");
00717 g_return_if_fail( ERGTK_IS_ICON_VIEW(er_iconview));
00718 g_return_if_fail(next == NULL || ERGTK_IS_ICON_VIEW(next ));
00719
00720 er_iconview->next = next;
00721 }
00722
00723
00724 void ergtk_icon_view_set_previous(erGtkIconView *er_iconview, erGtkIconView *previous)
00725 {
00726 LOGPRINTF("entry");
00727 g_return_if_fail( ERGTK_IS_ICON_VIEW(er_iconview));
00728 g_return_if_fail(previous == NULL || ERGTK_IS_ICON_VIEW(previous ));
00729
00730 er_iconview->previous = previous;
00731 }
00732
00733
00734 void ergtk_icon_view_get_cursor(erGtkIconView *er_iconview, gint *row, gint *col)
00735 {
00736 GtkIconView *iconview = (GtkIconView*) er_iconview;
00737
00738 gint r = 0;
00739 gint c = 0;
00740
00741 LOGPRINTF("entry");
00742 g_return_if_fail(ERGTK_IS_ICON_VIEW(er_iconview));
00743
00744 force_cursor_present(er_iconview);
00745
00746 if (iconview->priv->cursor_item)
00747 {
00748 r = iconview->priv->cursor_item->row;
00749 c = iconview->priv->cursor_item->col;
00750 }
00751
00752 if (row != NULL)
00753 {
00754 *row = r;
00755 }
00756
00757 if (col != NULL)
00758 {
00759 *col = c;
00760 }
00761 }
00762
00763
00764 void ergtk_icon_view_get_view_size(erGtkIconView *er_iconview, gint *num_rows, gint *num_cols, gint *num_items)
00765 {
00766 LOGPRINTF("entry");
00767 g_return_if_fail(ERGTK_IS_ICON_VIEW(er_iconview));
00768
00769 GtkIconView *iconview = (GtkIconView*) er_iconview;
00770
00771 if (num_rows != NULL)
00772 {
00773 *num_rows = er_iconview->num_rows;
00774 }
00775
00776 if (num_cols != NULL)
00777 {
00778 *num_cols = er_iconview->num_cols;
00779 }
00780
00781 if (num_items != NULL)
00782 {
00783 *num_items = g_list_length(iconview->priv->items);
00784 }
00785
00786 LOGPRINTF("leave");
00787 }
00788
00789
00790 void ergtk_icon_view_get_icon_size(erGtkIconView *er_iconview, gint *icon_width, gint *icon_height)
00791 {
00792 LOGPRINTF("entry");
00793 g_return_if_fail(ERGTK_IS_ICON_VIEW(er_iconview));
00794
00795 GtkIconView *iconview = (GtkIconView*) er_iconview;
00796 GtkIconViewCellInfo *info;
00797
00798
00799 info = g_list_nth_data (iconview->priv->cell_list, iconview->priv->pixbuf_cell);
00800 if (info && info->cell)
00801 {
00802 gtk_cell_renderer_get_fixed_size(GTK_CELL_RENDERER(info->cell), icon_width, icon_height);
00803 }
00804 else
00805 {
00806 if (icon_width)
00807 {
00808 *icon_width = 0;
00809 }
00810 if (icon_height)
00811 {
00812 *icon_height = 0;
00813 }
00814 }
00815 }
00816
00817
00818
00819
00820
00821
00822
00823
00824 void ergtk_icon_view_set_cursor(erGtkIconView *er_iconview, gint row, gint col)
00825 {
00826 LOGPRINTF("entry");
00827 g_return_if_fail(ERGTK_IS_ICON_VIEW(er_iconview));
00828
00829 GtkIconView *iconview = (GtkIconView*) er_iconview;
00830 GtkWidget *widget = (GtkWidget *) er_iconview;
00831
00832 GtkTreePath *path = NULL;
00833 gint index = 0;
00834 gint num_rows = 0;
00835 gint num_cols = 0;
00836 gint num_items = 0;
00837 gint last_row;
00838 gint last_col;
00839 gint last_row_last_col;
00840
00841 LOGPRINTF("entry: row [%d] col [%d]", row, col);
00842
00843 ergtk_icon_view_get_view_size(er_iconview, &num_rows, &num_cols, &num_items);
00844 LOGPRINTF("num_rows [%d] num_cols [%d] num_items [%d]", num_rows, num_cols, num_items);
00845
00846 if (num_items <= 0)
00847 {
00848 WARNPRINTF("no items, quit");
00849 return;
00850 }
00851
00852 if (num_rows <= 0 || num_cols <= 0)
00853 {
00854 WARNPRINTF("no space allocated, num_rows [%d] num_cols [%d]",
00855 num_rows, num_cols );
00856 return;
00857 }
00858
00859 last_row = (num_items - 1) / num_cols;
00860 last_row_last_col = (num_items - 1) % num_cols;
00861
00862
00863 if (last_row == 0)
00864 {
00865
00866 row = 0;
00867 }
00868 else
00869 {
00870
00871 if (row < 0)
00872 {
00873
00874 row = last_row;
00875 }
00876 else if (row > last_row)
00877 {
00878
00879 if (col <= last_row_last_col)
00880 {
00881
00882
00883 row = last_row;
00884 }
00885 else
00886 {
00887
00888 row = last_row - 1;
00889 }
00890 }
00891 }
00892
00893
00894 if (row == last_row)
00895 {
00896 last_col = last_row_last_col;
00897 }
00898 else
00899 {
00900 last_col = num_cols - 1;
00901 }
00902 if (col < 0 || col > last_col)
00903 {
00904
00905
00906 col = last_col;
00907 }
00908 LOGPRINTF("calculated: col [%d] row [%d]", col, row);
00909
00910
00911 index = (row * num_cols) + col;
00912 path = gtk_tree_path_new_from_indices(index, -1);
00913 gtk_widget_grab_focus (widget);
00914 gtk_icon_view_select_path(iconview, path);
00915 gtk_icon_view_set_cursor(iconview, path, NULL, FALSE);
00916
00917
00918 if (path) { gtk_tree_path_free(path); }
00919
00920 return;
00921 }
00922
00923
00924 void ergtk_icon_view_set_focus_mode(erGtkIconView *er_iconview,
00925 gboolean focus_in,
00926 gboolean focus_out)
00927 {
00928 if (!focus_in)
00929 {
00930
00931 g_signal_connect(G_OBJECT(er_iconview), "focus-in-event", G_CALLBACK (on_focus_in), NULL);
00932 }
00933 if (!focus_out)
00934 {
00935
00936 g_signal_connect(G_OBJECT(er_iconview), "focus-out-event", G_CALLBACK (on_focus_out), NULL);
00937 }
00938 }
00939
00940
00941
00942
00943
00944
00945 static void force_cursor_present (erGtkIconView *er_iconview)
00946 {
00947 LOGPRINTF("entry");
00948
00949 GtkIconView *iconview = (GtkIconView*) er_iconview;
00950
00951 if ( !iconview->priv->cursor_item )
00952 {
00953
00954 WARNPRINTF("no cursor, force to (0,0)");
00955 ergtk_icon_view_set_cursor(er_iconview, 0, 0);
00956 }
00957 }
00958
00959
00960 static gboolean on_pre_move_cursor (erGtkIconView *er_iconview,
00961 erGtkIconViewKeyPress navigate)
00962 {
00963 LOGPRINTF("entry");
00964
00965 gboolean ret = FALSE;
00966 GtkIconView *iconview = (GtkIconView*) er_iconview;
00967 GtkTreePath *path = NULL;
00968
00969 gint curcol = 0;
00970 gint currow = 0;
00971 gint num_rows = 0;
00972 gint num_cols = 0;
00973 gint num_items = 0;
00974 gint row_items = 0;
00975 gint last_row = 0;
00976 gint last_row_last_col = 0;
00977 gint step = 0;
00978
00979 LOGPRINTF("entry: navigate [%d]", navigate);
00980 g_return_val_if_fail (ERGTK_ICON_VIEW (er_iconview), FALSE);
00981
00982 if (!GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (er_iconview)))
00983 {
00984 WARNPRINTF("widget has no focus");
00985 return FALSE;
00986 }
00987
00988 force_cursor_present(er_iconview);
00989
00990 ergtk_icon_view_get_cursor(er_iconview, &currow, &curcol);
00991 ergtk_icon_view_get_view_size(er_iconview, &num_rows, &num_cols, &num_items);
00992
00993
00994 if (currow == num_rows)
00995 {
00996 row_items = num_items - (num_cols*(num_rows-1));
00997 }
00998 else
00999 {
01000 row_items = num_cols;
01001 }
01002
01003
01004 if ((currow+1) == num_rows)
01005 {
01006 row_items = num_items - (num_cols*(num_rows-1));
01007 }
01008
01009 last_row = (num_items - 1) / num_cols;
01010 last_row_last_col = (num_items - 1) % num_cols;
01011
01012 LOGPRINTF("curcol [%d] currow [%d]", curcol, currow);
01013 LOGPRINTF("num_cols [%d] num_rows [%d] num_items [%d] row_items [%d] last_row [%d] last_row_last_col [%d]",
01014 num_cols, num_rows, num_items, row_items, last_row, last_row_last_col );
01015
01016 switch (navigate)
01017 {
01018 case ERGTK_ICON_VIEW_PRESS_SHORT_UP:
01019 if (currow > 0)
01020 {
01021
01022 g_signal_emit_by_name(er_iconview, "move-cursor", GTK_MOVEMENT_DISPLAY_LINES, -1, &ret);
01023 }
01024 else
01025 {
01026 gint items_previous = 0;
01027 if (er_iconview->previous)
01028 {
01029 ergtk_icon_view_get_view_size(er_iconview->previous, NULL, NULL, &items_previous);
01030 }
01031
01032 if (items_previous > 0)
01033 {
01034
01035 ergtk_icon_view_set_cursor(er_iconview->previous, -1, curcol);
01036 }
01037 else
01038 {
01039
01040 g_signal_emit_by_name(er_iconview, "navigate-cursor", ERGTK_ICON_VIEW_PRESS_SHORT_UP);
01041 }
01042 }
01043 break;
01044
01045 case ERGTK_ICON_VIEW_PRESS_SHORT_DOWN:
01046 if (currow < last_row)
01047 {
01048 if (((currow+1)*row_items)+curcol < num_items)
01049 {
01050
01051 g_signal_emit_by_name (er_iconview, "move-cursor", GTK_MOVEMENT_DISPLAY_LINES, 1, &ret);
01052 }
01053 else
01054 {
01055
01056 g_signal_emit_by_name (er_iconview, "move-cursor", GTK_MOVEMENT_BUFFER_ENDS, 1, &ret);
01057 }
01058 }
01059 else
01060 {
01061 gint item_next = 0;
01062 if (er_iconview->next)
01063 {
01064 ergtk_icon_view_get_view_size(er_iconview->next, NULL, NULL, &item_next);
01065 }
01066
01067 if (item_next > 0)
01068 {
01069
01070 ergtk_icon_view_set_cursor(er_iconview->next, 0, curcol);
01071 }
01072 else
01073 {
01074
01075 g_signal_emit_by_name(er_iconview, "navigate-cursor", ERGTK_ICON_VIEW_PRESS_SHORT_DOWN);
01076 }
01077 }
01078 break;
01079
01080 case ERGTK_ICON_VIEW_PRESS_SHORT_LEFT:
01081 if (curcol > 0)
01082 {
01083 g_signal_emit_by_name (er_iconview, "move-cursor", GTK_MOVEMENT_VISUAL_POSITIONS, -1, &ret);
01084 }
01085 else
01086 {
01087 if (currow > 0)
01088 {
01089
01090 ergtk_icon_view_set_cursor(er_iconview, currow-1, -1);
01091 }
01092 else if (er_iconview->previous)
01093 {
01094
01095 ergtk_icon_view_set_cursor(er_iconview->previous, -1, -1);
01096 }
01097 else
01098 {
01099
01100 g_signal_emit_by_name(er_iconview, "navigate-cursor", ERGTK_ICON_VIEW_PRESS_SHORT_LEFT);
01101 }
01102 }
01103 break;
01104
01105 case ERGTK_ICON_VIEW_PRESS_SHORT_RIGHT:
01106 if ( ((curcol+1) < row_items) && !((currow == last_row) && (curcol == last_row_last_col)) )
01107 {
01108 g_signal_emit_by_name (er_iconview, "move-cursor", GTK_MOVEMENT_VISUAL_POSITIONS, 1, &ret);
01109 }
01110 else
01111 {
01112 if (currow < last_row)
01113 {
01114
01115 ergtk_icon_view_set_cursor(er_iconview, currow+1, 0);
01116 }
01117 else if (er_iconview->next)
01118 {
01119
01120 ergtk_icon_view_set_cursor(er_iconview->next, 0, 0);
01121 }
01122 else
01123 {
01124
01125 g_signal_emit_by_name(er_iconview, "navigate-cursor", ERGTK_ICON_VIEW_PRESS_SHORT_RIGHT);
01126 }
01127 }
01128 break;
01129
01130 case ERGTK_ICON_VIEW_PRESS_LONG_UP:
01131 g_signal_emit_by_name(er_iconview, "navigate-cursor", ERGTK_ICON_VIEW_PRESS_LONG_UP);
01132 break;
01133
01134 case ERGTK_ICON_VIEW_PRESS_LONG_DOWN:
01135 g_signal_emit_by_name(er_iconview, "navigate-cursor", ERGTK_ICON_VIEW_PRESS_LONG_DOWN);
01136 break;
01137
01138 case ERGTK_ICON_VIEW_PRESS_LONG_LEFT:
01139 if (curcol > 0)
01140 {
01141
01142 step = 1 - (curcol+1);
01143 g_signal_emit_by_name (er_iconview, "move-cursor", GTK_MOVEMENT_VISUAL_POSITIONS, step, &ret);
01144 }
01145 else
01146 {
01147 if (currow > 0)
01148 {
01149
01150 on_pre_move_cursor(er_iconview, ERGTK_ICON_VIEW_PRESS_SHORT_UP);
01151 }
01152 else if (er_iconview->previous)
01153 {
01154
01155 ergtk_icon_view_set_cursor(er_iconview->previous, -1, 0);
01156 }
01157 else
01158 {
01159
01160 g_signal_emit_by_name(er_iconview, "navigate-cursor", ERGTK_ICON_VIEW_PRESS_LONG_LEFT);
01161 }
01162 }
01163 break;
01164
01165 case ERGTK_ICON_VIEW_PRESS_LONG_RIGHT:
01166 if ((curcol+1) < row_items)
01167 {
01168
01169 if (currow == last_row)
01170 {
01171 step = last_row_last_col - curcol;
01172 }
01173 else
01174 {
01175 step = row_items - (curcol+1);
01176 }
01177 g_signal_emit_by_name (er_iconview, "move-cursor", GTK_MOVEMENT_VISUAL_POSITIONS, step, &ret);
01178 }
01179 else
01180 {
01181 if (currow < last_row)
01182 {
01183
01184 on_pre_move_cursor(er_iconview, ERGTK_ICON_VIEW_PRESS_SHORT_DOWN);
01185 }
01186 else if (er_iconview->next)
01187 {
01188
01189 ergtk_icon_view_set_cursor(er_iconview->next, 0, -1);
01190 }
01191 else
01192 {
01193
01194 g_signal_emit_by_name(er_iconview, "navigate-cursor", ERGTK_ICON_VIEW_PRESS_LONG_RIGHT);
01195 }
01196 }
01197 break;
01198
01199 case ERGTK_ICON_VIEW_PRESS_ACTIVATE:
01200 path = gtk_tree_path_new();
01201 gtk_icon_view_get_cursor(iconview, &path, NULL);
01202 gtk_icon_view_item_activated(iconview, path);
01203 gtk_tree_path_free(path);
01204 path = NULL;
01205 break;
01206
01207 default:
01208 g_assert_not_reached();
01209 break;
01210 }
01211
01212 LOGPRINTF("leave");
01213 return TRUE;
01214 }
01215
01216 static void add_move_bindings(GtkBindingSet *binding_set, const gchar * navigate_mode)
01217 {
01218 LOGPRINTF("entry");
01219 g_return_if_fail(binding_set != NULL);
01220
01221 gint n = strlen(simple_navigate_mode);
01222 if (g_strncasecmp(navigate_mode, simple_navigate_mode, n) == 0)
01223 {
01224 add_move_binding(binding_set, GDK_Up, 0, ERGTK_ICON_VIEW_PRESS_SHORT_LEFT);
01225 add_move_binding(binding_set, GDK_KP_Up, 0, ERGTK_ICON_VIEW_PRESS_SHORT_LEFT);
01226
01227 add_move_binding(binding_set, GDK_Down, 0, ERGTK_ICON_VIEW_PRESS_SHORT_RIGHT);
01228 add_move_binding(binding_set, GDK_KP_Down, 0, ERGTK_ICON_VIEW_PRESS_SHORT_RIGHT);
01229
01230 add_move_binding(binding_set, GDK_Page_Up, 0, ERGTK_ICON_VIEW_PRESS_LONG_UP);
01231 add_move_binding(binding_set, GDK_KP_Page_Up, 0, ERGTK_ICON_VIEW_PRESS_LONG_UP);
01232
01233 add_move_binding(binding_set, GDK_Page_Down, 0, ERGTK_ICON_VIEW_PRESS_LONG_DOWN);
01234 add_move_binding(binding_set, GDK_KP_Page_Down, 0, ERGTK_ICON_VIEW_PRESS_LONG_DOWN);
01235 }
01236 else
01237 {
01238 add_move_binding(binding_set, GDK_Up, 0, ERGTK_ICON_VIEW_PRESS_SHORT_UP);
01239 add_move_binding(binding_set, GDK_KP_Up, 0, ERGTK_ICON_VIEW_PRESS_SHORT_UP);
01240
01241 add_move_binding(binding_set, GDK_Down, 0, ERGTK_ICON_VIEW_PRESS_SHORT_DOWN);
01242 add_move_binding(binding_set, GDK_KP_Down, 0, ERGTK_ICON_VIEW_PRESS_SHORT_DOWN);
01243
01244 add_move_binding(binding_set, GDK_Page_Up, 0, ERGTK_ICON_VIEW_PRESS_LONG_UP);
01245 add_move_binding(binding_set, GDK_KP_Page_Up, 0, ERGTK_ICON_VIEW_PRESS_LONG_UP);
01246
01247 add_move_binding(binding_set, GDK_Page_Down, 0, ERGTK_ICON_VIEW_PRESS_LONG_DOWN);
01248 add_move_binding(binding_set, GDK_KP_Page_Down, 0, ERGTK_ICON_VIEW_PRESS_LONG_DOWN);
01249 }
01250
01251 add_move_binding(binding_set, GDK_Left, 0, ERGTK_ICON_VIEW_PRESS_SHORT_LEFT);
01252 add_move_binding(binding_set, GDK_KP_Left, 0, ERGTK_ICON_VIEW_PRESS_SHORT_LEFT);
01253
01254 add_move_binding(binding_set, GDK_Right, 0, ERGTK_ICON_VIEW_PRESS_SHORT_RIGHT);
01255 add_move_binding(binding_set, GDK_KP_Right, 0, ERGTK_ICON_VIEW_PRESS_SHORT_RIGHT);
01256
01257 add_move_binding(binding_set, GDK_Home, 0, ERGTK_ICON_VIEW_PRESS_LONG_LEFT);
01258 add_move_binding(binding_set, GDK_KP_Home, 0, ERGTK_ICON_VIEW_PRESS_LONG_LEFT);
01259
01260 add_move_binding(binding_set, GDK_End, 0, ERGTK_ICON_VIEW_PRESS_LONG_RIGHT);
01261 add_move_binding(binding_set, GDK_KP_End, 0, ERGTK_ICON_VIEW_PRESS_LONG_RIGHT);
01262
01263 add_move_binding(binding_set, GDK_space, 0, ERGTK_ICON_VIEW_PRESS_ACTIVATE);
01264 add_move_binding(binding_set, GDK_Return, 0, ERGTK_ICON_VIEW_PRESS_ACTIVATE);
01265 add_move_binding(binding_set, GDK_ISO_Enter, 0, ERGTK_ICON_VIEW_PRESS_ACTIVATE);
01266 add_move_binding(binding_set, GDK_KP_Enter, 0, ERGTK_ICON_VIEW_PRESS_ACTIVATE);
01267 }
01268
01269 static void add_move_binding(GtkBindingSet *binding_set,
01270 guint keyval,
01271 GdkModifierType modmask,
01272 erGtkIconViewKeyPress navigate)
01273 {
01274 LOGPRINTF("entry");
01275
01276 gtk_binding_entry_add_signal(binding_set, keyval, modmask,
01277 "pre-move-cursor", 1,
01278 G_TYPE_ENUM, navigate);
01279
01280 gtk_binding_entry_add_signal(binding_set, keyval, GDK_SHIFT_MASK,
01281 "pre-move-cursor", 1,
01282 G_TYPE_ENUM, navigate);
01283
01284 if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
01285 {
01286 return;
01287 }
01288
01289 gtk_binding_entry_add_signal(binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
01290 "pre-move-cursor", 1,
01291 G_TYPE_ENUM, navigate);
01292
01293 gtk_binding_entry_add_signal(binding_set, keyval, GDK_CONTROL_MASK,
01294 "pre-move-cursor", 1,
01295 G_TYPE_ENUM, navigate);
01296 }
01297
01298 static void remove_move_bindings(GtkBindingSet *binding_set)
01299 {
01300 LOGPRINTF("entry");
01301 g_return_if_fail(binding_set != NULL);
01302
01303 remove_move_binding(binding_set, GDK_Up, 0);
01304 remove_move_binding(binding_set, GDK_KP_Up, 0);
01305
01306 remove_move_binding(binding_set, GDK_Down, 0);
01307 remove_move_binding(binding_set, GDK_KP_Down, 0);
01308
01309 remove_move_binding(binding_set, GDK_Page_Up, 0);
01310 remove_move_binding(binding_set, GDK_KP_Page_Up, 0);
01311
01312 remove_move_binding(binding_set, GDK_Page_Down, 0);
01313 remove_move_binding(binding_set, GDK_KP_Page_Down, 0);
01314
01315 remove_move_binding(binding_set, GDK_Left, 0);
01316 remove_move_binding(binding_set, GDK_KP_Left, 0);
01317
01318 remove_move_binding(binding_set, GDK_Right, 0);
01319 remove_move_binding(binding_set, GDK_KP_Right, 0);
01320
01321 remove_move_binding(binding_set, GDK_Home, 0);
01322 remove_move_binding(binding_set, GDK_KP_Home, 0);
01323
01324 remove_move_binding(binding_set, GDK_End, 0);
01325 remove_move_binding(binding_set, GDK_KP_End, 0);
01326
01327 remove_move_binding(binding_set, GDK_space, 0);
01328 remove_move_binding(binding_set, GDK_Return, 0);
01329 remove_move_binding(binding_set, GDK_ISO_Enter, 0);
01330 remove_move_binding(binding_set, GDK_KP_Enter, 0);
01331 }
01332
01333 static void remove_move_binding(GtkBindingSet *binding_set,
01334 guint keyval,
01335 GdkModifierType modmask)
01336 {
01337 LOGPRINTF("entry");
01338
01339 gtk_binding_entry_remove(binding_set, keyval, modmask);
01340 gtk_binding_entry_remove(binding_set, keyval, GDK_SHIFT_MASK);
01341
01342 if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
01343 {
01344 return;
01345 }
01346
01347 gtk_binding_entry_remove(binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK);
01348 gtk_binding_entry_remove(binding_set, keyval, GDK_CONTROL_MASK);
01349 }
01350
01351
01352 static void get_property_impl ( GObject *object,
01353 guint param_id,
01354 GValue *value,
01355 GParamSpec *pspec )
01356 {
01357 g_return_if_fail( ERGTK_IS_ICON_VIEW(object) );
01358
01359 erGtkIconViewPrivate *priv = ERGTK_ICON_VIEW_GET_PRIVATE(object);
01360
01361 switch (param_id)
01362 {
01363 case PROP_NAVIGATE_MODE:
01364 g_value_set_string (value, priv->navigate_mode);
01365 break;
01366
01367 default:
01368 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
01369 }
01370 }
01371
01372
01373
01374 static void set_property_impl ( GObject *object,
01375 guint param_id,
01376 const GValue *value,
01377 GParamSpec *pspec )
01378 {
01379 g_return_if_fail( ERGTK_IS_ICON_VIEW(object) );
01380
01381 erGtkIconViewPrivate *priv = ERGTK_ICON_VIEW_GET_PRIVATE(object);
01382
01383 gchar **cpp;
01384
01385 switch (param_id)
01386 {
01387 case PROP_NAVIGATE_MODE:
01388 {
01389 const gchar *navigate_mode = g_value_get_string(value);
01390 if (g_strncasecmp(navigate_mode, normal_navigate_mode, strlen(normal_navigate_mode))
01391 && g_strncasecmp(navigate_mode, simple_navigate_mode, strlen(simple_navigate_mode)))
01392 {
01393 WARNPRINTF("Invalid navigate mode: %s!", navigate_mode);
01394 }
01395 else
01396 {
01397 cpp = &(priv->navigate_mode);
01398 g_free(*cpp);
01399 *cpp = g_strdup(g_value_get_string(value));
01400 LOGPRINTF("navigate-mode set to [%s]", *cpp);
01401 GtkBindingSet *binding_set = gtk_binding_set_find(type_name);
01402 remove_move_bindings(binding_set);
01403 add_move_bindings(binding_set, navigate_mode);
01404 }
01405 }
01406 break;
01407 default:
01408 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
01409 }
01410 }
01411
01412
01413 static void finalize_impl (GObject *obj)
01414 {
01415 g_return_if_fail( ERGTK_IS_ICON_VIEW(obj) );
01416
01417 erGtkIconViewPrivate *priv = ERGTK_ICON_VIEW_GET_PRIVATE(obj);
01418
01419
01420
01421 g_free(priv->navigate_mode);
01422
01423
01424
01425 ((GObjectClass*)g_parent_class)->finalize( obj );
01426 }
01427