static void esm_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { ESelectionModel *esm = E_SELECTION_MODEL (object); switch (property_id) { case PROP_SORTER: drop_sorter (esm); add_sorter ( esm, g_value_get_object (value) ? E_SORTER (g_value_get_object (value)) : NULL); break; case PROP_SELECTION_MODE: esm->mode = g_value_get_int (value); if (esm->mode == GTK_SELECTION_SINGLE) { gint cursor_row = e_selection_model_cursor_row (esm); gint cursor_col = e_selection_model_cursor_col (esm); e_selection_model_do_something (esm, cursor_row, cursor_col, 0); } break; case PROP_CURSOR_MODE: esm->cursor_mode = g_value_get_int (value); break; } }
static void reflow_columns (EReflow *reflow) { GSList *list; int count; int start; int i; int column_count, column_start; double running_height; if (reflow->reflow_from_column <= 1) { start = 0; column_count = 1; column_start = 0; } else { /* we start one column before the earliest new entry, so we can handle the case where the new entry is inserted at the start of the column */ column_start = reflow->reflow_from_column - 1; start = reflow->columns[column_start]; column_count = column_start + 1; } list = NULL; running_height = E_REFLOW_BORDER_WIDTH; count = reflow->count - start; for (i = start; i < count; i++) { int unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i); if (i != 0 && running_height + reflow->heights[unsorted] + E_REFLOW_BORDER_WIDTH > reflow->height) { list = g_slist_prepend (list, GINT_TO_POINTER(i)); column_count ++; running_height = E_REFLOW_BORDER_WIDTH * 2 + reflow->heights[unsorted]; } else running_height += reflow->heights[unsorted] + E_REFLOW_BORDER_WIDTH; } reflow->column_count = column_count; reflow->columns = g_renew (int, reflow->columns, column_count); column_count --; for (; column_count > column_start; column_count--) { GSList *to_free; reflow->columns[column_count] = GPOINTER_TO_INT(list->data); to_free = list; list = list->next; g_slist_free_1 (to_free); } reflow->columns[column_start] = start; queue_incarnate (reflow); reflow->need_reflow_columns = FALSE; reflow->reflow_from_column = -1; }
static void items_inserted (EReflowModel *model, int position, int count, EReflow *reflow) { int i, oldcount; if (position < 0 || position > reflow->count) return; oldcount = reflow->count; reflow->count += count; if (reflow->count > reflow->allocated_count) { while (reflow->count > reflow->allocated_count) reflow->allocated_count += 256; reflow->heights = g_renew (int, reflow->heights, reflow->allocated_count); reflow->items = g_renew (GnomeCanvasItem *, reflow->items, reflow->allocated_count); } memmove (reflow->heights + position + count, reflow->heights + position, (reflow->count - position - count) * sizeof (int)); memmove (reflow->items + position + count, reflow->items + position, (reflow->count - position - count) * sizeof (GnomeCanvasItem *)); for (i = position; i < position + count; i++) { reflow->items[i] = NULL; reflow->heights[i] = e_reflow_model_height (reflow->model, i, GNOME_CANVAS_GROUP (reflow)); } e_selection_model_simple_set_row_count (E_SELECTION_MODEL_SIMPLE (reflow->selection), reflow->count); if (position == oldcount) e_sorter_array_append (reflow->sorter, count); else e_sorter_array_set_count (reflow->sorter, reflow->count); for (i = position; i < position + count; i ++) { int sorted = e_sorter_model_to_sorted (E_SORTER (reflow->sorter), i); int c; for (c = reflow->column_count - 1; c >= 0; c--) { int start_of_column = reflow->columns[c]; if (start_of_column <= sorted) { if (reflow->reflow_from_column == -1 || reflow->reflow_from_column > c) { reflow->reflow_from_column = c; } break; } } } reflow->need_reflow_columns = TRUE; set_empty (reflow); e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow)); }
static void e_reflow_reflow( GnomeCanvasItem *item, int flags ) { EReflow *reflow = E_REFLOW(item); gdouble old_width; gdouble running_width; gdouble running_height; int next_column; int i; if (! (GTK_OBJECT_FLAGS (reflow) & GNOME_CANVAS_ITEM_REALIZED)) return; if (reflow->need_reflow_columns) { reflow_columns (reflow); } old_width = reflow->width; running_width = E_REFLOW_BORDER_WIDTH; running_height = E_REFLOW_BORDER_WIDTH; next_column = 1; for (i = 0; i < reflow->count; i++) { int unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i); if (next_column < reflow->column_count && i == reflow->columns[next_column]) { running_height = E_REFLOW_BORDER_WIDTH; running_width += reflow->column_width + E_REFLOW_FULL_GUTTER; next_column ++; } if (unsorted >= 0 && reflow->items[unsorted]) { e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(reflow->items[unsorted]), (double) running_width, (double) running_height); running_height += reflow->heights[unsorted] + E_REFLOW_BORDER_WIDTH; } } reflow->width = running_width + reflow->column_width + E_REFLOW_BORDER_WIDTH; if ( reflow->width < reflow->minimum_width ) reflow->width = reflow->minimum_width; if (old_width != reflow->width) e_canvas_item_request_parent_reflow(item); }
static void incarnate (EReflow *reflow) { int column_width; int first_column; int last_column; int first_cell; int last_cell; int i; GtkAdjustment *adjustment = gtk_layout_get_hadjustment (GTK_LAYOUT (GNOME_CANVAS_ITEM (reflow)->canvas)); column_width = reflow->column_width; first_column = adjustment->value - 1 + E_REFLOW_BORDER_WIDTH; first_column /= column_width + E_REFLOW_FULL_GUTTER; last_column = adjustment->value + adjustment->page_size + 1 - E_REFLOW_BORDER_WIDTH - E_REFLOW_DIVIDER_WIDTH; last_column /= column_width + E_REFLOW_FULL_GUTTER; last_column ++; if (first_column >= 0 && first_column < reflow->column_count) first_cell = reflow->columns[first_column]; else first_cell = 0; if (last_column >= 0 && last_column < reflow->column_count) last_cell = reflow->columns[last_column]; else last_cell = reflow->count; for (i = first_cell; i < last_cell; i++) { int unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i); if (reflow->items[unsorted] == NULL) { if (reflow->model) { reflow->items[unsorted] = e_reflow_model_incarnate (reflow->model, unsorted, GNOME_CANVAS_GROUP (reflow)); g_object_set (reflow->items[unsorted], "selected", e_selection_model_is_row_selected(E_SELECTION_MODEL(reflow->selection), unsorted), "width", (double) reflow->column_width, NULL); } } } reflow->incarnate_idle_id = 0; }
static void item_removed (EReflowModel *model, int i, EReflow *reflow) { int c; int sorted; if (i < 0 || i >= reflow->count) return; sorted = e_sorter_model_to_sorted (E_SORTER (reflow->sorter), i); for (c = reflow->column_count - 1; c >= 0; c--) { int start_of_column = reflow->columns[c]; if (start_of_column <= sorted) { if (reflow->reflow_from_column == -1 || reflow->reflow_from_column > c) { reflow->reflow_from_column = c; } break; } } if (reflow->items[i]) gtk_object_destroy (GTK_OBJECT (reflow->items[i])); memmove (reflow->heights + i, reflow->heights + i + 1, (reflow->count - i - 1) * sizeof (int)); memmove (reflow->items + i, reflow->items + i + 1, (reflow->count - i - 1) * sizeof (GnomeCanvasItem *)); reflow->count --; reflow->heights [reflow->count] = 0; reflow->items [reflow->count] = NULL; reflow->need_reflow_columns = TRUE; set_empty (reflow); e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow)); e_sorter_array_set_count (reflow->sorter, reflow->count); e_selection_model_simple_delete_rows (E_SELECTION_MODEL_SIMPLE (reflow->selection), i, 1); }
static gboolean e_reflow_event (GnomeCanvasItem *item, GdkEvent *event) { EReflow *reflow; int return_val = FALSE; reflow = E_REFLOW (item); switch( event->type ) { case GDK_KEY_PRESS: return_val = e_selection_model_key_press(reflow->selection, (GdkEventKey *) event); break; #if 0 if (event->key.keyval == GDK_Tab || event->key.keyval == GDK_KP_Tab || event->key.keyval == GDK_ISO_Left_Tab) { int i; int count; count = reflow->count; for (i = 0; i < count; i++) { int unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i); GnomeCanvasItem *item = reflow->items[unsorted]; EFocus has_focus; if (item) { g_object_get(item, "has_focus", &has_focus, NULL); if (has_focus) { if (event->key.state & GDK_SHIFT_MASK) { if (i == 0) return FALSE; i--; } else { if (i == count - 1) return FALSE; i++; } unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i); if (reflow->items[unsorted] == NULL) { reflow->items[unsorted] = e_reflow_model_incarnate (reflow->model, unsorted, GNOME_CANVAS_GROUP (reflow)); } item = reflow->items[unsorted]; gnome_canvas_item_set(item, "has_focus", (event->key.state & GDK_SHIFT_MASK) ? E_FOCUS_END : E_FOCUS_START, NULL); return TRUE; } } } } #endif case GDK_BUTTON_PRESS: switch(event->button.button) { case 1: { GdkEventButton *button = (GdkEventButton *) event; double n_x, max_x; n_x = button->x; n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH; n_x = fmod(n_x,(reflow->column_width + E_REFLOW_FULL_GUTTER)); max_x = E_REFLOW_BORDER_WIDTH; max_x += (reflow->column_width + E_REFLOW_FULL_GUTTER) * reflow->column_count; if ( button->y >= E_REFLOW_BORDER_WIDTH && button->y <= reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER && max_x > button->x ) { /* don't allow to drag the first line*/ if (e_reflow_pick_line(reflow, button->x) == 0) return TRUE; reflow->which_column_dragged = e_reflow_pick_line(reflow, button->x); reflow->start_x = reflow->which_column_dragged * (reflow->column_width + E_REFLOW_FULL_GUTTER) - E_REFLOW_DIVIDER_WIDTH / 2; reflow->temp_column_width = reflow->column_width; reflow->column_drag = TRUE; gnome_canvas_item_grab (item, GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK, reflow->arrow_cursor, button->time); reflow->previous_temp_column_width = -1; reflow->need_column_resize = TRUE; gnome_canvas_item_request_update(item); return TRUE; } } break; case 4: { GtkAdjustment *adjustment = gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas)); gdouble new_value = adjustment->value; new_value -= adjustment->step_increment; gtk_adjustment_set_value(adjustment, new_value); } break; case 5: { GtkAdjustment *adjustment = gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas)); gdouble new_value = adjustment->value; new_value += adjustment->step_increment; if ( new_value > adjustment->upper - adjustment->page_size ) new_value = adjustment->upper - adjustment->page_size; gtk_adjustment_set_value(adjustment, new_value); } break; } break; case GDK_BUTTON_RELEASE: if (reflow->column_drag) { gdouble old_width = reflow->column_width; GdkEventButton *button = (GdkEventButton *) event; GtkAdjustment *adjustment = gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas)); reflow->temp_column_width = reflow->column_width + (button->x - reflow->start_x)/(reflow->which_column_dragged - e_reflow_pick_line(reflow, adjustment->value)); if ( reflow->temp_column_width < 50 ) reflow->temp_column_width = 50; reflow->column_drag = FALSE; if ( old_width != reflow->temp_column_width ) { gtk_adjustment_set_value(adjustment, adjustment->value + e_reflow_pick_line(reflow, adjustment->value) * (reflow->temp_column_width - reflow->column_width)); reflow->column_width = reflow->temp_column_width; adjustment->step_increment = (reflow->column_width + E_REFLOW_FULL_GUTTER) / 2; adjustment->page_increment = adjustment->page_size - adjustment->step_increment; gtk_adjustment_changed(adjustment); e_reflow_resize_children(item); e_canvas_item_request_reflow(item); gnome_canvas_request_redraw(item->canvas, 0, 0, reflow->width, reflow->height); column_width_changed (reflow); } reflow->need_column_resize = TRUE; gnome_canvas_item_request_update(item); gnome_canvas_item_ungrab (item, button->time); return TRUE; } break; case GDK_MOTION_NOTIFY: if (reflow->column_drag) { double old_width = reflow->temp_column_width; GdkEventMotion *motion = (GdkEventMotion *) event; GtkAdjustment *adjustment = gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas)); reflow->temp_column_width = reflow->column_width + (motion->x - reflow->start_x)/(reflow->which_column_dragged - e_reflow_pick_line(reflow, adjustment->value)); if (reflow->temp_column_width < 50) reflow->temp_column_width = 50; if (old_width != reflow->temp_column_width) { reflow->need_column_resize = TRUE; gnome_canvas_item_request_update(item); } return TRUE; } else { GdkEventMotion *motion = (GdkEventMotion *) event; double n_x, max_x; n_x = motion->x; n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH; n_x = fmod(n_x,(reflow->column_width + E_REFLOW_FULL_GUTTER)); max_x = E_REFLOW_BORDER_WIDTH; max_x += (reflow->column_width + E_REFLOW_FULL_GUTTER) * reflow->column_count; if ( motion->y >= E_REFLOW_BORDER_WIDTH && motion->y <= reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER && max_x > motion->x) { if ( reflow->default_cursor_shown ) { gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, reflow->arrow_cursor); reflow->default_cursor_shown = FALSE; } } else if ( ! reflow->default_cursor_shown ) { gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, reflow->default_cursor); reflow->default_cursor_shown = TRUE; } } break; case GDK_ENTER_NOTIFY: if (!reflow->column_drag) { GdkEventCrossing *crossing = (GdkEventCrossing *) event; double n_x, max_x; n_x = crossing->x; n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH; n_x = fmod(n_x,(reflow->column_width + E_REFLOW_FULL_GUTTER)); max_x = E_REFLOW_BORDER_WIDTH; max_x += (reflow->column_width + E_REFLOW_FULL_GUTTER) * reflow->column_count; if ( crossing->y >= E_REFLOW_BORDER_WIDTH && crossing->y <= reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER && max_x > crossing->x) { if ( reflow->default_cursor_shown ) { gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, reflow->arrow_cursor); reflow->default_cursor_shown = FALSE; } } } break; case GDK_LEAVE_NOTIFY: if (!reflow->column_drag) { GdkEventCrossing *crossing = (GdkEventCrossing *) event; double n_x; n_x = crossing->x; n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH; n_x = fmod(n_x,(reflow->column_width + E_REFLOW_FULL_GUTTER)); if ( !( crossing->y >= E_REFLOW_BORDER_WIDTH && crossing->y <= reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER ) ) { if ( ! reflow->default_cursor_shown ) { gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, reflow->default_cursor); reflow->default_cursor_shown = TRUE; } } } break; default: break; } if (return_val) return return_val; else if (GNOME_CANVAS_ITEM_CLASS( e_reflow_parent_class )->event) return (* GNOME_CANVAS_ITEM_CLASS( e_reflow_parent_class )->event) (item, event); else return FALSE; }