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
00035 #include "gtk/gtkprivate.h"
00036
00037
00038
00039
00040 #include "ergtk_log.h"
00041 #include "ergtklistview.h"
00042
00043
00044
00045
00046 static GtkTreeViewClass* g_parent_class = NULL;
00047 static guint pre_move_signal = 0;
00048 static guint navigate_cursor_signal = 0;
00049
00050
00051
00052
00053
00054
00055 static void add_move_binding (GtkBindingSet *binding_set,
00056 guint keyval,
00057 GdkModifierType modmask,
00058 erGtkListViewKeyPress navigate);
00059
00060
00061
00062 static void on_realize (GtkWidget *widget);
00063
00064 static gboolean on_pre_move_cursor (erGtkListView *er_listview,
00065 erGtkListViewKeyPress navigate);
00066
00067 static void on_style_set (GtkWidget *widget,
00068 GtkStyle *previous_style);
00069
00070 static void on_size_allocate (GtkWidget *widget,
00071 GtkAllocation *allocation);
00072
00073 static gboolean on_button_press_event (GtkWidget *widget,
00074 GdkEventButton *event);
00075
00076 static gboolean on_button_release_event (GtkWidget *widget,
00077 GdkEventButton *event);
00078
00079 static gboolean on_motion_notify_event (GtkWidget *widget,
00080 GdkEventMotion *event);
00081
00082 static void on_column_notify_title (GObject *object,
00083 GParamSpec *arg1,
00084 gpointer user_data);
00085
00086 static gboolean on_focus_in (GtkWidget *widget,
00087 gpointer data);
00088
00089 static gboolean on_focus_out (GtkWidget *widget,
00090 gpointer data);
00091
00092
00093
00094
00095
00096 static void ergtk_list_view_class_init (erGtkListViewClass* klass)
00097 {
00098 GObjectClass *object_class = (GObjectClass* )klass;
00099 GtkWidgetClass *widget_class = (GtkWidgetClass*)klass;
00100
00101 GtkBindingSet *binding_set = gtk_binding_set_by_class (klass);
00102
00103
00104 g_parent_class = g_type_class_peek_parent(klass);
00105
00106
00107 widget_class->realize = on_realize;
00108 widget_class->style_set = on_style_set;
00109 widget_class->size_allocate = on_size_allocate;
00110 widget_class->button_press_event = on_button_press_event;
00111 widget_class->button_release_event = on_button_release_event;
00112 widget_class->motion_notify_event = on_motion_notify_event;
00113
00114
00115 klass->pre_move_cursor = on_pre_move_cursor;
00116
00117 gtk_widget_class_install_style_property (widget_class,
00118 g_param_spec_int ("column-spacing",
00119 P_("Column spacing"),
00120 P_("Empty pixels between columns"),
00121 0, G_MAXINT, 0,
00122 GTK_PARAM_READABLE));
00123
00124 pre_move_signal = g_signal_new ("pre-move-cursor",
00125 G_TYPE_FROM_CLASS (object_class),
00126 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
00127 G_STRUCT_OFFSET (erGtkListViewClass, pre_move_cursor),
00128 NULL, NULL,
00129 gtk_marshal_VOID__ENUM,
00130 G_TYPE_NONE,
00131 1,
00132 G_TYPE_INT);
00133
00134 navigate_cursor_signal = g_signal_new("navigate-cursor",
00135 G_TYPE_FROM_CLASS (object_class),
00136 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
00137 0,
00138 NULL, NULL,
00139 gtk_marshal_VOID__ENUM,
00140 G_TYPE_NONE,
00141 1,
00142 G_TYPE_INT);
00143
00144 add_move_binding(binding_set, GDK_Up, 0, ERGTK_LIST_VIEW_PRESS_SHORT_UP);
00145 add_move_binding(binding_set, GDK_KP_Up, 0, ERGTK_LIST_VIEW_PRESS_SHORT_UP);
00146
00147 add_move_binding(binding_set, GDK_Down, 0, ERGTK_LIST_VIEW_PRESS_SHORT_DOWN);
00148 add_move_binding(binding_set, GDK_KP_Down, 0, ERGTK_LIST_VIEW_PRESS_SHORT_DOWN);
00149
00150 add_move_binding(binding_set, GDK_Left, 0, ERGTK_LIST_VIEW_PRESS_SHORT_UP);
00151 add_move_binding(binding_set, GDK_KP_Left, 0, ERGTK_LIST_VIEW_PRESS_SHORT_UP);
00152
00153 add_move_binding(binding_set, GDK_Right, 0, ERGTK_LIST_VIEW_PRESS_SHORT_DOWN);
00154 add_move_binding(binding_set, GDK_KP_Right, 0, ERGTK_LIST_VIEW_PRESS_SHORT_DOWN);
00155
00156 add_move_binding(binding_set, GDK_Page_Up, 0, ERGTK_LIST_VIEW_PRESS_LONG_UP);
00157 add_move_binding(binding_set, GDK_KP_Page_Up, 0, ERGTK_LIST_VIEW_PRESS_LONG_UP);
00158
00159 add_move_binding(binding_set, GDK_Page_Down, 0, ERGTK_LIST_VIEW_PRESS_LONG_DOWN);
00160 add_move_binding(binding_set, GDK_KP_Page_Down, 0, ERGTK_LIST_VIEW_PRESS_LONG_DOWN);
00161
00162 add_move_binding(binding_set, GDK_Home, 0, ERGTK_LIST_VIEW_PRESS_SHORT_UP);
00163 add_move_binding(binding_set, GDK_KP_Home, 0, ERGTK_LIST_VIEW_PRESS_SHORT_UP);
00164
00165 add_move_binding(binding_set, GDK_End, 0, ERGTK_LIST_VIEW_PRESS_SHORT_DOWN);
00166 add_move_binding(binding_set, GDK_KP_End, 0, ERGTK_LIST_VIEW_PRESS_SHORT_DOWN);
00167
00168 add_move_binding(binding_set, GDK_space, 0, ERGTK_LIST_VIEW_PRESS_ACTIVATE);
00169 add_move_binding(binding_set, GDK_Return, 0, ERGTK_LIST_VIEW_PRESS_ACTIVATE);
00170 add_move_binding(binding_set, GDK_ISO_Enter, 0, ERGTK_LIST_VIEW_PRESS_ACTIVATE);
00171 add_move_binding(binding_set, GDK_KP_Enter, 0, ERGTK_LIST_VIEW_PRESS_ACTIVATE);
00172 }
00173
00174
00175
00176 static void ergtk_list_view_init (erGtkListView *er_listview)
00177 {
00178 g_return_if_fail(ERGTK_IS_LIST_VIEW(er_listview));
00179
00180 GtkTreeView* treeview = (GtkTreeView*) er_listview;
00181
00182
00183
00184 gtk_tree_view_set_headers_clickable(treeview, FALSE);
00185 gtk_tree_view_set_enable_search(treeview, FALSE);
00186
00187
00188 er_listview->row_height = -1;
00189 er_listview->is_forced_height = FALSE;
00190 er_listview->is_button_down = FALSE;
00191 }
00192
00193
00194 GType ergtk_list_view_get_type (void)
00195 {
00196 static GType class_type = 0;
00197
00198 if (class_type == 0)
00199 {
00200 static const GTypeInfo class_info =
00201 {
00202 sizeof(erGtkListViewClass),
00203 NULL,
00204 NULL,
00205 (GClassInitFunc) ergtk_list_view_class_init,
00206 NULL,
00207 NULL,
00208 sizeof(erGtkListView),
00209 0,
00210 (GInstanceInitFunc) ergtk_list_view_init,
00211 NULL
00212
00213 };
00214 class_type = g_type_register_static(GTK_TYPE_TREE_VIEW, "erGtkListView", &class_info, 0);
00215 }
00216
00217 return class_type;
00218 }
00219
00220
00221 GtkWidget *ergtk_list_view_new (void)
00222 {
00223 return g_object_new (ERGTK_TYPE_LIST_VIEW, NULL);
00224 }
00225
00226
00227 GtkWidget *ergtk_list_view_new_with_model (GtkTreeModel *model)
00228 {
00229 return g_object_new (ERGTK_TYPE_LIST_VIEW, "model", model, NULL);
00230 }
00231
00232
00233 gint ergtk_list_view_append_column ( erGtkListView *er_listview,
00234 GtkTreeViewColumn *column )
00235 {
00236 g_return_val_if_fail( ERGTK_IS_LIST_VIEW(er_listview), 0 );
00237 g_return_val_if_fail( GTK_IS_TREE_VIEW_COLUMN(column), 0 );
00238
00239 const gchar *title = gtk_tree_view_column_get_title(column);
00240 GtkTreeView *treeview = (GtkTreeView *) er_listview;
00241
00242 gint num_columns = 0;
00243 GtkWidget *widget = NULL;
00244 GtkWidget *label = NULL;
00245 GtkWidget *event_box = NULL;
00246 GtkBox *vbox = NULL;
00247 const gchar *listview_name = gtk_widget_get_name( (GtkWidget*)er_listview );
00248 gchar *header_name = g_strdup_printf("%s-header", listview_name);
00249
00250 LOGPRINTF("entry: title [%s]", title);
00251
00252
00253 if ( gtk_tree_view_get_column(treeview, 0) != NULL )
00254 {
00255 GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
00256 g_object_set( G_OBJECT(renderer),
00257 "xpad", 0,
00258 "ypad", 0,
00259 "text", "",
00260 NULL );
00261 GtkTreeViewColumn *filler_column = gtk_tree_view_column_new_with_attributes( "", renderer, NULL );
00262 gtk_tree_view_column_set_sizing(filler_column, GTK_TREE_VIEW_COLUMN_FIXED);
00263 gtk_tree_view_append_column(treeview, filler_column);
00264 }
00265
00266
00267 if (title)
00268 {
00269 widget = gtk_tree_view_column_get_widget(column);
00270 if (widget == NULL)
00271 {
00272
00273
00274
00275
00276
00277 widget = gtk_vbox_new(FALSE, 0);
00278 vbox = GTK_BOX(widget);
00279
00280 label = gtk_label_new( title );
00281 gtk_widget_set_name(label, header_name);
00282 gtk_misc_set_alignment( GTK_MISC(label), 0.0, 0.0);
00283 gtk_box_pack_start(vbox, label, FALSE, FALSE, 0);
00284
00285 event_box = gtk_event_box_new();
00286 gtk_widget_set_name(event_box, header_name);
00287
00288 gtk_widget_set_size_request(event_box, -1, 15);
00289 GTK_WIDGET_UNSET_FLAGS(event_box, GTK_CAN_FOCUS);
00290 gtk_box_pack_start(vbox, event_box, FALSE, FALSE, 0);
00291
00292 gtk_widget_show_all(widget);
00293 gtk_tree_view_column_set_widget(column, widget);
00294
00295
00296 g_signal_connect(column, "notify::title", G_CALLBACK(on_column_notify_title), label);
00297 }
00298 }
00299
00300
00301 num_columns = gtk_tree_view_append_column(treeview, column);
00302
00303
00304 g_free(header_name);
00305
00306 return num_columns;
00307 }
00308
00309
00310
00311 static void on_column_notify_title ( GObject *object,
00312 GParamSpec *arg1,
00313 gpointer user_data )
00314 {
00315 LOGPRINTF("entry");
00316 g_return_if_fail(GTK_IS_TREE_VIEW_COLUMN(object));
00317 g_return_if_fail(GTK_IS_LABEL(user_data));
00318
00319 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(object);
00320 GtkLabel *label = GTK_LABEL(user_data);
00321
00322 if (column && label)
00323 {
00324 gtk_label_set_text(label, gtk_tree_view_column_get_title(column));
00325 }
00326 }
00327
00328
00329
00330
00331
00332
00333 static void on_style_set (GtkWidget *widget, GtkStyle *previous_style)
00334 {
00335 g_return_if_fail(ERGTK_IS_LIST_VIEW(widget));
00336
00337 GtkWidgetClass* parent_widget_class = GTK_WIDGET_CLASS(g_parent_class);
00338
00339
00340 if (parent_widget_class->style_set)
00341 {
00342 parent_widget_class->style_set(widget, previous_style);
00343 }
00344 }
00345
00346
00347 static void on_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
00348 {
00349 g_return_if_fail(ERGTK_IS_LIST_VIEW(widget));
00350
00351 GtkWidgetClass *parent_widget_class = GTK_WIDGET_CLASS(g_parent_class);
00352 GtkTreeView *treeview = (GtkTreeView *) widget;
00353 erGtkListView *er_listview = (erGtkListView*) widget;
00354
00355 GList *columns = NULL;
00356 GList *p_col;
00357 GtkTreeViewColumn *col;
00358 gint col_idx;
00359 GList *renderers = NULL;
00360 GList *p_rend;
00361 GtkCellRenderer *rend;
00362 GtkWidget *child = NULL;
00363 GtkAllocation child_allocation;
00364 gint focus_line_width = 0;
00365 gint column_spacing = 0;
00366 gint filler_width = 0;
00367 gint row_height = 1;
00368 gboolean is_forced_height = er_listview->is_forced_height;
00369 gint height;
00370
00371 LOGPRINTF("entry");
00372
00373
00374 if (parent_widget_class->size_allocate)
00375 {
00376 parent_widget_class->size_allocate(widget, allocation);
00377 }
00378
00379
00380 gtk_widget_style_get( widget,
00381 "column-spacing", &column_spacing,
00382 "focus-line-width", &focus_line_width,
00383 NULL );
00384 filler_width = column_spacing - (2 * focus_line_width);
00385 if (filler_width < 0)
00386 {
00387 filler_width = 0;
00388 }
00389
00390
00391
00392 columns = gtk_tree_view_get_columns(treeview);
00393 for ( p_col = columns, col_idx = 0 ;
00394 p_col ;
00395 p_col = p_col->next, col_idx++ )
00396 {
00397 col = GTK_TREE_VIEW_COLUMN(p_col->data);
00398
00399 if (col_idx % 2 == 0)
00400 {
00401
00402
00403 child = gtk_tree_view_column_get_widget(col);
00404 if (child)
00405 {
00406 child_allocation = child->allocation;
00407 child_allocation.width = gtk_tree_view_column_get_width(col);
00408 child_allocation.width -= 2 * focus_line_width;
00409 gtk_widget_size_allocate(child, &child_allocation);
00410 }
00411
00412
00413
00414 if ( !is_forced_height )
00415 {
00416 gtk_tree_view_column_cell_get_size(col, NULL, NULL, NULL, NULL, &height );
00417 LOGPRINTF("height [%d]", height);
00418 if (height > row_height)
00419 {
00420 row_height = height;
00421 }
00422 }
00423 }
00424 else
00425 {
00426
00427
00428 gtk_tree_view_column_set_min_width(col, filler_width);
00429 }
00430 }
00431
00432
00433 if (is_forced_height)
00434 {
00435 row_height = er_listview->row_height;
00436 }
00437 else
00438 {
00439 er_listview->row_height = row_height;
00440 }
00441 row_height -= 2 * focus_line_width;
00442 for ( p_col = columns, col_idx = 0 ;
00443 p_col ;
00444 p_col = p_col->next, col_idx++ )
00445 {
00446 col = GTK_TREE_VIEW_COLUMN(p_col->data);
00447
00448 if (col_idx % 2 == 0)
00449 {
00450
00451
00452
00453 renderers = gtk_tree_view_column_get_cell_renderers(col);
00454 for ( p_rend = renderers ; p_rend ; p_rend = p_rend->next )
00455 {
00456 rend = GTK_CELL_RENDERER(p_rend->data);
00457 gtk_cell_renderer_set_fixed_size(rend, -1, row_height);
00458 }
00459 g_list_free(renderers);
00460 renderers = NULL;
00461 }
00462 }
00463
00464
00465 g_list_free(columns);
00466 columns = NULL;
00467 }
00468
00469
00470 static gboolean on_button_press_event (GtkWidget *widget,
00471 GdkEventButton *event)
00472 {
00473 g_return_val_if_fail(ERGTK_IS_LIST_VIEW(widget), FALSE);
00474
00475 GtkTreeView *treeview = (GtkTreeView *) widget;
00476 erGtkListView *er_listview = (erGtkListView*) widget;
00477 GtkTreePath *path = NULL;
00478 gint *pi;
00479 gint item_idx = 0;
00480 gboolean ok;
00481
00482 LOGPRINTF("entry: x y [%lf %lf] button [%d]", event->x, event->y, event->button);
00483
00484
00485 ok = gtk_tree_view_get_path_at_pos(treeview, event->x, event->y, &path, NULL, NULL, NULL);
00486 if (ok && path)
00487 {
00488 pi = gtk_tree_path_get_indices(path);
00489 if (pi)
00490 {
00491 item_idx = *pi;
00492 }
00493 }
00494 LOGPRINTF("item_idx [%d]", item_idx);
00495
00496
00497 if ( ok
00498 && path
00499 && event->button == 1
00500 && event->type == GDK_BUTTON_PRESS )
00501 {
00502
00503 er_listview->is_button_down = TRUE;
00504 er_listview->press_event_button = event->button;
00505 er_listview->press_event_state = event->state;
00506 er_listview->press_event_x = event->x;
00507 er_listview->press_event_y = event->y;
00508
00509
00510 er_listview->press_item_idx = item_idx;
00511
00512
00513 ergtk_list_view_set_cursor(er_listview, item_idx);
00514 }
00515 else
00516 {
00517 er_listview->is_button_down = FALSE;
00518 }
00519 LOGPRINTF("is_down [%d] item_idx [%d]", er_listview->is_button_down, item_idx);
00520
00521
00522 if (path) { gtk_tree_path_free(path); }
00523
00524 return TRUE;
00525 }
00526
00527
00528 static gboolean on_button_release_event (GtkWidget *widget,
00529 GdkEventButton *event)
00530 {
00531 g_return_val_if_fail(ERGTK_IS_LIST_VIEW(widget), FALSE);
00532
00533 GtkTreeView *treeview = (GtkTreeView *) widget;
00534 erGtkListView *er_listview = (erGtkListView*) widget;
00535 GtkTreePath *path = NULL;
00536 gint *pi;
00537 gint item_idx = 0;
00538 gboolean ok;
00539
00540
00541 ok = gtk_tree_view_get_path_at_pos(treeview, event->x, event->y, &path, NULL, NULL, NULL);
00542 if (ok && path)
00543 {
00544
00545 pi = gtk_tree_path_get_indices(path);
00546 if (pi)
00547 {
00548 item_idx = *pi;
00549 }
00550
00551
00552 if ( event->button == 1
00553 && er_listview->is_button_down
00554 && er_listview->press_event_button == event->button
00555 && er_listview->press_item_idx == item_idx )
00556 {
00557 LOGPRINTF("activate row [%d]", item_idx);
00558 gtk_tree_view_row_activated(treeview, path, NULL);
00559 }
00560 }
00561
00562
00563 er_listview->is_button_down = FALSE;
00564
00565
00566 if (path) { gtk_tree_path_free(path); }
00567
00568 return TRUE;
00569 }
00570
00571
00572 static gboolean on_motion_notify_event(GtkWidget *widget,
00573 GdkEventMotion *event)
00574 {
00575
00576 return TRUE;
00577 }
00578
00579
00580 static void on_realize(GtkWidget *widget)
00581 {
00582 GtkWidgetClass *parent_widget_class = GTK_WIDGET_CLASS(g_parent_class);
00583
00584
00585 if (parent_widget_class->realize)
00586 {
00587 parent_widget_class->realize(widget);
00588 }
00589
00590
00591 GdkEventMask mask = gdk_window_get_events(widget->window);
00592 gdk_window_set_events(widget->window, mask & ~(GDK_POINTER_MOTION_MASK));
00593 }
00594
00595
00596 void ergtk_list_view_get_cursor (erGtkListView *er_listview, gint *row)
00597 {
00598 GtkTreeView *treeview = (GtkTreeView*) er_listview;
00599 GtkTreePath *path = NULL;
00600 gint *pi;
00601 gint currow = -1;
00602
00603 g_return_if_fail(ERGTK_LIST_VIEW(er_listview));
00604
00605 if (row != NULL)
00606 {
00607 path = gtk_tree_path_new();
00608 gtk_tree_view_get_cursor(treeview, &path, NULL);
00609 if (path == NULL)
00610 {
00611 LOGPRINTF("no cursor set");
00612 }
00613 else
00614 {
00615 pi = gtk_tree_path_get_indices(path);
00616 if (pi)
00617 {
00618 currow = *pi;
00619 }
00620 }
00621 gtk_tree_path_free(path);
00622
00623 *row = currow;
00624 }
00625 }
00626
00627
00628 void ergtk_list_view_get_view_size (erGtkListView *er_listview, gint *num_rows, gint *num_items)
00629 {
00630 g_return_if_fail(ERGTK_IS_LIST_VIEW(er_listview));
00631
00632 GtkTreeView *treeview = (GtkTreeView*) er_listview;
00633 GdkRectangle visible_rect;
00634 GtkTreePath *path = NULL;
00635 gboolean ok;
00636 gint *pi;
00637 gint vertical_separator = 0;
00638
00639 LOGPRINTF("entry");
00640
00641
00642 gtk_widget_style_get( GTK_WIDGET(er_listview),
00643 "vertical-separator", &vertical_separator,
00644 NULL );
00645
00646
00647 if (num_rows != NULL)
00648 {
00649
00650 gtk_tree_view_get_visible_rect(treeview, &visible_rect);
00651 if ( visible_rect.height > 0
00652 && er_listview->row_height > 0 )
00653 {
00654 *num_rows = visible_rect.height / (er_listview->row_height + vertical_separator);
00655 }
00656 else
00657 {
00658 *num_rows = 1;
00659 }
00660 LOGPRINTF("num_rows [%d]", *num_rows);
00661 }
00662
00663
00664 if (num_items != NULL)
00665 {
00666 pi = NULL;
00667 ok = gtk_tree_view_get_visible_range(treeview, NULL, &path);
00668 if (ok && path)
00669 {
00670 pi = gtk_tree_path_get_indices(path);
00671 }
00672
00673 if (pi)
00674 {
00675 *num_items = *pi + 1;
00676 }
00677 else
00678 {
00679 *num_items = 0;
00680 }
00681 LOGPRINTF("num_items [%d]", *num_items);
00682
00683
00684 if (path) { gtk_tree_path_free(path); }
00685 path = NULL;
00686 }
00687 LOGPRINTF("leave");
00688 }
00689
00690
00691 void ergtk_list_view_set_cursor (erGtkListView *er_listview, gint row)
00692 {
00693 g_return_if_fail(ERGTK_IS_LIST_VIEW(er_listview));
00694
00695 GtkTreeView *treeview = (GtkTreeView*) er_listview;
00696 GtkWidget *widget = (GtkWidget *) er_listview;
00697 GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
00698
00699 GtkTreePath *path = NULL;
00700 gint num_rows = 0;
00701 gint num_items = 0;
00702
00703 LOGPRINTF("entry: row %d", row);
00704
00705 ergtk_list_view_get_view_size(er_listview, &num_rows, &num_items);
00706 LOGPRINTF("num_rows %d, num_items %d", num_rows, num_items);
00707
00708
00709 if (row >= num_items)
00710 {
00711 row = num_items - 1;
00712 }
00713 if (row < 0)
00714 {
00715 row = -1;
00716 }
00717
00718
00719 if (num_items > 0)
00720 {
00721 path = gtk_tree_path_new_from_indices(row, -1);
00722 gtk_widget_grab_focus (widget);
00723 gtk_tree_selection_select_path(selection, path);
00724 gtk_tree_view_set_cursor(treeview, path, NULL, FALSE);
00725 }
00726
00727
00728 if (path) { gtk_tree_path_free(path); }
00729
00730 return;
00731 }
00732
00733
00734 void ergtk_list_view_set_focus_mode (erGtkListView *er_listview,
00735 gboolean focus_in,
00736 gboolean focus_out)
00737 {
00738 LOGPRINTF("entry");
00739
00740 if (!focus_in)
00741 {
00742
00743 g_signal_connect(G_OBJECT(er_listview), "focus-in-event", G_CALLBACK (on_focus_in), NULL);
00744 }
00745 if (!focus_out)
00746 {
00747
00748 g_signal_connect(G_OBJECT(er_listview), "focus-out-event", G_CALLBACK (on_focus_out), NULL);
00749 }
00750 }
00751
00752
00753 void ergtk_list_view_set_row_height (erGtkListView *er_listview, gint row_height)
00754 {
00755 g_return_if_fail(ERGTK_IS_LIST_VIEW(er_listview));
00756
00757 gint focus_line_width = 0;
00758
00759 LOGPRINTF("entry");
00760
00761 if (row_height > 0)
00762 {
00763 gtk_widget_style_get( GTK_WIDGET(er_listview),
00764 "focus-line-width", &focus_line_width,
00765 NULL );
00766 er_listview->row_height = row_height + (2 * focus_line_width);
00767 er_listview->is_forced_height = TRUE;
00768 }
00769 else
00770 {
00771 er_listview->row_height = -1;
00772 er_listview->is_forced_height = FALSE;
00773 }
00774 }
00775
00776
00777
00778
00779
00780
00781 static gboolean on_pre_move_cursor (erGtkListView *er_listview,
00782 erGtkListViewKeyPress navigate )
00783 {
00784 GtkTreeView *treeview = (GtkTreeView *) er_listview;
00785
00786 gboolean rc;
00787 GtkTreePath *path = NULL;
00788 gint currow = 0;
00789 gint num_rows = 0;
00790 gint num_items = 0;
00791
00792 g_return_val_if_fail (ERGTK_LIST_VIEW (er_listview), FALSE);
00793
00794 if (!GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (er_listview)))
00795 {
00796 WARNPRINTF("widget has no focus");
00797 return FALSE;
00798 }
00799
00800 ergtk_list_view_get_cursor(er_listview, &currow);
00801 ergtk_list_view_get_view_size(er_listview, &num_rows, &num_items);
00802
00803 LOGPRINTF("navigate [%d] currow [%d] num_rows [%d] num_items [%d]",
00804 navigate, currow, num_rows, num_items );
00805
00806 switch (navigate)
00807 {
00808 case ERGTK_LIST_VIEW_PRESS_SHORT_UP:
00809 if (currow > 0)
00810 {
00811
00812 g_signal_emit_by_name(er_listview, "move-cursor", GTK_MOVEMENT_DISPLAY_LINES, -1, &rc);
00813 }
00814 else
00815 {
00816
00817 g_signal_emit_by_name(er_listview, "navigate-cursor", ERGTK_LIST_VIEW_PRESS_SHORT_UP);
00818 }
00819 break;
00820
00821 case ERGTK_LIST_VIEW_PRESS_SHORT_DOWN:
00822 if (currow + 1 < num_items)
00823 {
00824 g_signal_emit_by_name (er_listview, "move-cursor", GTK_MOVEMENT_DISPLAY_LINES, 1, &rc);
00825 }
00826 else
00827 {
00828 g_signal_emit_by_name(er_listview, "navigate-cursor", ERGTK_LIST_VIEW_PRESS_SHORT_DOWN);
00829 }
00830 break;
00831
00832 case ERGTK_LIST_VIEW_PRESS_LONG_UP:
00833 g_signal_emit_by_name(er_listview, "navigate-cursor", ERGTK_LIST_VIEW_PRESS_LONG_UP);
00834 break;
00835
00836 case ERGTK_LIST_VIEW_PRESS_LONG_DOWN:
00837 g_signal_emit_by_name(er_listview, "navigate-cursor", ERGTK_LIST_VIEW_PRESS_LONG_DOWN);
00838 break;
00839
00840 case ERGTK_LIST_VIEW_PRESS_ACTIVATE:
00841 gtk_tree_view_row_activated(treeview, path, NULL);
00842 break;
00843
00844 default:
00845 g_assert_not_reached();
00846 break;
00847 }
00848
00849
00850 if (path) { gtk_tree_path_free(path); }
00851
00852 return TRUE;
00853 }
00854
00855
00856 static void
00857 add_move_binding (GtkBindingSet *binding_set,
00858 guint keyval,
00859 GdkModifierType modmask,
00860 erGtkListViewKeyPress navigate)
00861 {
00862 gtk_binding_entry_add_signal(binding_set, keyval, modmask,
00863 "pre-move-cursor", 1,
00864 G_TYPE_ENUM, navigate);
00865
00866 gtk_binding_entry_add_signal(binding_set, keyval, GDK_SHIFT_MASK,
00867 "pre-move-cursor", 1,
00868 G_TYPE_ENUM, navigate);
00869
00870 if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
00871 {
00872 return;
00873 }
00874
00875 gtk_binding_entry_add_signal(binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
00876 "pre-move-cursor", 1,
00877 G_TYPE_ENUM, navigate);
00878
00879 gtk_binding_entry_add_signal(binding_set, keyval, GDK_CONTROL_MASK,
00880 "pre-move-cursor", 1,
00881 G_TYPE_ENUM, navigate);
00882 }
00883
00884
00885 static gboolean on_focus_in(GtkWidget *widget, gpointer data)
00886 {
00887 LOGPRINTF("entry");
00888
00889
00890 return TRUE;
00891 }
00892
00893
00894 static gboolean on_focus_out(GtkWidget *widget, gpointer data)
00895 {
00896 LOGPRINTF("entry");
00897
00898
00899 return TRUE;
00900 }
00901