X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkctree.c;h=1fac2ce5cbbe4dc4177a2a8561fb189f6c82e5c4;hb=4b83b736284e36e24043533f69eb4bc374f5e141;hp=1b4ea3eccd2439e6d71e1850d8c7b7dae31d3f59;hpb=e3b8e185242cc0506bdcaed4ddc9e565e96ec86e;p=~andy%2Fgtk diff --git a/gtk/gtkctree.c b/gtk/gtkctree.c index 1b4ea3ecc..1fac2ce5c 100644 --- a/gtk/gtkctree.c +++ b/gtk/gtkctree.c @@ -6,32 +6,39 @@ * Copyright (C) 1998 Lars Hamann and Stefan Jeske * * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public + * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU Library General Public + * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + #include #include "gtkctree.h" #include "gtkbindings.h" #include "gtkmain.h" -#include +#include "gtkdnd.h" #include #define PM_SIZE 8 #define TAB_SIZE (PM_SIZE + 6) #define CELL_SPACING 1 -#define CLIST_OPTIMUM_SIZE 512 +#define CLIST_OPTIMUM_SIZE 64 #define COLUMN_INSET 3 #define DRAG_WIDTH 6 @@ -44,54 +51,118 @@ + (clist)->hoffset) #define COLUMN_LEFT(clist, column) ((clist)->column[(column)].area.x) -#define GTK_CLIST_CLASS_FW(_widget_) GTK_CLIST_CLASS (GTK_OBJECT (_widget_)->klass) +static inline gint +COLUMN_FROM_XPIXEL (GtkCList * clist, + gint x) +{ + gint i, cx; + + for (i = 0; i < clist->columns; i++) + if (clist->column[i].visible) + { + cx = clist->column[i].area.x + clist->hoffset; + + if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) && + x <= (cx + clist->column[i].area.width + COLUMN_INSET)) + return i; + } + + /* no match */ + return -1; +} +#define CLIST_UNFROZEN(clist) (((GtkCList*) (clist))->freeze_count == 0) +#define CLIST_REFRESH(clist) G_STMT_START { \ + if (CLIST_UNFROZEN (clist)) \ + GTK_CLIST_GET_CLASS (clist)->refresh ((GtkCList*) (clist)); \ +} G_STMT_END + + +enum { + ARG_0, + ARG_N_COLUMNS, + ARG_TREE_COLUMN, + ARG_INDENT, + ARG_SPACING, + ARG_SHOW_STUB, + ARG_LINE_STYLE, + ARG_EXPANDER_STYLE +}; -static void gtk_ctree_class_init (GtkCTreeClass *klass); -static void gtk_ctree_init (GtkCTree *ctree); -static void gtk_ctree_destroy (GtkObject *object); +static void gtk_ctree_class_init (GtkCTreeClass *klass); +static void gtk_ctree_init (GtkCTree *ctree); +static GObject* gtk_ctree_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params); +static void gtk_ctree_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void gtk_ctree_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); static void gtk_ctree_realize (GtkWidget *widget); static void gtk_ctree_unrealize (GtkWidget *widget); static gint gtk_ctree_button_press (GtkWidget *widget, GdkEventButton *event); -static gint gtk_ctree_button_release (GtkWidget *widget, - GdkEventButton *event); -static gint gtk_ctree_button_motion (GtkWidget *widget, - GdkEventMotion *event); +static void ctree_attach_styles (GtkCTree *ctree, + GtkCTreeNode *node, + gpointer data); +static void ctree_detach_styles (GtkCTree *ctree, + GtkCTreeNode *node, + gpointer data); +static gint draw_cell_pixmap (GdkWindow *window, + GdkRectangle *clip_rectangle, + GdkGC *fg_gc, + GdkPixmap *pixmap, + GdkBitmap *mask, + gint x, + gint y, + gint width, + gint height); +static void get_cell_style (GtkCList *clist, + GtkCListRow *clist_row, + gint state, + gint column, + GtkStyle **style, + GdkGC **fg_gc, + GdkGC **bg_gc); +static gint gtk_ctree_draw_expander (GtkCTree *ctree, + GtkCTreeRow *ctree_row, + GtkStyle *style, + GdkRectangle *clip_rectangle, + gint x); +static gint gtk_ctree_draw_lines (GtkCTree *ctree, + GtkCTreeRow *ctree_row, + gint row, + gint column, + gint state, + GdkRectangle *clip_rectangle, + GdkRectangle *cell_rectangle, + GdkRectangle *crect, + GdkRectangle *area, + GtkStyle *style); static void draw_row (GtkCList *clist, GdkRectangle *area, gint row, - GtkCListRow *clist_row); -static void create_xor_gc (GtkCTree *ctree); -static void draw_xor_line (GtkCTree *ctree); -static void draw_xor_rect (GtkCTree *ctree); -static void create_drag_icon (GtkCTree *ctree, - GtkCTreeRow *row); + GtkCListRow *clist_row); +static void draw_drag_highlight (GtkCList *clist, + GtkCListRow *dest_row, + gint dest_row_number, + GtkCListDragPos drag_pos); static void tree_draw_node (GtkCTree *ctree, GtkCTreeNode *node); -static void cell_empty (GtkCList *clist, - GtkCListRow *clist_row, - gint column); -static void cell_set_text (GtkCList *clist, +static void set_cell_contents (GtkCList *clist, GtkCListRow *clist_row, gint column, - gchar *text); -static void cell_set_pixmap (GtkCList *clist, - GtkCListRow *clist_row, - gint column, - GdkPixmap *pixmap, - GdkBitmap *mask); -static void cell_set_pixtext (GtkCList *clist, - GtkCListRow *clist_row, - gint column, - gchar *text, + GtkCellType type, + const gchar *text, guint8 spacing, GdkPixmap *pixmap, GdkBitmap *mask); static void set_node_info (GtkCTree *ctree, GtkCTreeNode *node, - gchar *text, + const gchar *text, guint8 spacing, GdkPixmap *pixmap_closed, GdkBitmap *mask_closed, @@ -148,9 +219,6 @@ static void real_tree_select (GtkCTree *ctree, static void real_tree_unselect (GtkCTree *ctree, GtkCTreeNode *node, gint column); -static void tree_toggle_selection (GtkCTree *ctree, - GtkCTreeNode *node, - gint column); static void real_tree_expand (GtkCTree *ctree, GtkCTreeNode *node); static void real_tree_collapse (GtkCTree *ctree, @@ -159,6 +227,9 @@ static void real_tree_move (GtkCTree *ctree, GtkCTreeNode *node, GtkCTreeNode *new_parent, GtkCTreeNode *new_sibling); +static void real_row_move (GtkCList *clist, + gint source_row, + gint dest_row); static void gtk_ctree_link (GtkCTree *ctree, GtkCTreeNode *node, GtkCTreeNode *parent, @@ -177,12 +248,6 @@ static gboolean ctree_is_hot_spot (GtkCTree *ctree, static void tree_sort (GtkCTree *ctree, GtkCTreeNode *node, gpointer data); -static gint default_compare (GtkCTree *ctree, - const GtkCTreeNode *node1, - const GtkCTreeNode *node2); - - - static void fake_unselect_all (GtkCList *clist, gint row); static GList * selection_find (GtkCList *clist, @@ -194,8 +259,46 @@ static void real_undo_selection (GtkCList *clist); static void select_row_recursive (GtkCTree *ctree, GtkCTreeNode *node, gpointer data); - - +static gint real_insert_row (GtkCList *clist, + gint row, + gchar *text[]); +static void real_remove_row (GtkCList *clist, + gint row); +static void real_sort_list (GtkCList *clist); +static void cell_size_request (GtkCList *clist, + GtkCListRow *clist_row, + gint column, + GtkRequisition *requisition); +static void column_auto_resize (GtkCList *clist, + GtkCListRow *clist_row, + gint column, + gint old_width); +static void auto_resize_columns (GtkCList *clist); + + +static gboolean check_drag (GtkCTree *ctree, + GtkCTreeNode *drag_source, + GtkCTreeNode *drag_target, + GtkCListDragPos insert_pos); +static void gtk_ctree_drag_begin (GtkWidget *widget, + GdkDragContext *context); +static gint gtk_ctree_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); +static void gtk_ctree_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint32 time); +static void remove_grab (GtkCList *clist); +static void drag_dest_cell (GtkCList *clist, + gint x, + gint y, + GtkCListDestInfo *dest_info); enum @@ -209,26 +312,6 @@ enum LAST_SIGNAL }; -typedef void (*GtkCTreeSignal1) (GtkObject *object, - GtkCTreeNode *arg1, - gint arg2, - gpointer data); - -typedef void (*GtkCTreeSignal2) (GtkObject *object, - GtkCTreeNode *arg1, - GtkCTreeNode *arg2, - GtkCTreeNode *arg3, - gpointer data); - -typedef void (*GtkCTreeSignal3) (GtkObject *object, - GtkCTreeNode *arg1, - gpointer data); - -typedef void (*GtkCTreeSignal4) (GtkObject *object, - GtkCTreeExpansionType arg1, - gpointer data); - - static GtkCListClass *parent_class = NULL; static GtkContainerClass *container_class = NULL; static guint ctree_signals[LAST_SIGNAL] = {0}; @@ -241,7 +324,7 @@ gtk_ctree_get_type (void) if (!ctree_type) { - GtkTypeInfo ctree_info = + static const GtkTypeInfo ctree_info = { "GtkCTree", sizeof (GtkCTree), @@ -262,9 +345,13 @@ gtk_ctree_get_type (void) static void gtk_ctree_class_init (GtkCTreeClass *klass) { + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GtkObjectClass *object_class; GtkWidgetClass *widget_class; GtkCListClass *clist_class; + GtkBindingSet *binding_set; + + gobject_class->constructor = gtk_ctree_constructor; object_class = (GtkObjectClass *) klass; widget_class = (GtkWidgetClass *) klass; @@ -274,199 +361,404 @@ gtk_ctree_class_init (GtkCTreeClass *klass) parent_class = gtk_type_class (GTK_TYPE_CLIST); container_class = gtk_type_class (GTK_TYPE_CONTAINER); + object_class->set_arg = gtk_ctree_set_arg; + object_class->get_arg = gtk_ctree_get_arg; + + widget_class->realize = gtk_ctree_realize; + widget_class->unrealize = gtk_ctree_unrealize; + widget_class->button_press_event = gtk_ctree_button_press; + + widget_class->drag_begin = gtk_ctree_drag_begin; + widget_class->drag_motion = gtk_ctree_drag_motion; + widget_class->drag_data_received = gtk_ctree_drag_data_received; + + clist_class->select_row = real_select_row; + clist_class->unselect_row = real_unselect_row; + clist_class->row_move = real_row_move; + clist_class->undo_selection = real_undo_selection; + clist_class->resync_selection = resync_selection; + clist_class->selection_find = selection_find; + clist_class->click_column = NULL; + clist_class->draw_row = draw_row; + clist_class->draw_drag_highlight = draw_drag_highlight; + clist_class->clear = real_clear; + clist_class->select_all = real_select_all; + clist_class->unselect_all = real_unselect_all; + clist_class->fake_unselect_all = fake_unselect_all; + clist_class->insert_row = real_insert_row; + clist_class->remove_row = real_remove_row; + clist_class->sort_list = real_sort_list; + clist_class->set_cell_contents = set_cell_contents; + clist_class->cell_size_request = cell_size_request; + + klass->tree_select_row = real_tree_select; + klass->tree_unselect_row = real_tree_unselect; + klass->tree_expand = real_tree_expand; + klass->tree_collapse = real_tree_collapse; + klass->tree_move = real_tree_move; + klass->change_focus_row_expansion = change_focus_row_expansion; + + gtk_object_add_arg_type ("GtkCTree::n_columns", /* overrides GtkCList::n_columns!! */ + GTK_TYPE_UINT, + GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY, + ARG_N_COLUMNS); + gtk_object_add_arg_type ("GtkCTree::tree_column", + GTK_TYPE_UINT, + GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY, + ARG_TREE_COLUMN); + gtk_object_add_arg_type ("GtkCTree::indent", + GTK_TYPE_UINT, + GTK_ARG_READWRITE, + ARG_INDENT); + gtk_object_add_arg_type ("GtkCTree::spacing", + GTK_TYPE_UINT, + GTK_ARG_READWRITE, + ARG_SPACING); + gtk_object_add_arg_type ("GtkCTree::show_stub", + GTK_TYPE_BOOL, + GTK_ARG_READWRITE, + ARG_SHOW_STUB); + gtk_object_add_arg_type ("GtkCTree::line_style", + GTK_TYPE_CTREE_LINE_STYLE, + GTK_ARG_READWRITE, + ARG_LINE_STYLE); + gtk_object_add_arg_type ("GtkCTree::expander_style", + GTK_TYPE_CTREE_EXPANDER_STYLE, + GTK_ARG_READWRITE, + ARG_EXPANDER_STYLE); + ctree_signals[TREE_SELECT_ROW] = gtk_signal_new ("tree_select_row", GTK_RUN_FIRST, - object_class->type, + GTK_CLASS_TYPE (object_class), GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_select_row), - gtk_marshal_NONE__POINTER_INT, - GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT); + gtk_marshal_VOID__BOXED_INT, + GTK_TYPE_NONE, 2, + GTK_TYPE_CTREE_NODE | G_SIGNAL_TYPE_STATIC_SCOPE, + GTK_TYPE_INT); ctree_signals[TREE_UNSELECT_ROW] = gtk_signal_new ("tree_unselect_row", GTK_RUN_FIRST, - object_class->type, + GTK_CLASS_TYPE (object_class), GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_unselect_row), - gtk_marshal_NONE__POINTER_INT, - GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT); + gtk_marshal_VOID__BOXED_INT, + GTK_TYPE_NONE, 2, + GTK_TYPE_CTREE_NODE | G_SIGNAL_TYPE_STATIC_SCOPE, + GTK_TYPE_INT); ctree_signals[TREE_EXPAND] = gtk_signal_new ("tree_expand", GTK_RUN_LAST, - object_class->type, + GTK_CLASS_TYPE (object_class), GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_expand), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); + gtk_marshal_VOID__BOXED, + GTK_TYPE_NONE, 1, + GTK_TYPE_CTREE_NODE | G_SIGNAL_TYPE_STATIC_SCOPE); ctree_signals[TREE_COLLAPSE] = gtk_signal_new ("tree_collapse", GTK_RUN_LAST, - object_class->type, + GTK_CLASS_TYPE (object_class), GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_collapse), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); + gtk_marshal_VOID__BOXED, + GTK_TYPE_NONE, 1, + GTK_TYPE_CTREE_NODE | G_SIGNAL_TYPE_STATIC_SCOPE); ctree_signals[TREE_MOVE] = gtk_signal_new ("tree_move", GTK_RUN_LAST, - object_class->type, + GTK_CLASS_TYPE (object_class), GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_move), - gtk_marshal_NONE__POINTER_POINTER_POINTER, - GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_POINTER, - GTK_TYPE_POINTER); + gtk_marshal_VOID__BOXED_BOXED_BOXED, + GTK_TYPE_NONE, 3, + GTK_TYPE_CTREE_NODE | G_SIGNAL_TYPE_STATIC_SCOPE, + GTK_TYPE_CTREE_NODE | G_SIGNAL_TYPE_STATIC_SCOPE, + GTK_TYPE_CTREE_NODE | G_SIGNAL_TYPE_STATIC_SCOPE); ctree_signals[CHANGE_FOCUS_ROW_EXPANSION] = gtk_signal_new ("change_focus_row_expansion", GTK_RUN_LAST | GTK_RUN_ACTION, - object_class->type, + GTK_CLASS_TYPE (object_class), GTK_SIGNAL_OFFSET (GtkCTreeClass, change_focus_row_expansion), - gtk_marshal_NONE__ENUM, - GTK_TYPE_NONE, 1, GTK_TYPE_C_TREE_EXPANSION_TYPE); - - gtk_object_class_add_signals (object_class, ctree_signals, LAST_SIGNAL); + gtk_marshal_VOID__ENUM, + GTK_TYPE_NONE, 1, GTK_TYPE_CTREE_EXPANSION_TYPE); + + binding_set = gtk_binding_set_by_class (klass); + gtk_binding_entry_add_signal (binding_set, + GDK_plus, GDK_SHIFT_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND); + gtk_binding_entry_add_signal (binding_set, + GDK_plus, 0, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND); + gtk_binding_entry_add_signal (binding_set, + GDK_plus, GDK_CONTROL_MASK | GDK_SHIFT_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND_RECURSIVE); + gtk_binding_entry_add_signal (binding_set, + GDK_plus, GDK_CONTROL_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND_RECURSIVE); + + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Add, GDK_SHIFT_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Add, 0, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Add, GDK_CONTROL_MASK | GDK_SHIFT_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND_RECURSIVE); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Add, GDK_CONTROL_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND_RECURSIVE); + + gtk_binding_entry_add_signal (binding_set, + GDK_minus, 0, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE); + gtk_binding_entry_add_signal (binding_set, + GDK_minus, GDK_CONTROL_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, + GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Subtract, 0, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Subtract, GDK_CONTROL_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, + GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE); + gtk_binding_entry_add_signal (binding_set, + GDK_equal, 0, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Equal, 0, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE); + gtk_binding_entry_add_signal (binding_set, + GDK_equal, GDK_SHIFT_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Equal, GDK_SHIFT_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Multiply, 0, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE); + gtk_binding_entry_add_signal (binding_set, + GDK_asterisk, 0, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Multiply, GDK_CONTROL_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, + GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE); + gtk_binding_entry_add_signal (binding_set, + GDK_asterisk, GDK_CONTROL_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, + GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE); +} - object_class->destroy = gtk_ctree_destroy; +static void +gtk_ctree_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id) +{ + GtkCTree *ctree; + GtkCList *clist; - widget_class->realize = gtk_ctree_realize; - widget_class->unrealize = gtk_ctree_unrealize; - widget_class->button_press_event = gtk_ctree_button_press; - widget_class->button_release_event = gtk_ctree_button_release; - widget_class->motion_notify_event = gtk_ctree_button_motion; + ctree = GTK_CTREE (object); + clist = GTK_CLIST (ctree); - clist_class->select_row = real_select_row; - clist_class->unselect_row = real_unselect_row; - clist_class->undo_selection = real_undo_selection; - clist_class->resync_selection = resync_selection; - clist_class->selection_find = selection_find; - clist_class->click_column = NULL; - clist_class->draw_row = draw_row; - clist_class->clear = real_clear; - clist_class->select_all = real_select_all; - clist_class->unselect_all = real_unselect_all; - clist_class->fake_unselect_all = fake_unselect_all; + switch (arg_id) + { + case ARG_N_COLUMNS: /* construct-only arg, only set at construction time */ + g_return_if_fail (clist->row_mem_chunk == NULL); + clist->columns = MAX (1, GTK_VALUE_UINT (*arg)); + clist->row_mem_chunk = g_mem_chunk_new ("ctree row mem chunk", + sizeof (GtkCTreeRow), + sizeof (GtkCTreeRow) + * CLIST_OPTIMUM_SIZE, + G_ALLOC_AND_FREE); + clist->cell_mem_chunk = g_mem_chunk_new ("ctree cell mem chunk", + sizeof (GtkCell) * clist->columns, + sizeof (GtkCell) * clist->columns + * CLIST_OPTIMUM_SIZE, + G_ALLOC_AND_FREE); + ctree->tree_column = CLAMP (ctree->tree_column, 0, clist->columns); + break; + case ARG_TREE_COLUMN: /* construct-only arg, only set at construction time */ + ctree->tree_column = GTK_VALUE_UINT (*arg); + if (clist->row_mem_chunk) + ctree->tree_column = CLAMP (ctree->tree_column, 0, clist->columns); + break; + case ARG_INDENT: + gtk_ctree_set_indent (ctree, GTK_VALUE_UINT (*arg)); + break; + case ARG_SPACING: + gtk_ctree_set_spacing (ctree, GTK_VALUE_UINT (*arg)); + break; + case ARG_SHOW_STUB: + gtk_ctree_set_show_stub (ctree, GTK_VALUE_BOOL (*arg)); + break; + case ARG_LINE_STYLE: + gtk_ctree_set_line_style (ctree, GTK_VALUE_ENUM (*arg)); + break; + case ARG_EXPANDER_STYLE: + gtk_ctree_set_expander_style (ctree, GTK_VALUE_ENUM (*arg)); + break; + default: + break; + } +} - klass->tree_select_row = real_tree_select; - klass->tree_unselect_row = real_tree_unselect; - klass->tree_expand = real_tree_expand; - klass->tree_collapse = real_tree_collapse; - klass->tree_move = real_tree_move; - klass->change_focus_row_expansion = change_focus_row_expansion; +static void +gtk_ctree_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id) +{ + GtkCTree *ctree; - { - GtkBindingSet *binding_set; - - binding_set = gtk_binding_set_by_class (klass); - gtk_binding_entry_add_signal (binding_set, - '+', GDK_SHIFT_MASK, - "change_focus_row_expansion", 1, - GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND); - gtk_binding_entry_add_signal (binding_set, - GDK_KP_Add, 0, - "change_focus_row_expansion", 1, - GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND); - gtk_binding_entry_add_signal (binding_set, - GDK_KP_Add, GDK_CONTROL_MASK, - "change_focus_row_expansion", 1, - GTK_TYPE_ENUM, - GTK_CTREE_EXPANSION_EXPAND_RECURSIVE); - gtk_binding_entry_add_signal (binding_set, - '-', 0, - "change_focus_row_expansion", 1, - GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE); - gtk_binding_entry_add_signal (binding_set, - GDK_KP_Subtract, 0, - "change_focus_row_expansion", 1, - GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE); - gtk_binding_entry_add_signal (binding_set, - GDK_KP_Subtract, GDK_CONTROL_MASK, - "change_focus_row_expansion", 1, - GTK_TYPE_ENUM, - GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE); - gtk_binding_entry_add_signal (binding_set, - '=', 0, - "change_focus_row_expansion", 1, - GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE); - gtk_binding_entry_add_signal (binding_set, - GDK_KP_Multiply, 0, - "change_focus_row_expansion", 1, - GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE); - gtk_binding_entry_add_signal (binding_set, - GDK_KP_Multiply, GDK_CONTROL_MASK, - "change_focus_row_expansion", 1, - GTK_TYPE_ENUM, - GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE); - } + ctree = GTK_CTREE (object); + switch (arg_id) + { + case ARG_N_COLUMNS: + GTK_VALUE_UINT (*arg) = GTK_CLIST (ctree)->columns; + break; + case ARG_TREE_COLUMN: + GTK_VALUE_UINT (*arg) = ctree->tree_column; + break; + case ARG_INDENT: + GTK_VALUE_UINT (*arg) = ctree->tree_indent; + break; + case ARG_SPACING: + GTK_VALUE_UINT (*arg) = ctree->tree_spacing; + break; + case ARG_SHOW_STUB: + GTK_VALUE_BOOL (*arg) = ctree->show_stub; + break; + case ARG_LINE_STYLE: + GTK_VALUE_ENUM (*arg) = ctree->line_style; + break; + case ARG_EXPANDER_STYLE: + GTK_VALUE_ENUM (*arg) = ctree->expander_style; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } } static void gtk_ctree_init (GtkCTree *ctree) { - ctree->xor_gc = NULL; - ctree->drag_icon = NULL; + GtkCList *clist; + + GTK_CLIST_SET_FLAG (ctree, CLIST_DRAW_DRAG_RECT); + GTK_CLIST_SET_FLAG (ctree, CLIST_DRAW_DRAG_LINE); + + clist = GTK_CLIST (ctree); + ctree->tree_indent = 20; + ctree->tree_spacing = 5; ctree->tree_column = 0; - ctree->drag_row = -1; - ctree->drag_source = NULL; - ctree->drag_target = NULL; - ctree->insert_pos = GTK_CTREE_POS_AS_CHILD; - ctree->node_compare = default_compare; - ctree->auto_sort = FALSE; - ctree->reorderable = FALSE; - ctree->use_icons = TRUE; - ctree->in_drag = FALSE; - ctree->drag_rect = FALSE; ctree->line_style = GTK_CTREE_LINES_SOLID; + ctree->expander_style = GTK_CTREE_EXPANDER_SQUARE; + ctree->drag_compare = NULL; + ctree->show_stub = TRUE; + + clist->button_actions[0] |= GTK_BUTTON_EXPANDS; } static void -gtk_ctree_destroy (GtkObject *object) +ctree_attach_styles (GtkCTree *ctree, + GtkCTreeNode *node, + gpointer data) { - gint i; GtkCList *clist; + gint i; - g_return_if_fail (object != NULL); - g_return_if_fail (GTK_IS_CTREE (object)); - - clist = GTK_CLIST (object); - - GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN); + clist = GTK_CLIST (ctree); - gtk_clist_clear (GTK_CLIST (object)); + if (GTK_CTREE_ROW (node)->row.style) + GTK_CTREE_ROW (node)->row.style = + gtk_style_attach (GTK_CTREE_ROW (node)->row.style, clist->clist_window); - if (clist->vscrollbar) - { - gtk_widget_unparent (clist->vscrollbar); - clist->vscrollbar = NULL; - } - if (clist->hscrollbar) + if (GTK_CTREE_ROW (node)->row.fg_set || GTK_CTREE_ROW (node)->row.bg_set) { - gtk_widget_unparent (clist->hscrollbar); - clist->hscrollbar = NULL; + GdkColormap *colormap; + + colormap = gtk_widget_get_colormap (GTK_WIDGET (ctree)); + if (GTK_CTREE_ROW (node)->row.fg_set) + gdk_color_alloc (colormap, &(GTK_CTREE_ROW (node)->row.foreground)); + if (GTK_CTREE_ROW (node)->row.bg_set) + gdk_color_alloc (colormap, &(GTK_CTREE_ROW (node)->row.background)); } for (i = 0; i < clist->columns; i++) - if (clist->column[i].button) - { - gtk_widget_unparent (clist->column[i].button); - clist->column[i].button = NULL; - } + if (GTK_CTREE_ROW (node)->row.cell[i].style) + GTK_CTREE_ROW (node)->row.cell[i].style = + gtk_style_attach (GTK_CTREE_ROW (node)->row.cell[i].style, + clist->clist_window); +} + +static void +ctree_detach_styles (GtkCTree *ctree, + GtkCTreeNode *node, + gpointer data) +{ + GtkCList *clist; + gint i; + + clist = GTK_CLIST (ctree); - if (GTK_OBJECT_CLASS (container_class)->destroy) - (*GTK_OBJECT_CLASS (container_class)->destroy) (object); + if (GTK_CTREE_ROW (node)->row.style) + gtk_style_detach (GTK_CTREE_ROW (node)->row.style); + for (i = 0; i < clist->columns; i++) + if (GTK_CTREE_ROW (node)->row.cell[i].style) + gtk_style_detach (GTK_CTREE_ROW (node)->row.cell[i].style); } static void gtk_ctree_realize (GtkWidget *widget) { GtkCTree *ctree; + GtkCList *clist; GdkGCValues values; + GtkCTreeNode *node; + GtkCTreeNode *child; + gint i; - g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_CTREE (widget)); - (* GTK_WIDGET_CLASS (parent_class)->realize) (widget); + GTK_WIDGET_CLASS (parent_class)->realize (widget); ctree = GTK_CTREE (widget); + clist = GTK_CLIST (widget); + + node = GTK_CTREE_NODE (clist->row_list); + for (i = 0; i < clist->rows; i++) + { + if (GTK_CTREE_ROW (node)->children && !GTK_CTREE_ROW (node)->expanded) + for (child = GTK_CTREE_ROW (node)->children; child; + child = GTK_CTREE_ROW (child)->sibling) + gtk_ctree_pre_recursive (ctree, child, ctree_attach_styles, NULL); + node = GTK_CTREE_NODE_NEXT (node); + } values.foreground = widget->style->fg[GTK_STATE_NORMAL]; - values.background = widget->style->bg[GTK_STATE_NORMAL]; + values.background = widget->style->base[GTK_STATE_NORMAL]; values.subwindow_mode = GDK_INCLUDE_INFERIORS; values.line_style = GDK_LINE_SOLID; ctree->lines_gc = gdk_gc_new_with_values (GTK_CLIST(widget)->clist_window, @@ -479,30 +771,43 @@ gtk_ctree_realize (GtkWidget *widget) if (ctree->line_style == GTK_CTREE_LINES_DOTTED) { gdk_gc_set_line_attributes (ctree->lines_gc, 1, - GDK_LINE_ON_OFF_DASH, None, None); + GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_MITER); gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2); } - - if (ctree->reorderable) - create_xor_gc (ctree); } static void gtk_ctree_unrealize (GtkWidget *widget) { GtkCTree *ctree; + GtkCList *clist; - g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_CTREE (widget)); - (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); + GTK_WIDGET_CLASS (parent_class)->unrealize (widget); ctree = GTK_CTREE (widget); + clist = GTK_CLIST (widget); - gdk_gc_destroy (ctree->lines_gc); + if (GTK_WIDGET_REALIZED (widget)) + { + GtkCTreeNode *node; + GtkCTreeNode *child; + gint i; + + node = GTK_CTREE_NODE (clist->row_list); + for (i = 0; i < clist->rows; i++) + { + if (GTK_CTREE_ROW (node)->children && + !GTK_CTREE_ROW (node)->expanded) + for (child = GTK_CTREE_ROW (node)->children; child; + child = GTK_CTREE_ROW (child)->sibling) + gtk_ctree_pre_recursive(ctree, child, ctree_detach_styles, NULL); + node = GTK_CTREE_NODE_NEXT (node); + } + } - if (ctree->reorderable) - gdk_gc_destroy (ctree->xor_gc); + gdk_gc_destroy (ctree->lines_gc); } static gint @@ -511,17 +816,21 @@ gtk_ctree_button_press (GtkWidget *widget, { GtkCTree *ctree; GtkCList *clist; + gint button_actions; - g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); ctree = GTK_CTREE (widget); clist = GTK_CLIST (widget); + button_actions = clist->button_actions[event->button - 1]; + + if (button_actions == GTK_BUTTON_IGNORED) + return FALSE; + if (event->window == clist->clist_window) { - gboolean collapse_expand = FALSE; GtkCTreeNode *work; gint x; gint y; @@ -534,547 +843,799 @@ gtk_ctree_button_press (GtkWidget *widget, if (!gtk_clist_get_selection_info (clist, x, y, &row, &column)) return FALSE; - if (event->button == 2) - ctree->drag_row = - 1 - ROW_FROM_YPIXEL (clist, y); - work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row)); - if (ctree->reorderable && event->button == 2 && !ctree->in_drag && - clist->anchor == -1) - { - gdk_pointer_grab (event->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON2_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, - NULL, NULL, event->time); - gtk_grab_add (widget); - ctree->in_drag = TRUE; - ctree->drag_source = work; - ctree->drag_target = NULL; - return FALSE; - } - else if (event->button == 1 && - (GTK_CTREE_ROW (work)->children && - (event->type == GDK_2BUTTON_PRESS || - ctree_is_hot_spot (ctree, work, row, x, y)))) + if (button_actions & GTK_BUTTON_EXPANDS && + (GTK_CTREE_ROW (work)->children && !GTK_CTREE_ROW (work)->is_leaf && + (event->type == GDK_2BUTTON_PRESS || + ctree_is_hot_spot (ctree, work, row, x, y)))) { if (GTK_CTREE_ROW (work)->expanded) gtk_ctree_collapse (ctree, work); else gtk_ctree_expand (ctree, work); - collapse_expand = TRUE; + return TRUE; } - if (event->button == 1) - { - gint old_row = clist->focus_row; - gboolean no_focus_row = FALSE; + } + + return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event); +} - switch (clist->selection_mode) - { - case GTK_SELECTION_MULTIPLE: - case GTK_SELECTION_SINGLE: - if (!collapse_expand) - break; +static void +draw_drag_highlight (GtkCList *clist, + GtkCListRow *dest_row, + gint dest_row_number, + GtkCListDragPos drag_pos) +{ + GtkCTree *ctree; + GdkPoint points[4]; + gint level; + gint i; + gint y = 0; - if (clist->focus_row == -1) - { - old_row = row; - no_focus_row = TRUE; - } - - GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION); - gdk_pointer_grab (clist->clist_window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, event->time); - gtk_grab_add (widget); - - if (GTK_CLIST_ADD_MODE (clist)) - { - GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE); - if (GTK_WIDGET_HAS_FOCUS (widget)) - { - gtk_widget_draw_focus (widget); - gdk_gc_set_line_attributes (clist->xor_gc, 1, - GDK_LINE_SOLID, 0, 0); - clist->focus_row = row; - gtk_widget_draw_focus (widget); - } - else - { - gdk_gc_set_line_attributes (clist->xor_gc, 1, - GDK_LINE_SOLID, 0, 0); - clist->focus_row = row; - } - } - else if (row != clist->focus_row) - { - if (GTK_WIDGET_HAS_FOCUS (widget)) - { - gtk_widget_draw_focus (widget); - clist->focus_row = row; - gtk_widget_draw_focus (widget); - } - else - clist->focus_row = row; - } + g_return_if_fail (GTK_IS_CTREE (clist)); - if (!GTK_WIDGET_HAS_FOCUS (widget)) - gtk_widget_grab_focus (widget); + ctree = GTK_CTREE (clist); - return FALSE; + level = ((GtkCTreeRow *)(dest_row))->level; - default: - break; - } - } + y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1; + + switch (drag_pos) + { + case GTK_CLIST_DRAG_NONE: + break; + case GTK_CLIST_DRAG_AFTER: + y += clist->row_height + 1; + case GTK_CLIST_DRAG_BEFORE: + + if (clist->column[ctree->tree_column].visible) + switch (clist->column[ctree->tree_column].justification) + { + case GTK_JUSTIFY_CENTER: + case GTK_JUSTIFY_FILL: + case GTK_JUSTIFY_LEFT: + if (ctree->tree_column > 0) + gdk_draw_line (clist->clist_window, clist->xor_gc, + COLUMN_LEFT_XPIXEL(clist, 0), y, + COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1)+ + clist->column[ctree->tree_column - 1].area.width, + y); + + gdk_draw_line (clist->clist_window, clist->xor_gc, + COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + + ctree->tree_indent * level - + (ctree->tree_indent - PM_SIZE) / 2, y, + GTK_WIDGET (ctree)->allocation.width, y); + break; + case GTK_JUSTIFY_RIGHT: + if (ctree->tree_column < clist->columns - 1) + gdk_draw_line (clist->clist_window, clist->xor_gc, + COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1), + y, + COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) + + clist->column[clist->columns - 1].area.width, y); + + gdk_draw_line (clist->clist_window, clist->xor_gc, + 0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + + clist->column[ctree->tree_column].area.width - + ctree->tree_indent * level + + (ctree->tree_indent - PM_SIZE) / 2, y); + break; + } + else + gdk_draw_line (clist->clist_window, clist->xor_gc, + 0, y, clist->clist_window_width, y); + break; + case GTK_CLIST_DRAG_INTO: + y = ROW_TOP_YPIXEL (clist, dest_row_number) + clist->row_height; + + if (clist->column[ctree->tree_column].visible) + switch (clist->column[ctree->tree_column].justification) + { + case GTK_JUSTIFY_CENTER: + case GTK_JUSTIFY_FILL: + case GTK_JUSTIFY_LEFT: + points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + + ctree->tree_indent * level - (ctree->tree_indent - PM_SIZE) / 2; + points[0].y = y; + points[3].x = points[0].x; + points[3].y = y - clist->row_height - 1; + points[1].x = clist->clist_window_width - 1; + points[1].y = points[0].y; + points[2].x = points[1].x; + points[2].y = points[3].y; + + for (i = 0; i < 3; i++) + gdk_draw_line (clist->clist_window, clist->xor_gc, + points[i].x, points[i].y, + points[i+1].x, points[i+1].y); + + if (ctree->tree_column > 0) + { + points[0].x = COLUMN_LEFT_XPIXEL(clist, + ctree->tree_column - 1) + + clist->column[ctree->tree_column - 1].area.width ; + points[0].y = y; + points[3].x = points[0].x; + points[3].y = y - clist->row_height - 1; + points[1].x = 0; + points[1].y = points[0].y; + points[2].x = 0; + points[2].y = points[3].y; + + for (i = 0; i < 3; i++) + gdk_draw_line (clist->clist_window, clist->xor_gc, + points[i].x, points[i].y, points[i+1].x, + points[i+1].y); + } + break; + case GTK_JUSTIFY_RIGHT: + points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) - + ctree->tree_indent * level + (ctree->tree_indent - PM_SIZE) / 2 + + clist->column[ctree->tree_column].area.width; + points[0].y = y; + points[3].x = points[0].x; + points[3].y = y - clist->row_height - 1; + points[1].x = 0; + points[1].y = points[0].y; + points[2].x = 0; + points[2].y = points[3].y; + + for (i = 0; i < 3; i++) + gdk_draw_line (clist->clist_window, clist->xor_gc, + points[i].x, points[i].y, + points[i+1].x, points[i+1].y); + + if (ctree->tree_column < clist->columns - 1) + { + points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column +1); + points[0].y = y; + points[3].x = points[0].x; + points[3].y = y - clist->row_height - 1; + points[1].x = clist->clist_window_width - 1; + points[1].y = points[0].y; + points[2].x = points[1].x; + points[2].y = points[3].y; + + for (i = 0; i < 3; i++) + gdk_draw_line (clist->clist_window, clist->xor_gc, + points[i].x, points[i].y, + points[i+1].x, points[i+1].y); + } + break; + } + else + gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, + 0, y - clist->row_height, + clist->clist_window_width - 1, clist->row_height); + break; } - return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event); } static gint -gtk_ctree_button_motion (GtkWidget *widget, - GdkEventMotion *event) +draw_cell_pixmap (GdkWindow *window, + GdkRectangle *clip_rectangle, + GdkGC *fg_gc, + GdkPixmap *pixmap, + GdkBitmap *mask, + gint x, + gint y, + gint width, + gint height) { - GtkCTree *ctree; - GtkCList *clist; - gint x; - gint y; - gint row; - gint insert_pos = GTK_CTREE_POS_AS_CHILD; + gint xsrc = 0; + gint ysrc = 0; - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); + if (mask) + { + gdk_gc_set_clip_mask (fg_gc, mask); + gdk_gc_set_clip_origin (fg_gc, x, y); + } + if (x < clip_rectangle->x) + { + xsrc = clip_rectangle->x - x; + width -= xsrc; + x = clip_rectangle->x; + } + if (x + width > clip_rectangle->x + clip_rectangle->width) + width = clip_rectangle->x + clip_rectangle->width - x; - ctree = GTK_CTREE (widget); - clist = GTK_CLIST (widget); + if (y < clip_rectangle->y) + { + ysrc = clip_rectangle->y - y; + height -= ysrc; + y = clip_rectangle->y; + } + if (y + height > clip_rectangle->y + clip_rectangle->height) + height = clip_rectangle->y + clip_rectangle->height - y; - if (GTK_CLIST_IN_DRAG (clist)) - return GTK_WIDGET_CLASS (parent_class)->motion_notify_event - (widget, event); + if (width > 0 && height > 0) + gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height); - if (event->window == clist->clist_window && - ctree->in_drag && ctree->reorderable) + if (mask) { - GdkModifierType modmask; - gint root_x; - gint root_y; + gdk_gc_set_clip_rectangle (fg_gc, NULL); + gdk_gc_set_clip_origin (fg_gc, 0, 0); + } - x = event->x; - y = event->y; - if (event->is_hint) - gdk_window_get_pointer (event->window, &x, &y, NULL); + return x + MAX (width, 0); +} + +static void +get_cell_style (GtkCList *clist, + GtkCListRow *clist_row, + gint state, + gint column, + GtkStyle **style, + GdkGC **fg_gc, + GdkGC **bg_gc) +{ + gint fg_state; + + if ((state == GTK_STATE_NORMAL) && + (GTK_WIDGET (clist)->state == GTK_STATE_INSENSITIVE)) + fg_state = GTK_STATE_INSENSITIVE; + else + fg_state = state; - /* delayed drag start */ - if (!ctree->drag_target && - y >= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) && - y <= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) + clist->row_height) - return - GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event); + if (clist_row->cell[column].style) + { + if (style) + *style = clist_row->cell[column].style; + if (fg_gc) + *fg_gc = clist_row->cell[column].style->fg_gc[fg_state]; + if (bg_gc) { + if (state == GTK_STATE_SELECTED) + *bg_gc = clist_row->cell[column].style->bg_gc[state]; + else + *bg_gc = clist_row->cell[column].style->base_gc[state]; + } + } + else if (clist_row->style) + { + if (style) + *style = clist_row->style; + if (fg_gc) + *fg_gc = clist_row->style->fg_gc[fg_state]; + if (bg_gc) { + if (state == GTK_STATE_SELECTED) + *bg_gc = clist_row->style->bg_gc[state]; + else + *bg_gc = clist_row->style->base_gc[state]; + } + } + else + { + if (style) + *style = GTK_WIDGET (clist)->style; + if (fg_gc) + *fg_gc = GTK_WIDGET (clist)->style->fg_gc[fg_state]; + if (bg_gc) { + if (state == GTK_STATE_SELECTED) + *bg_gc = GTK_WIDGET (clist)->style->bg_gc[state]; + else + *bg_gc = GTK_WIDGET (clist)->style->base_gc[state]; + } - if (ctree->use_icons) + if (state != GTK_STATE_SELECTED) { - if (!ctree->drag_icon) - create_drag_icon (ctree, GTK_CTREE_ROW (ctree->drag_source)); - else - { - gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask); - gdk_window_move (ctree->drag_icon, root_x - ctree->icon_width /2, - root_y - ctree->icon_height); - } + if (fg_gc && clist_row->fg_set) + *fg_gc = clist->fg_gc; + if (bg_gc && clist_row->bg_set) + *bg_gc = clist->bg_gc; } + } +} - /* out of bounds check */ - if (x < 0 || y < -3 || x > clist->clist_window_width || - y > clist->clist_window_height + 3 || - y > ROW_TOP_YPIXEL (clist, clist->rows-1) + clist->row_height + 3) - { - if (ctree->drag_row >= 0) - { - if (ctree->drag_rect) - { - draw_xor_rect (ctree); - ctree->drag_rect = FALSE; - } - else - draw_xor_line (ctree); - ctree->drag_row = -1; - } - return - (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) - (widget, event); +static gint +gtk_ctree_draw_expander (GtkCTree *ctree, + GtkCTreeRow *ctree_row, + GtkStyle *style, + GdkRectangle *clip_rectangle, + gint x) +{ + GtkCList *clist; + GdkPoint points[3]; + gint justification_factor; + gint y; + + if (ctree->expander_style == GTK_CTREE_EXPANDER_NONE) + return x; + + clist = GTK_CLIST (ctree); + if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT) + justification_factor = -1; + else + justification_factor = 1; + y = (clip_rectangle->y + (clip_rectangle->height - PM_SIZE) / 2 - + (clip_rectangle->height + 1) % 2); + + if (!ctree_row->children) + { + switch (ctree->expander_style) + { + case GTK_CTREE_EXPANDER_NONE: + return x; + case GTK_CTREE_EXPANDER_TRIANGLE: + return x + justification_factor * (PM_SIZE + 3); + case GTK_CTREE_EXPANDER_SQUARE: + case GTK_CTREE_EXPANDER_CIRCULAR: + return x + justification_factor * (PM_SIZE + 1); } + } - row = ROW_FROM_YPIXEL (clist, y); + gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], clip_rectangle); + gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], clip_rectangle); - /* re-calculate target (mouse left the window) */ - if (ctree->drag_target && ctree->drag_row == -1) - ctree->drag_target = GTK_CTREE_NODE (g_list_nth (clist->row_list,row)); - - if (y < 0 || y > clist->clist_window_height || - ROW_TOP_YPIXEL (clist, row + 1) > clist->clist_window_height - || row >= clist->rows) - return GTK_WIDGET_CLASS (parent_class)->motion_notify_event - (widget, event); - - if (y - ROW_TOP_YPIXEL (clist, row) < clist->row_height / 4) - insert_pos = GTK_CTREE_POS_BEFORE; - else if (ROW_TOP_YPIXEL (clist, row) + clist->row_height - y - < clist->row_height / 4) - insert_pos = GTK_CTREE_POS_AFTER; - - if (row != ctree->drag_row || - (row == ctree->drag_row && ctree->insert_pos != insert_pos)) + switch (ctree->expander_style) + { + case GTK_CTREE_EXPANDER_NONE: + break; + case GTK_CTREE_EXPANDER_TRIANGLE: + if (ctree_row->expanded) { - if (insert_pos != GTK_CTREE_POS_AS_CHILD) - { - if (ctree->drag_row >= 0) - { - if (ctree->drag_rect) - { - draw_xor_rect (ctree); - ctree->drag_rect = FALSE; - } - else - draw_xor_line (ctree); - } - ctree->insert_pos = insert_pos; - ctree->drag_target = - GTK_CTREE_NODE (g_list_nth (clist->row_list, row)); - ctree->drag_row = row; - draw_xor_line (ctree); - } - else if (ctree->drag_target && - !GTK_CTREE_ROW (ctree->drag_target)->is_leaf) - { - if (ctree->drag_row >= 0) - { - if (ctree->drag_rect) - draw_xor_rect (ctree); - else - draw_xor_line (ctree); - } - ctree->drag_rect = TRUE; - ctree->insert_pos = insert_pos; - ctree->drag_target = - GTK_CTREE_NODE (g_list_nth (clist->row_list, row)); - ctree->drag_row = row; - draw_xor_rect (ctree); - } + points[0].x = x; + points[0].y = y + (PM_SIZE + 2) / 6; + points[1].x = points[0].x + justification_factor * (PM_SIZE + 2); + points[1].y = points[0].y; + points[2].x = (points[0].x + + justification_factor * (PM_SIZE + 2) / 2); + points[2].y = y + 2 * (PM_SIZE + 2) / 3; } + else + { + points[0].x = x + justification_factor * ((PM_SIZE + 2) / 6 + 2); + points[0].y = y - 1; + points[1].x = points[0].x; + points[1].y = points[0].y + (PM_SIZE + 2); + points[2].x = (points[0].x + + justification_factor * (2 * (PM_SIZE + 2) / 3 - 1)); + points[2].y = points[0].y + (PM_SIZE + 2) / 2; + } + + gdk_draw_polygon (clist->clist_window, style->base_gc[GTK_STATE_NORMAL], + TRUE, points, 3); + gdk_draw_polygon (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL], + FALSE, points, 3); + + x += justification_factor * (PM_SIZE + 3); + break; + case GTK_CTREE_EXPANDER_SQUARE: + case GTK_CTREE_EXPANDER_CIRCULAR: + if (justification_factor == -1) + x += justification_factor * (PM_SIZE + 1); + + if (ctree->expander_style == GTK_CTREE_EXPANDER_CIRCULAR) + { + gdk_draw_arc (clist->clist_window, style->base_gc[GTK_STATE_NORMAL], + TRUE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64); + gdk_draw_arc (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL], + FALSE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64); + } + else + { + gdk_draw_rectangle (clist->clist_window, + style->base_gc[GTK_STATE_NORMAL], TRUE, + x, y, PM_SIZE, PM_SIZE); + gdk_draw_rectangle (clist->clist_window, + style->fg_gc[GTK_STATE_NORMAL], FALSE, + x, y, PM_SIZE, PM_SIZE); + } + + gdk_draw_line (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL], + x + 2, y + PM_SIZE / 2, x + PM_SIZE - 2, y + PM_SIZE / 2); + + if (!ctree_row->expanded) + gdk_draw_line (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL], + x + PM_SIZE / 2, y + 2, + x + PM_SIZE / 2, y + PM_SIZE - 2); + + if (justification_factor == 1) + x += justification_factor * (PM_SIZE + 1); + break; } - return GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event); + + gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], NULL); + gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], NULL); + + return x; } + static gint -gtk_ctree_button_release (GtkWidget *widget, - GdkEventButton *event) +gtk_ctree_draw_lines (GtkCTree *ctree, + GtkCTreeRow *ctree_row, + gint row, + gint column, + gint state, + GdkRectangle *clip_rectangle, + GdkRectangle *cell_rectangle, + GdkRectangle *crect, + GdkRectangle *area, + GtkStyle *style) { - GtkCTree *ctree; GtkCList *clist; + GtkCTreeNode *node; + GtkCTreeNode *parent; + GdkRectangle tree_rectangle; + GdkRectangle tc_rectangle; + GdkGC *bg_gc; + gint offset; + gint offset_x; + gint offset_y; + gint xcenter; + gint ycenter; + gint next_level; + gint column_right; + gint column_left; + gint justify_right; + gint justification_factor; + + clist = GTK_CLIST (ctree); + ycenter = clip_rectangle->y + (clip_rectangle->height / 2); + justify_right = (clist->column[column].justification == GTK_JUSTIFY_RIGHT); - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - ctree = GTK_CTREE (widget); - clist = GTK_CLIST (widget); + if (justify_right) + { + offset = (clip_rectangle->x + clip_rectangle->width - 1 - + ctree->tree_indent * (ctree_row->level - 1)); + justification_factor = -1; + } + else + { + offset = clip_rectangle->x + ctree->tree_indent * (ctree_row->level - 1); + justification_factor = 1; + } - if (event->button == 2 && clist->anchor == -1) + switch (ctree->line_style) { - gtk_grab_remove (widget); - gdk_pointer_ungrab (event->time); + case GTK_CTREE_LINES_NONE: + break; + case GTK_CTREE_LINES_TABBED: + xcenter = offset + justification_factor * TAB_SIZE; - ctree->in_drag = FALSE; + column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) + + clist->column[ctree->tree_column].area.width + + COLUMN_INSET); + column_left = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) - + COLUMN_INSET - CELL_SPACING); - if (ctree->use_icons && ctree->drag_icon) + if (area) { - gdk_window_destroy (ctree->drag_icon); - ctree->drag_icon = NULL; - } + tree_rectangle.y = crect->y; + tree_rectangle.height = crect->height; - if (ctree->drag_row >= 0) - { - if (ctree->drag_rect) + if (justify_right) { - draw_xor_rect (ctree); - ctree->drag_rect = FALSE; + tree_rectangle.x = xcenter; + tree_rectangle.width = column_right - xcenter; } else - draw_xor_line (ctree); - ctree->drag_row = -1; - } - - /* nop if out of bounds / source == target */ - if (event->x < 0 || event->y < -3 || - event->x > clist->clist_window_width || - event->y > clist->clist_window_height + 3 || - ctree->drag_target == ctree->drag_source || - !ctree->drag_target) - return GTK_WIDGET_CLASS (parent_class)->button_release_event - (widget, event); - - if (!GTK_CTREE_ROW (ctree->drag_source)->children || - !gtk_ctree_is_ancestor (ctree, ctree->drag_source, - ctree->drag_target)) - { - if (ctree->insert_pos == GTK_CTREE_POS_AFTER) - { - if (GTK_CTREE_ROW (ctree->drag_target)->sibling != - ctree->drag_source) - gtk_signal_emit (GTK_OBJECT (ctree), - ctree_signals[TREE_MOVE], - ctree->drag_source, - GTK_CTREE_ROW (ctree->drag_target)->parent, - GTK_CTREE_ROW (ctree->drag_target)->sibling); - } - else if (ctree->insert_pos == GTK_CTREE_POS_BEFORE) { - if (GTK_CTREE_ROW (ctree->drag_source)->sibling != - ctree->drag_target) - gtk_signal_emit (GTK_OBJECT (ctree), - ctree_signals[TREE_MOVE], - ctree->drag_source, - GTK_CTREE_ROW (ctree->drag_target)->parent, - ctree->drag_target); + tree_rectangle.x = column_left; + tree_rectangle.width = xcenter - column_left; } - else if (!GTK_CTREE_ROW (ctree->drag_target)->is_leaf) + + if (!gdk_rectangle_intersect (area, &tree_rectangle, &tc_rectangle)) { - if (GTK_CTREE_ROW (ctree->drag_target)->children != - ctree->drag_source) - gtk_signal_emit (GTK_OBJECT (ctree), - ctree_signals[TREE_MOVE], - ctree->drag_source, - ctree->drag_target, - GTK_CTREE_ROW (ctree->drag_target)->children); + offset += justification_factor * 3; + break; } } - ctree->drag_source = NULL; - ctree->drag_target = NULL; - } - else if (event->button == 1 && GTK_CLIST_DRAG_SELECTION (clist) && - (clist->selection_mode == GTK_SELECTION_SINGLE || - clist->selection_mode == GTK_SELECTION_MULTIPLE)) - { - gint row; - gint column; - GtkCTreeNode *work; - if (gtk_clist_get_selection_info - (clist, event->x, event->y, &row, &column)) + gdk_gc_set_clip_rectangle (ctree->lines_gc, crect); + + next_level = ctree_row->level; + + if (!ctree_row->sibling || (ctree_row->children && ctree_row->expanded)) { - if (clist->anchor == clist->focus_row && - (work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row)))) - tree_toggle_selection (ctree, work, column); + node = gtk_ctree_find_node_ptr (ctree, ctree_row); + if (GTK_CTREE_NODE_NEXT (node)) + next_level = GTK_CTREE_ROW (GTK_CTREE_NODE_NEXT (node))->level; + else + next_level = 0; } - clist->anchor = -1; - } - return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event); -} -static void -create_drag_icon (GtkCTree *ctree, - GtkCTreeRow *row) -{ - GtkCList *clist; - GtkWidget *widget; - GdkWindow *window = NULL; - GdkWindowAttr attributes; - gint attributes_mask; - GdkPixmap *pixmap; - GdkBitmap *mask; - GdkModifierType modmask; - gint root_x; - gint root_y; - - clist = GTK_CLIST (ctree); - widget = GTK_WIDGET (ctree); - - if (!(pixmap = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->pixmap)) - return; - mask = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->mask; + if (ctree->tree_indent > 0) + { + node = ctree_row->parent; + while (node) + { + xcenter -= (justification_factor * ctree->tree_indent); - gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask); - gdk_window_get_size (pixmap, &ctree->icon_width, &ctree->icon_height); + if ((justify_right && xcenter < column_left) || + (!justify_right && xcenter > column_right)) + { + node = GTK_CTREE_ROW (node)->parent; + continue; + } - attributes.window_type = GDK_WINDOW_TEMP; - attributes.x = root_x - ctree->icon_width / 2; - attributes.y = root_y - ctree->icon_height; - attributes.width = ctree->icon_width; - attributes.height = ctree->icon_height; - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = gtk_widget_get_events (widget); + tree_rectangle.y = cell_rectangle->y; + tree_rectangle.height = cell_rectangle->height; + if (justify_right) + { + tree_rectangle.x = MAX (xcenter - ctree->tree_indent + 1, + column_left); + tree_rectangle.width = MIN (xcenter - column_left, + ctree->tree_indent); + } + else + { + tree_rectangle.x = xcenter; + tree_rectangle.width = MIN (column_right - xcenter, + ctree->tree_indent); + } - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + if (!area || gdk_rectangle_intersect (area, &tree_rectangle, + &tc_rectangle)) + { + get_cell_style (clist, >K_CTREE_ROW (node)->row, + state, column, NULL, NULL, &bg_gc); + + if (bg_gc == clist->bg_gc) + gdk_gc_set_foreground + (clist->bg_gc, >K_CTREE_ROW (node)->row.background); + + if (!area) + gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE, + tree_rectangle.x, + tree_rectangle.y, + tree_rectangle.width, + tree_rectangle.height); + else + gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE, + tc_rectangle.x, + tc_rectangle.y, + tc_rectangle.width, + tc_rectangle.height); + } + if (next_level > GTK_CTREE_ROW (node)->level) + gdk_draw_line (clist->clist_window, ctree->lines_gc, + xcenter, crect->y, + xcenter, crect->y + crect->height); + else + { + gint width; - window = gdk_window_new (widget->window, &attributes, attributes_mask); - gdk_window_set_back_pixmap (window, pixmap, FALSE); - if (mask) - gdk_window_shape_combine_mask (window, mask, 0, 0); - gdk_window_show (window); + offset_x = MIN (ctree->tree_indent, 2 * TAB_SIZE); + width = offset_x / 2 + offset_x % 2; - ctree->drag_icon = window; -} + parent = GTK_CTREE_ROW (node)->parent; -static void -create_xor_gc (GtkCTree *ctree) -{ - GtkCList *clist; - GdkGCValues values; + tree_rectangle.y = ycenter; + tree_rectangle.height = (cell_rectangle->y - ycenter + + cell_rectangle->height); - clist = GTK_CLIST (ctree); + if (justify_right) + { + tree_rectangle.x = MAX(xcenter + 1 - width, column_left); + tree_rectangle.width = MIN (xcenter + 1 - column_left, + width); + } + else + { + tree_rectangle.x = xcenter; + tree_rectangle.width = MIN (column_right - xcenter, + width); + } - values.foreground = GTK_WIDGET (clist)->style->bg[GTK_STATE_NORMAL]; - values.function = GDK_XOR; - values.subwindow_mode = GDK_INCLUDE_INFERIORS; - ctree->xor_gc = gdk_gc_new_with_values (clist->clist_window, &values, - GDK_GC_FOREGROUND | - GDK_GC_FUNCTION | - GDK_GC_SUBWINDOW); - gdk_gc_set_line_attributes (ctree->xor_gc, 1, GDK_LINE_ON_OFF_DASH, - None, None); - gdk_gc_set_dashes (ctree->xor_gc, 0, "\2\2", 2); -} + if (!area || + gdk_rectangle_intersect (area, &tree_rectangle, + &tc_rectangle)) + { + if (parent) + { + get_cell_style (clist, >K_CTREE_ROW (parent)->row, + state, column, NULL, NULL, &bg_gc); + if (bg_gc == clist->bg_gc) + gdk_gc_set_foreground + (clist->bg_gc, + >K_CTREE_ROW (parent)->row.background); + } + else if (state == GTK_STATE_SELECTED) + bg_gc = style->base_gc[state]; + else + bg_gc = GTK_WIDGET (clist)->style->base_gc[state]; + + if (!area) + gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE, + tree_rectangle.x, + tree_rectangle.y, + tree_rectangle.width, + tree_rectangle.height); + else + gdk_draw_rectangle (clist->clist_window, + bg_gc, TRUE, + tc_rectangle.x, + tc_rectangle.y, + tc_rectangle.width, + tc_rectangle.height); + } -static void -draw_xor_line (GtkCTree *ctree) -{ - GtkCList *clist; - gint level; - gint y = 0; + get_cell_style (clist, >K_CTREE_ROW (node)->row, + state, column, NULL, NULL, &bg_gc); + if (bg_gc == clist->bg_gc) + gdk_gc_set_foreground + (clist->bg_gc, >K_CTREE_ROW (node)->row.background); - clist = GTK_CLIST (ctree); + gdk_gc_set_clip_rectangle (bg_gc, crect); + gdk_draw_arc (clist->clist_window, bg_gc, TRUE, + xcenter - (justify_right * offset_x), + cell_rectangle->y, + offset_x, clist->row_height, + (180 + (justify_right * 90)) * 64, 90 * 64); + gdk_gc_set_clip_rectangle (bg_gc, NULL); - level = GTK_CTREE_ROW (ctree->drag_target)->level; + gdk_draw_line (clist->clist_window, ctree->lines_gc, + xcenter, cell_rectangle->y, xcenter, ycenter); - if (ctree->insert_pos == GTK_CTREE_POS_AFTER) - y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height; - else - y = ROW_TOP_YPIXEL (clist, ctree->drag_row) - 1; - - switch (clist->column[ctree->tree_column].justification) - { - case GTK_JUSTIFY_CENTER: - case GTK_JUSTIFY_FILL: - case GTK_JUSTIFY_LEFT: - if (ctree->tree_column > 0) - gdk_draw_line (clist->clist_window, ctree->xor_gc, - COLUMN_LEFT_XPIXEL(clist, 0), y, - COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) + - clist->column[ctree->tree_column - 1].area.width, y); - - gdk_draw_line (clist->clist_window, ctree->xor_gc, - COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + - ctree->tree_indent * level - - (ctree->tree_indent - PM_SIZE) / 2, y, - GTK_WIDGET (ctree)->allocation.width, y); - break; - case GTK_JUSTIFY_RIGHT: - if (ctree->tree_column < clist->columns - 1) - gdk_draw_line (clist->clist_window, ctree->xor_gc, - COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1), y, - COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) + - clist->column[clist->columns - 1].area.width, y); - - gdk_draw_line (clist->clist_window, ctree->xor_gc, - 0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) - + clist->column[ctree->tree_column].area.width - - ctree->tree_indent * level + - (ctree->tree_indent - PM_SIZE) / 2, y); - break; - } -} + if (justify_right) + gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE, + xcenter - offset_x, cell_rectangle->y, + offset_x, clist->row_height, + 270 * 64, 90 * 64); + else + gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE, + xcenter, cell_rectangle->y, + offset_x, clist->row_height, + 180 * 64, 90 * 64); + } + node = GTK_CTREE_ROW (node)->parent; + } + } -static void -draw_xor_rect (GtkCTree *ctree) -{ - GtkCList *clist; - GdkPoint points[4]; - guint level; - gint i; - gint y; + if (state != GTK_STATE_SELECTED) + { + tree_rectangle.y = clip_rectangle->y; + tree_rectangle.height = clip_rectangle->height; + tree_rectangle.width = COLUMN_INSET + CELL_SPACING + + MIN (clist->column[ctree->tree_column].area.width + COLUMN_INSET, + TAB_SIZE); + + if (justify_right) + tree_rectangle.x = MAX (xcenter + 1, column_left); + else + tree_rectangle.x = column_left; - clist = GTK_CLIST (ctree); + if (!area) + gdk_draw_rectangle (clist->clist_window, + GTK_WIDGET + (ctree)->style->base_gc[GTK_STATE_NORMAL], + TRUE, + tree_rectangle.x, + tree_rectangle.y, + tree_rectangle.width, + tree_rectangle.height); + else if (gdk_rectangle_intersect (area, &tree_rectangle, + &tc_rectangle)) + gdk_draw_rectangle (clist->clist_window, + GTK_WIDGET + (ctree)->style->base_gc[GTK_STATE_NORMAL], + TRUE, + tc_rectangle.x, + tc_rectangle.y, + tc_rectangle.width, + tc_rectangle.height); + } - level = GTK_CTREE_ROW (ctree->drag_target)->level; + xcenter = offset + (justification_factor * ctree->tree_indent / 2); - y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height; + get_cell_style (clist, &ctree_row->row, state, column, NULL, NULL, + &bg_gc); + if (bg_gc == clist->bg_gc) + gdk_gc_set_foreground (clist->bg_gc, &ctree_row->row.background); - switch (clist->column[ctree->tree_column].justification) - { - case GTK_JUSTIFY_CENTER: - case GTK_JUSTIFY_FILL: - case GTK_JUSTIFY_LEFT: - points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + - ctree->tree_indent * level - (ctree->tree_indent - PM_SIZE) / 2; - points[0].y = y; - points[3].x = points[0].x; - points[3].y = y - clist->row_height - 1; - points[1].x = clist->clist_window_width - 1; - points[1].y = points[0].y; - points[2].x = points[1].x; - points[2].y = points[3].y; + gdk_gc_set_clip_rectangle (bg_gc, crect); + if (ctree_row->is_leaf) + { + GdkPoint points[6]; - for (i = 0; i < 3; i++) - gdk_draw_line (clist->clist_window, ctree->xor_gc, - points[i].x, points[i].y, points[i+1].x, points[i+1].y); + points[0].x = offset + justification_factor * TAB_SIZE; + points[0].y = cell_rectangle->y; - if (ctree->tree_column > 0) - { - points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) + - clist->column[ctree->tree_column - 1].area.width ; - points[0].y = y; - points[3].x = points[0].x; - points[3].y = y - clist->row_height - 1; - points[1].x = 0; + points[1].x = points[0].x - justification_factor * 4; points[1].y = points[0].y; - points[2].x = 0; - points[2].y = points[3].y; - for (i = 0; i < 3; i++) - gdk_draw_line (clist->clist_window, ctree->xor_gc, - points[i].x, points[i].y, points[i+1].x, - points[i+1].y); + points[2].x = points[1].x - justification_factor * 2; + points[2].y = points[1].y + 3; + + points[3].x = points[2].x; + points[3].y = points[2].y + clist->row_height - 5; + + points[4].x = points[3].x + justification_factor * 2; + points[4].y = points[3].y + 3; + + points[5].x = points[4].x + justification_factor * 4; + points[5].y = points[4].y; + + gdk_draw_polygon (clist->clist_window, bg_gc, TRUE, points, 6); + gdk_draw_lines (clist->clist_window, ctree->lines_gc, points, 6); } + else + { + gdk_draw_arc (clist->clist_window, bg_gc, TRUE, + offset - (justify_right * 2 * TAB_SIZE), + cell_rectangle->y, + 2 * TAB_SIZE, clist->row_height, + (90 + (180 * justify_right)) * 64, 180 * 64); + gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE, + offset - (justify_right * 2 * TAB_SIZE), + cell_rectangle->y, + 2 * TAB_SIZE, clist->row_height, + (90 + (180 * justify_right)) * 64, 180 * 64); + } + gdk_gc_set_clip_rectangle (bg_gc, NULL); + gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL); + + offset += justification_factor * 3; break; - case GTK_JUSTIFY_RIGHT: - points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) - - ctree->tree_indent * level + (ctree->tree_indent - PM_SIZE) / 2 + - clist->column[ctree->tree_column].area.width; - points[0].y = y; - points[3].x = points[0].x; - points[3].y = y - clist->row_height - 1; - points[1].x = 0; - points[1].y = points[0].y; - points[2].x = 0; - points[2].y = points[3].y; - - for (i = 0; i < 3; i++) - gdk_draw_line (clist->clist_window, ctree->xor_gc, - points[i].x, points[i].y, points[i+1].x, points[i+1].y); - - if (ctree->tree_column < clist->columns - 1) + default: + xcenter = offset + justification_factor * PM_SIZE / 2; + + if (area) { - points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1); - points[0].y = y; - points[3].x = points[0].x; - points[3].y = y - clist->row_height - 1; - points[1].x = clist->clist_window_width - 1; - points[1].y = points[0].y; - points[2].x = points[1].x; - points[2].y = points[3].y; + tree_rectangle.y = crect->y; + tree_rectangle.height = crect->height; + + if (justify_right) + { + tree_rectangle.x = xcenter - PM_SIZE / 2 - 2; + tree_rectangle.width = (clip_rectangle->x + + clip_rectangle->width -tree_rectangle.x); + } + else + { + tree_rectangle.x = clip_rectangle->x + PM_SIZE / 2; + tree_rectangle.width = (xcenter + PM_SIZE / 2 + 2 - + clip_rectangle->x); + } + + if (!gdk_rectangle_intersect (area, &tree_rectangle, &tc_rectangle)) + break; + } + + offset_x = 1; + offset_y = 0; + if (ctree->line_style == GTK_CTREE_LINES_DOTTED) + { + offset_x += abs((clip_rectangle->x + clist->hoffset) % 2); + offset_y = abs((cell_rectangle->y + clist->voffset) % 2); + } + + clip_rectangle->y--; + clip_rectangle->height++; + gdk_gc_set_clip_rectangle (ctree->lines_gc, clip_rectangle); + gdk_draw_line (clist->clist_window, ctree->lines_gc, + xcenter, + (ctree->show_stub || clist->row_list->data != ctree_row) ? + cell_rectangle->y + offset_y : ycenter, + xcenter, + (ctree_row->sibling) ? crect->y +crect->height : ycenter); + + gdk_draw_line (clist->clist_window, ctree->lines_gc, + xcenter + (justification_factor * offset_x), ycenter, + xcenter + (justification_factor * (PM_SIZE / 2 + 2)), + ycenter); + + node = ctree_row->parent; + while (node) + { + xcenter -= (justification_factor * ctree->tree_indent); - for (i = 0; i < 3; i++) - gdk_draw_line (clist->clist_window, ctree->xor_gc, - points[i].x, points[i].y, points[i+1].x, - points[i+1].y); + if (GTK_CTREE_ROW (node)->sibling) + gdk_draw_line (clist->clist_window, ctree->lines_gc, + xcenter, cell_rectangle->y + offset_y, + xcenter, crect->y + crect->height); + node = GTK_CTREE_ROW (node)->parent; } + gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL); + clip_rectangle->y++; + clip_rectangle->height--; break; - } + } + return offset; } static void @@ -1085,26 +1646,23 @@ draw_row (GtkCList *clist, { GtkWidget *widget; GtkCTree *ctree; - GdkGC *fg_gc; - GdkGC *bg_gc; + GdkRectangle *rect; + GdkRectangle *crect; GdkRectangle row_rectangle; GdkRectangle cell_rectangle; GdkRectangle clip_rectangle; GdkRectangle intersect_rectangle; - GdkRectangle *rect; - - gint i, offset = 0, width, height, pixmap_width = 0, string_width = 0; - gint xsrc, ysrc, xdest = 0, ydest; - gboolean need_redraw = TRUE; - gboolean draw_pixmap = FALSE; + gint last_column; + gint column_left = 0; + gint column_right = 0; + gint offset = 0; + gint state; + gint i; g_return_if_fail (clist != NULL); /* bail now if we arn't drawable yet */ - if (!GTK_WIDGET_DRAWABLE (clist)) - return; - - if (row < 0 || row >= clist->rows) + if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows) return; widget = GTK_WIDGET (clist); @@ -1127,1272 +1685,362 @@ draw_row (GtkCList *clist, cell_rectangle.width = row_rectangle.width; cell_rectangle.height = CELL_SPACING; - /* rectangle used to clip drawing operations, it's y and height + /* rectangle used to clip drawing operations, its y and height * positions only need to be set once, so we set them once here. * the x and width are set withing the drawing loop below once per * column */ clip_rectangle.y = row_rectangle.y; clip_rectangle.height = row_rectangle.height; - /* select GC for background rectangle */ - if (clist_row->state == GTK_STATE_SELECTED) - { - fg_gc = widget->style->fg_gc[GTK_STATE_SELECTED]; - bg_gc = widget->style->bg_gc[GTK_STATE_SELECTED]; - } - else + if (clist_row->state == GTK_STATE_NORMAL) { if (clist_row->fg_set) - { - gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground); - fg_gc = clist->fg_gc; - } - else - fg_gc = widget->style->fg_gc[GTK_STATE_NORMAL]; - + gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground); if (clist_row->bg_set) - { - gdk_gc_set_foreground (clist->bg_gc, &clist_row->background); - bg_gc = clist->bg_gc; - } - else - bg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT]; - + gdk_gc_set_foreground (clist->bg_gc, &clist_row->background); } + + state = clist_row->state; + + gdk_gc_set_foreground (ctree->lines_gc, + &widget->style->fg[clist_row->state]); - /* draw the cell borders and background */ + /* draw the cell borders */ if (area) { - if (gdk_rectangle_intersect (area, &cell_rectangle, - &intersect_rectangle)) - gdk_draw_rectangle (clist->clist_window, - widget->style->base_gc[GTK_STATE_NORMAL], - TRUE, - intersect_rectangle.x, - intersect_rectangle.y, - intersect_rectangle.width, - intersect_rectangle.height); - - /* the last row has to clear it's bottom cell spacing too */ - if (clist_row == clist->row_list_end->data) - { - cell_rectangle.y += clist->row_height + CELL_SPACING; + rect = &intersect_rectangle; + crect = &intersect_rectangle; - if (gdk_rectangle_intersect (area, &cell_rectangle, - &intersect_rectangle)) - gdk_draw_rectangle (clist->clist_window, - widget->style->base_gc[GTK_STATE_NORMAL], - TRUE, - intersect_rectangle.x, - intersect_rectangle.y, - intersect_rectangle.width, - intersect_rectangle.height); - } - - if (gdk_rectangle_intersect - (area, &row_rectangle, &intersect_rectangle)) - { - if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set) - gdk_draw_rectangle (clist->clist_window, - bg_gc, - TRUE, - intersect_rectangle.x, - intersect_rectangle.y, - intersect_rectangle.width, - intersect_rectangle.height); - else - gdk_window_clear_area (clist->clist_window, - intersect_rectangle.x, - intersect_rectangle.y, - intersect_rectangle.width, - intersect_rectangle.height); - } - else - need_redraw = FALSE; + if (gdk_rectangle_intersect (area, &cell_rectangle, crect)) + gdk_draw_rectangle (clist->clist_window, + widget->style->base_gc[GTK_STATE_NORMAL], TRUE, + crect->x, crect->y, crect->width, crect->height); } else { - gdk_draw_rectangle (clist->clist_window, - widget->style->base_gc[GTK_STATE_NORMAL], - TRUE, - cell_rectangle.x, - cell_rectangle.y, - cell_rectangle.width, - cell_rectangle.height); - - /* the last row has to clear it's bottom cell spacing too */ - if (clist_row == clist->row_list_end->data) - { - cell_rectangle.y += clist->row_height + CELL_SPACING; + rect = &clip_rectangle; + crect = &cell_rectangle; - gdk_draw_rectangle (clist->clist_window, - widget->style->base_gc[GTK_STATE_NORMAL], - TRUE, - cell_rectangle.x, - cell_rectangle.y, - cell_rectangle.width, - cell_rectangle.height); - } - - if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set) - gdk_draw_rectangle (clist->clist_window, - bg_gc, - TRUE, - row_rectangle.x, - row_rectangle.y, - row_rectangle.width, - row_rectangle.height); - else - gdk_window_clear_area (clist->clist_window, - row_rectangle.x, - row_rectangle.y, - row_rectangle.width, - row_rectangle.height); + gdk_draw_rectangle (clist->clist_window, + widget->style->base_gc[GTK_STATE_NORMAL], TRUE, + crect->x, crect->y, crect->width, crect->height); } - /* iterate and draw all the columns (row cells) and draw their contents */ - for (i = 0; i < clist->columns; i++) - { - - if (!need_redraw && ctree->tree_column != i) - continue; + /* horizontal black lines */ + if (ctree->line_style == GTK_CTREE_LINES_TABBED) + { - clip_rectangle.x = clist->column[i].area.x + clist->hoffset; - clip_rectangle.width = clist->column[i].area.width; + column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) + + clist->column[ctree->tree_column].area.width + + COLUMN_INSET); + column_left = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) - + COLUMN_INSET - (ctree->tree_column != 0) * CELL_SPACING); - /* calculate clipping region */ - if (i == ctree->tree_column) + switch (clist->column[ctree->tree_column].justification) { - clip_rectangle.y -= CELL_SPACING; - clip_rectangle.height += CELL_SPACING; + case GTK_JUSTIFY_CENTER: + case GTK_JUSTIFY_FILL: + case GTK_JUSTIFY_LEFT: + offset = (column_left + ctree->tree_indent * + (((GtkCTreeRow *)clist_row)->level - 1)); + + gdk_draw_line (clist->clist_window, ctree->lines_gc, + MIN (offset + TAB_SIZE, column_right), + cell_rectangle.y, + clist->clist_window_width, cell_rectangle.y); + break; + case GTK_JUSTIFY_RIGHT: + offset = (column_right - 1 - ctree->tree_indent * + (((GtkCTreeRow *)clist_row)->level - 1)); + + gdk_draw_line (clist->clist_window, ctree->lines_gc, + -1, cell_rectangle.y, + MAX (offset - TAB_SIZE, column_left), + cell_rectangle.y); + break; } + } + + /* the last row has to clear its bottom cell spacing too */ + if (clist_row == clist->row_list_end->data) + { + cell_rectangle.y += clist->row_height + CELL_SPACING; - if (i == ctree->tree_column) + if (!area || gdk_rectangle_intersect (area, &cell_rectangle, crect)) { + gdk_draw_rectangle (clist->clist_window, + widget->style->base_gc[GTK_STATE_NORMAL], TRUE, + crect->x, crect->y, crect->width, crect->height); - if (clist_row->state == GTK_STATE_SELECTED) - { - gdk_gc_set_foreground (ctree->lines_gc, - >K_WIDGET (ctree)->style-> - fg[GTK_STATE_SELECTED]); - gdk_gc_set_background (ctree->lines_gc, - >K_WIDGET (ctree)->style-> - bg[GTK_STATE_SELECTED]); - } - else - { - gdk_gc_set_foreground (ctree->lines_gc, - >K_WIDGET (ctree)->style-> - fg[GTK_STATE_NORMAL]); - if (clist_row->bg_set) - gdk_gc_set_background (ctree->lines_gc, - &clist_row->background); - } - + /* horizontal black lines */ if (ctree->line_style == GTK_CTREE_LINES_TABBED) - { - if (clist->column[i].justification == GTK_JUSTIFY_RIGHT) - { - xdest = clip_rectangle.x + clip_rectangle.width - 1 - - (((GtkCTreeRow *) clist_row)->level - 1) * - ctree->tree_indent; - - gdk_draw_line (clist->clist_window, - ctree->lines_gc, - -1, - row_rectangle.y - 1, - MAX (xdest - TAB_SIZE, clip_rectangle.x - 1), - row_rectangle.y - 1); - - if (clist_row == clist->row_list_end->data) - gdk_draw_line - (clist->clist_window, - ctree->lines_gc, - -1, - row_rectangle.y + clist->row_height, - MAX (clip_rectangle.x + clip_rectangle.width - - TAB_SIZE - 1 - - (((GtkCTreeRow *) clist_row)->level > 1) * - MIN (ctree->tree_indent / 2, TAB_SIZE), - clip_rectangle.x - 1), - row_rectangle.y + clist->row_height); - - if (clist_row->state != GTK_STATE_SELECTED) - gdk_draw_rectangle - (clist->clist_window, - widget->style->bg_gc[GTK_STATE_PRELIGHT], - TRUE, - clip_rectangle.x + clip_rectangle.width, - row_rectangle.y, - CELL_SPACING + COLUMN_INSET, - row_rectangle.height); - } - else + { + switch (clist->column[ctree->tree_column].justification) { - xdest = clip_rectangle.x + - (((GtkCTreeRow *) clist_row)->level - 1) * - ctree->tree_indent; - - gdk_draw_line (clist->clist_window, - ctree->lines_gc, - MIN (xdest + TAB_SIZE, - clip_rectangle.x + clip_rectangle.width), - row_rectangle.y - 1, - clist->clist_window_width, - row_rectangle.y - 1); - - if (clist_row == clist->row_list_end->data) - gdk_draw_line - (clist->clist_window, ctree->lines_gc, - MIN (clip_rectangle.x + TAB_SIZE + - (((GtkCTreeRow *) clist_row)->level > 1) * - MIN (ctree->tree_indent / 2, TAB_SIZE), - clip_rectangle.x + clip_rectangle.width), - row_rectangle.y + clist->row_height, - clist->clist_window_width, - row_rectangle.y + clist->row_height); - - if (clist_row->state != GTK_STATE_SELECTED) - gdk_draw_rectangle - (clist->clist_window, - widget->style->bg_gc[GTK_STATE_PRELIGHT], - TRUE, - clip_rectangle.x - CELL_SPACING - COLUMN_INSET, - row_rectangle.y, - CELL_SPACING + COLUMN_INSET, - row_rectangle.height); + case GTK_JUSTIFY_CENTER: + case GTK_JUSTIFY_FILL: + case GTK_JUSTIFY_LEFT: + gdk_draw_line (clist->clist_window, ctree->lines_gc, + MIN (column_left + TAB_SIZE + COLUMN_INSET + + (((GtkCTreeRow *)clist_row)->level > 1) * + MIN (ctree->tree_indent / 2, TAB_SIZE), + column_right), + cell_rectangle.y, + clist->clist_window_width, cell_rectangle.y); + break; + case GTK_JUSTIFY_RIGHT: + gdk_draw_line (clist->clist_window, ctree->lines_gc, + -1, cell_rectangle.y, + MAX (column_right - TAB_SIZE - 1 - + COLUMN_INSET - + (((GtkCTreeRow *)clist_row)->level > 1) * + MIN (ctree->tree_indent / 2, TAB_SIZE), + column_left - 1), cell_rectangle.y); + break; } } } + } - if (!area) - { - rect = &clip_rectangle; - } - else - { + for (last_column = clist->columns - 1; + last_column >= 0 && !clist->column[last_column].visible; last_column--) + ; - if (!gdk_rectangle_intersect (area, &clip_rectangle, - &intersect_rectangle)) - continue; - rect = &intersect_rectangle; - } - - /* calculate real width for column justification */ - switch (clist_row->cell[i].type) - { - case GTK_CELL_EMPTY: - continue; - break; - - case GTK_CELL_TEXT: - width = gdk_string_width (GTK_WIDGET (clist)->style->font, - GTK_CELL_TEXT (clist_row->cell[i])->text); - break; - - case GTK_CELL_PIXMAP: - gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, - &width, &height); - pixmap_width = width; - break; - - case GTK_CELL_PIXTEXT: - if (i == ctree->tree_column) - { - string_width = 0; - width = 0; + /* iterate and draw all the columns (row cells) and draw their contents */ + for (i = 0; i < clist->columns; i++) + { + GtkStyle *style; + GdkGC *fg_gc; + GdkGC *bg_gc; + PangoLayout *layout = NULL; + PangoRectangle logical_rect; + + gint width; + gint height; + gint pixmap_width; + gint string_width; + gint old_offset; + + if (!clist->column[i].visible) + continue; - if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap) - gdk_window_get_size (GTK_CELL_PIXTEXT - (clist_row->cell[i])->pixmap, - &width, &height); + get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc); - pixmap_width = width; - width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing; + /* calculate clipping region */ + clip_rectangle.x = clist->column[i].area.x + clist->hoffset; + clip_rectangle.width = clist->column[i].area.width; - if (GTK_CELL_PIXTEXT (clist_row->cell[i])->text) - string_width += gdk_string_width - (GTK_WIDGET (clist)->style->font, - GTK_CELL_PIXTEXT(clist_row->cell[i])->text); - - width += string_width + - ((GtkCTreeRow *)clist_row)->level * ctree->tree_indent; - } - else - { - gdk_window_get_size (GTK_CELL_PIXTEXT - (clist_row->cell[i])->pixmap, - &width, &height); - pixmap_width = width; - width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing; - width += gdk_string_width (GTK_WIDGET (clist)->style->font, - GTK_CELL_PIXTEXT - (clist_row->cell[i])->text); - } - break; + cell_rectangle.x = clip_rectangle.x - COLUMN_INSET - CELL_SPACING; + cell_rectangle.width = (clip_rectangle.width + 2 * COLUMN_INSET + + (1 + (i == last_column)) * CELL_SPACING); + cell_rectangle.y = clip_rectangle.y; + cell_rectangle.height = clip_rectangle.height; - case GTK_CELL_WIDGET: - /* unimplemented */ - continue; - break; + string_width = 0; + pixmap_width = 0; - default: - continue; - break; + if (area && !gdk_rectangle_intersect (area, &cell_rectangle, + &intersect_rectangle)) + { + if (i != ctree->tree_column) + continue; } - - switch (clist->column[i].justification) + else { - case GTK_JUSTIFY_LEFT: - offset = clip_rectangle.x; - break; + gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE, + crect->x, crect->y, crect->width, crect->height); - case GTK_JUSTIFY_RIGHT: - offset = (clip_rectangle.x + clip_rectangle.width) - width; - break; - - case GTK_JUSTIFY_CENTER: - offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - - (width / 2); - break; - - case GTK_JUSTIFY_FILL: - offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - - (width / 2); - break; - - default: - offset = 0; - break; - }; - if (i == ctree->tree_column) - { - GdkGC *cgc; - GdkGC *tgc; - GdkGC *mbg_gc; - GtkCTreeNode *work; - GtkCTreeNode *work2; - gint xoffset; - gint yoffset; - gint xcenter; - gint ycenter; - gint offset_x; - gint offset_y = 0; - gint next_level; - gint in; - GdkPoint points[6]; + layout = _gtk_clist_create_cell_layout (clist, clist_row, i); + if (layout) + { + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + width = logical_rect.width; + } + else + width = 0; - xsrc = 0; - ysrc = 0; + switch (clist_row->cell[i].type) + { + case GTK_CELL_PIXMAP: + gdk_window_get_size + (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &pixmap_width, + &height); + width += pixmap_width; + break; + case GTK_CELL_PIXTEXT: + if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap) + { + gdk_window_get_size + (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap, + &pixmap_width, &height); + width += pixmap_width; + } - yoffset = (clip_rectangle.height - PM_SIZE) / 2; - xoffset = (ctree->tree_indent - PM_SIZE) / 2; - ycenter = clip_rectangle.y + (clip_rectangle.height / 2); - ydest = ycenter - height / 2 + clist_row->cell[i].vertical; + if (GTK_CELL_PIXTEXT (clist_row->cell[i])->text && + GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap) + width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing; - gdk_gc_set_clip_origin (fg_gc, 0, 0); - gdk_gc_set_clip_rectangle (fg_gc, rect); - if (ctree->line_style != GTK_CTREE_LINES_NONE) - { - gdk_gc_set_clip_origin (ctree->lines_gc, 0, 0); - gdk_gc_set_clip_rectangle (ctree->lines_gc, rect); + if (i == ctree->tree_column) + width += (ctree->tree_indent * + ((GtkCTreeRow *)clist_row)->level); + break; + default: + break; } switch (clist->column[i].justification) { + case GTK_JUSTIFY_LEFT: + offset = clip_rectangle.x + clist_row->cell[i].horizontal; + break; + case GTK_JUSTIFY_RIGHT: + offset = (clip_rectangle.x + clist_row->cell[i].horizontal + + clip_rectangle.width - width); + break; case GTK_JUSTIFY_CENTER: case GTK_JUSTIFY_FILL: - offset = clip_rectangle.x; - case GTK_JUSTIFY_LEFT: - offset_x = 1; - xdest = clip_rectangle.x - xoffset + - (((GtkCTreeRow *) clist_row)->level - 1) * ctree->tree_indent; - xcenter = xdest + (ctree->tree_indent / 2); - - switch (ctree->line_style) + offset = (clip_rectangle.x + clist_row->cell[i].horizontal + + (clip_rectangle.width / 2) - (width / 2)); + break; + }; + + if (i != ctree->tree_column) + { + offset += clist_row->cell[i].horizontal; + switch (clist_row->cell[i].type) { - case GTK_CTREE_LINES_NONE: + case GTK_CELL_PIXMAP: + draw_cell_pixmap + (clist->clist_window, &clip_rectangle, fg_gc, + GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, + GTK_CELL_PIXMAP (clist_row->cell[i])->mask, + offset, + clip_rectangle.y + clist_row->cell[i].vertical + + (clip_rectangle.height - height) / 2, + pixmap_width, height); break; - case GTK_CTREE_LINES_TABBED: - xdest = clip_rectangle.x + - (((GtkCTreeRow *) clist_row)->level - 1) * - ctree->tree_indent; - xcenter = xdest + TAB_SIZE; - - gdk_gc_set_clip_origin (clist->bg_gc, 0, 0); - gdk_gc_set_clip_rectangle (clist->bg_gc, rect); - - gdk_gc_set_clip_origin - (widget->style->bg_gc[GTK_STATE_PRELIGHT], 0, 0); - gdk_gc_set_clip_rectangle - (widget->style->bg_gc[GTK_STATE_PRELIGHT], rect); - - work = ((GtkCTreeRow *)clist_row)->parent; - next_level = ((GtkCTreeRow *)clist_row)->level; - - if (!(((GtkCTreeRow *)clist_row)->sibling || - (((GtkCTreeRow *)clist_row)->children && - ((GtkCTreeRow *)clist_row)->expanded))) + case GTK_CELL_PIXTEXT: + offset = draw_cell_pixmap + (clist->clist_window, &clip_rectangle, fg_gc, + GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap, + GTK_CELL_PIXTEXT (clist_row->cell[i])->mask, + offset, + clip_rectangle.y + clist_row->cell[i].vertical + + (clip_rectangle.height - height) / 2, + pixmap_width, height); + offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing; + + /* Fall through */ + case GTK_CELL_TEXT: + if (layout) { - work2 = gtk_ctree_find_glist_ptr - (ctree, (GtkCTreeRow *) clist_row); - - if (GTK_CTREE_NODE_NEXT (work2)) - next_level = - GTK_CTREE_ROW (GTK_CTREE_NODE_NEXT (work2))->level; - else - next_level = 0; - } - - while (work) - { - xcenter -= ctree->tree_indent; - - if (GTK_CTREE_ROW(work)->row.bg_set) - { - gdk_gc_set_foreground - (clist->bg_gc, - &(GTK_CTREE_ROW(work)->row.background)); - mbg_gc = clist->bg_gc; - } - else - mbg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT]; - - if (clist_row->state != GTK_STATE_SELECTED) - gdk_draw_rectangle (clist->clist_window, mbg_gc, TRUE, - xcenter, rect->y, - ctree->tree_indent, rect->height); - - if (next_level > GTK_CTREE_ROW (work)->level) - gdk_draw_line - (clist->clist_window, ctree->lines_gc, - xcenter, rect->y, - xcenter, rect->y + rect->height); - else - { - gdk_draw_line (clist->clist_window, ctree->lines_gc, - xcenter, clip_rectangle.y, - xcenter, ycenter); - - in = MIN (ctree->tree_indent, 2 * TAB_SIZE); - - if (clist_row->state != GTK_STATE_SELECTED) - { - work2 = GTK_CTREE_ROW (work)->parent; - - if (work2 && GTK_CTREE_ROW (work2)->row.bg_set) - { - gdk_gc_set_foreground - (clist->bg_gc, - &(GTK_CTREE_ROW (work2)->row.background)); - - gdk_draw_rectangle - (clist->clist_window, clist->bg_gc, TRUE, - xcenter, - ycenter, - in / 2 + in % 2, - row_rectangle.height / 2 + 1); - - if (GTK_CTREE_ROW (work)->row.bg_set) - gdk_gc_set_foreground - (clist->bg_gc, - &(GTK_CTREE_ROW (work)->row.background)); - } - else - gdk_draw_rectangle - (clist->clist_window, - widget->style->bg_gc[GTK_STATE_PRELIGHT], - TRUE, - xcenter, - ycenter, - in / 2 + in % 2, - row_rectangle.height / 2 + 1); - - gdk_draw_arc (clist->clist_window, mbg_gc, - TRUE, - xcenter, clip_rectangle.y, - in, clist->row_height, - 180 * 64, 90 * 64); - } - - gdk_draw_arc (clist->clist_window, ctree->lines_gc, - FALSE, - xcenter, clip_rectangle.y, - in, clist->row_height, - 180 * 64, 90 * 64); - } - work = GTK_CTREE_ROW (work)->parent; - } - - if (clist_row->state != GTK_STATE_SELECTED) - gdk_draw_rectangle - (clist->clist_window, - widget->style->bg_gc[GTK_STATE_PRELIGHT], TRUE, - clip_rectangle.x, row_rectangle.y, - TAB_SIZE, row_rectangle.height); - - xcenter = xdest + (ctree->tree_indent / 2); - - if (clist_row->bg_set) - gdk_gc_set_foreground - (clist->bg_gc, &clist_row->background); - - if (((GtkCTreeRow *)clist_row)->is_leaf) - { - points[0].x = xdest + TAB_SIZE; - points[0].y = row_rectangle.y - 1; - - points[1].x = points[0].x - 4; - points[1].y = points[0].y; - - points[2].x = points[1].x - 2; - points[2].y = points[1].y + 3; - - points[3].x = points[2].x; - points[3].y = points[2].y + clist->row_height - 5; - - points[4].x = points[3].x + 2; - points[4].y = points[3].y + 3; - - points[5].x = points[4].x + 4; - points[5].y = points[4].y; - - if (clist_row->state != GTK_STATE_SELECTED) - gdk_draw_polygon (clist->clist_window, bg_gc, TRUE, - points, 6); - - gdk_draw_lines (clist->clist_window, ctree->lines_gc, - points, 6); - } - else - { - if (clist_row->state != GTK_STATE_SELECTED) - gdk_draw_arc (clist->clist_window, bg_gc, TRUE, - xdest, row_rectangle.y - 1, - 2 * TAB_SIZE, clist->row_height, - 90 * 64, 180 * 64); - - gdk_draw_arc (clist->clist_window, ctree->lines_gc, - FALSE, - xdest, row_rectangle.y - 1, - 2 * TAB_SIZE, clist->row_height, - 90 * 64, 180 * 64); - + gint row_center_offset = 1.5 + (clist->row_height - logical_rect.height - 1) / 2; + + gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle); + gdk_draw_layout (clist->clist_window, fg_gc, + offset, + row_rectangle.y + row_center_offset + clist_row->cell[i].vertical, + layout); + gdk_gc_set_clip_rectangle (fg_gc, NULL); + g_object_unref (G_OBJECT (layout)); } - - gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL); - gdk_gc_set_clip_rectangle (clist->bg_gc, NULL); - gdk_gc_set_clip_rectangle - (widget->style->bg_gc[GTK_STATE_PRELIGHT], NULL); - break; default: - xcenter = xdest + (ctree->tree_indent / 2); - if (ctree->line_style == GTK_CTREE_LINES_DOTTED) - { - offset_x += abs ((clip_rectangle.x + clist->hoffset) % - 2); - offset_y = abs ((clip_rectangle.y + clist->voffset) % 2); - } - - gdk_draw_line (clist->clist_window, ctree->lines_gc, - xcenter, clip_rectangle.y + offset_y, xcenter, - (((GtkCTreeRow *)clist_row)->sibling) ? - rect->y + rect->height : ycenter); - - gdk_draw_line (clist->clist_window, ctree->lines_gc, - xcenter + offset_x, ycenter, - xcenter + PM_SIZE / 2 + 2, ycenter); - - work = ((GtkCTreeRow *)clist_row)->parent; - while (work) - { - xcenter -= ctree->tree_indent; - if (GTK_CTREE_ROW (work)->sibling) - gdk_draw_line (clist->clist_window, ctree->lines_gc, - xcenter, clip_rectangle.y + offset_y, - xcenter, rect->y + rect->height); - work = GTK_CTREE_ROW (work)->parent; - } - gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL); break; } - - if (((GtkCTreeRow *)clist_row)->children) - { - if (clist_row->state == GTK_STATE_SELECTED) - { - if (clist_row->fg_set) - tgc = clist->fg_gc; - else - tgc = widget->style->fg_gc[GTK_STATE_NORMAL]; - cgc = tgc; - } - else - { - cgc = GTK_WIDGET - (clist)->style->fg_gc[GTK_STATE_SELECTED]; - tgc = fg_gc; - } - - gdk_gc_set_clip_rectangle (cgc, rect); - - switch (ctree->line_style) - { - case GTK_CTREE_LINES_NONE: - if (!((GtkCTreeRow *)clist_row)->expanded) - { - points[0].x = xdest + xoffset + (PM_SIZE+2) / 6 + 2; - points[0].y = clip_rectangle.y + yoffset - 1; - points[1].x = points[0].x; - points[1].y = points[0].y + (PM_SIZE+2); - points[2].x = points[0].x + 2 * (PM_SIZE+2) / 3 - 1; - points[2].y = points[0].y + (PM_SIZE+2) / 2; - } - else - { - points[0].x = xdest + xoffset; - points[0].y = clip_rectangle.y + yoffset - + (PM_SIZE+2) / 6; - points[1].x = points[0].x + (PM_SIZE+2); - points[1].y = points[0].y; - points[2].x = points[0].x + (PM_SIZE+2) / 2; - points[2].y = clip_rectangle.y + yoffset + - 2 * (PM_SIZE+2) / 3; - } - - gdk_draw_polygon (clist->clist_window, - GTK_WIDGET (clist)->style-> - fg_gc[GTK_STATE_SELECTED], - TRUE, points, 3); - gdk_draw_polygon (clist->clist_window, tgc, FALSE, - points, 3); - break; - case GTK_CTREE_LINES_TABBED: - xcenter = xdest + PM_SIZE + 2; - gdk_draw_arc (clist->clist_window, - GTK_WIDGET (clist)->style-> - fg_gc[GTK_STATE_SELECTED], - TRUE, - xcenter - PM_SIZE/2, - ycenter - PM_SIZE/2, - PM_SIZE, PM_SIZE, 0, 360 * 64); - - gdk_draw_line (clist->clist_window, tgc, - xcenter - 2, - ycenter, - xcenter + 2, - ycenter); - - if (!((GtkCTreeRow *)clist_row)->expanded) - gdk_draw_line (clist->clist_window, tgc, - xcenter, clip_rectangle.y + yoffset + 2, - xcenter, - clip_rectangle.y + yoffset + PM_SIZE-2); - break; - default: - gdk_draw_rectangle - (clist->clist_window, - GTK_WIDGET (clist)->style->fg_gc[GTK_STATE_SELECTED], - TRUE, - xdest + xoffset, - clip_rectangle.y + yoffset, - PM_SIZE, PM_SIZE); - - gdk_draw_rectangle (clist->clist_window, tgc, FALSE, - xdest + xoffset, - clip_rectangle.y + yoffset, - PM_SIZE, PM_SIZE); - - gdk_draw_line (clist->clist_window, tgc, - xdest + xoffset + 2, ycenter, - xdest + xoffset + PM_SIZE - 2, ycenter); - - if (!((GtkCTreeRow *)clist_row)->expanded) - { - xcenter = xdest + (ctree->tree_indent / 2); - gdk_draw_line (clist->clist_window, tgc, - xcenter, - clip_rectangle.y + yoffset + 2, - xcenter, - clip_rectangle.y + yoffset + - PM_SIZE - 2); - } - break; - } - - gdk_gc_set_clip_rectangle (cgc, NULL); - } - - xdest += offset - clip_rectangle.x + ctree->tree_indent + - clist_row->cell[i].horizontal; - - if (pixmap_width && xdest + pixmap_width >= rect->x && - xdest <= rect->x + rect->width) - draw_pixmap = TRUE; - - break; - - case GTK_JUSTIFY_RIGHT: - offset_x = 0; - - xdest = clip_rectangle.x + clip_rectangle.width + xoffset - 1 - - (((GtkCTreeRow *) clist_row)->level - 1) * ctree->tree_indent; - - switch (ctree->line_style) - { - case GTK_CTREE_LINES_NONE: - break; - case GTK_CTREE_LINES_TABBED: - xdest = clip_rectangle.x + clip_rectangle.width - 1 - - (((GtkCTreeRow *) clist_row)->level - 1) - * ctree->tree_indent; - xcenter = xdest - TAB_SIZE; - - gdk_gc_set_clip_origin (clist->bg_gc, 0, 0); - gdk_gc_set_clip_rectangle (clist->bg_gc, rect); - - gdk_gc_set_clip_origin - (widget->style->bg_gc[GTK_STATE_PRELIGHT], 0, 0); - gdk_gc_set_clip_rectangle - (widget->style->bg_gc[GTK_STATE_PRELIGHT], rect); - - work = ((GtkCTreeRow *)clist_row)->parent; - next_level = ((GtkCTreeRow *)clist_row)->level; - - if (!(((GtkCTreeRow *)clist_row)->sibling || - (((GtkCTreeRow *)clist_row)->children && - ((GtkCTreeRow *)clist_row)->expanded))) - { - work2 = gtk_ctree_find_glist_ptr - (ctree, (GtkCTreeRow *) clist_row); + continue; + } + } - if (GTK_CTREE_NODE_NEXT (work2)) - next_level = - GTK_CTREE_ROW (GTK_CTREE_NODE_NEXT (work2))->level; - else - next_level = 0; - } + if (bg_gc == clist->bg_gc) + gdk_gc_set_background (ctree->lines_gc, &clist_row->background); - while (work) - { - xcenter += ctree->tree_indent; + /* draw ctree->tree_column */ + cell_rectangle.y -= CELL_SPACING; + cell_rectangle.height += CELL_SPACING; - if (GTK_CTREE_ROW(work)->row.bg_set) - { - gdk_gc_set_foreground - (clist->bg_gc, - &(GTK_CTREE_ROW (work)->row.background)); - mbg_gc = clist->bg_gc; - } - else - mbg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT]; + if (area && !gdk_rectangle_intersect (area, &cell_rectangle, + &intersect_rectangle)) + { + if (layout) + g_object_unref (G_OBJECT (layout)); + continue; + } - if (clist_row->state != GTK_STATE_SELECTED) - gdk_draw_rectangle (clist->clist_window, - mbg_gc, TRUE, - xcenter - ctree->tree_indent + 1, - rect->y, - ctree->tree_indent, - rect->height); - - if (next_level > GTK_CTREE_ROW (work)->level) - gdk_draw_line - (clist->clist_window, ctree->lines_gc, - xcenter, rect->y, - xcenter, rect->y + rect->height); - else - { - gdk_draw_line (clist->clist_window, ctree->lines_gc, - xcenter, clip_rectangle.y, - xcenter, ycenter); - - in = MIN (ctree->tree_indent, 2 * TAB_SIZE); - - if (clist_row->state != GTK_STATE_SELECTED) - { - work2 = GTK_CTREE_ROW (work)->parent; - - if (work2 && GTK_CTREE_ROW (work2)->row.bg_set) - { - gdk_gc_set_foreground - (clist->bg_gc, - &(GTK_CTREE_ROW (work2)->row.background)); - - gdk_draw_rectangle - (clist->clist_window, clist->bg_gc, TRUE, - xcenter + 1 - in / 2 - in % 2, - ycenter, - in / 2 + in % 2, - row_rectangle.height / 2 + 1); - - if (GTK_CTREE_ROW (work)->row.bg_set) - gdk_gc_set_foreground - (clist->bg_gc, - &(GTK_CTREE_ROW(work)->row.background)); - } - else - gdk_draw_rectangle - (clist->clist_window, - widget->style->bg_gc[GTK_STATE_PRELIGHT], - TRUE, - xcenter + 1 - in / 2 - in % 2, - ycenter, - in / 2 + in % 2, - row_rectangle.height / 2 + 1); - - gdk_draw_arc (clist->clist_window, mbg_gc, TRUE, - xcenter - in, clip_rectangle.y, - in, clist->row_height, - 270 * 64, 90 * 64); - } - - gdk_draw_arc (clist->clist_window, ctree->lines_gc, - FALSE, - xcenter - in, clip_rectangle.y, - in, clist->row_height, - 270 * 64, 90 * 64); - } + /* draw lines */ + offset = gtk_ctree_draw_lines (ctree, (GtkCTreeRow *)clist_row, row, i, + state, &clip_rectangle, &cell_rectangle, + crect, area, style); - work = GTK_CTREE_ROW (work)->parent; - } + /* draw expander */ + offset = gtk_ctree_draw_expander (ctree, (GtkCTreeRow *)clist_row, + style, &clip_rectangle, offset); - if (clist_row->state != GTK_STATE_SELECTED) - gdk_draw_rectangle - (clist->clist_window, - widget->style->bg_gc[GTK_STATE_PRELIGHT], TRUE, - xcenter + 1, row_rectangle.y, - TAB_SIZE, row_rectangle.height); - - xcenter = xdest - (ctree->tree_indent / 2); - - if (clist_row->bg_set) - gdk_gc_set_foreground - (clist->bg_gc, &clist_row->background); - - if (((GtkCTreeRow *)clist_row)->is_leaf) - { - points[0].x = xdest - TAB_SIZE; - points[0].y = row_rectangle.y - 1; - - points[1].x = points[0].x + 4; - points[1].y = points[0].y; - - points[2].x = points[1].x + 2; - points[2].y = points[1].y + 3; - - points[3].x = points[2].x; - points[3].y = points[2].y + clist->row_height - 5; - - points[4].x = points[3].x - 2; - points[4].y = points[3].y + 3; - - points[5].x = points[4].x - 4; - points[5].y = points[4].y; - - if (clist_row->state != GTK_STATE_SELECTED) - gdk_draw_polygon (clist->clist_window, bg_gc, TRUE, - points, 6); - - gdk_draw_lines (clist->clist_window, ctree->lines_gc, - points, 6); - } - else - { - if (clist_row->state != GTK_STATE_SELECTED) - gdk_draw_arc (clist->clist_window, bg_gc, TRUE, - xdest - 2 * TAB_SIZE, - row_rectangle.y - 1, - 2 * TAB_SIZE, clist->row_height, - 270 * 64, 180 * 64); - - gdk_draw_arc (clist->clist_window, ctree->lines_gc, - FALSE, - xdest - 2 * TAB_SIZE, - row_rectangle.y - 1, - 2 * TAB_SIZE, clist->row_height, - 270 * 64, 180 * 64); - } - - gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL); - gdk_gc_set_clip_rectangle (clist->bg_gc, NULL); - gdk_gc_set_clip_rectangle - (widget->style->bg_gc[GTK_STATE_PRELIGHT], NULL); - - break; - default: - xcenter = xdest - (ctree->tree_indent / 2); - if (ctree->line_style == GTK_CTREE_LINES_DOTTED) - { - offset_x += abs ((clip_rectangle.x + clist->hoffset) % - 2); - offset_y = abs ((clip_rectangle.y + clist->voffset) % 2); - } - - gdk_draw_line (clist->clist_window, ctree->lines_gc, - xcenter, clip_rectangle.y + offset_y, - xcenter, - (((GtkCTreeRow *)clist_row)->sibling) ? - rect->y + rect->height : ycenter); - - gdk_draw_line (clist->clist_window, ctree->lines_gc, - xcenter - offset_x, ycenter, - xcenter - PM_SIZE / 2 - 2, ycenter); - - work = ((GtkCTreeRow *)clist_row)->parent; - while (work) - { - xcenter += ctree->tree_indent; - if (GTK_CTREE_ROW (work)->sibling) - gdk_draw_line (clist->clist_window, ctree->lines_gc, - xcenter, clip_rectangle.y - offset_y, - xcenter, rect->y + rect->height); - work = GTK_CTREE_ROW (work)->parent; - } - gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL); - } + if (clist->column[i].justification == GTK_JUSTIFY_RIGHT) + offset -= ctree->tree_spacing; + else + offset += ctree->tree_spacing; + if (clist->column[i].justification == GTK_JUSTIFY_RIGHT) + offset -= (pixmap_width + clist_row->cell[i].horizontal); + else + offset += clist_row->cell[i].horizontal; + + old_offset = offset; + offset = draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc, + GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap, + GTK_CELL_PIXTEXT (clist_row->cell[i])->mask, + offset, + clip_rectangle.y + clist_row->cell[i].vertical + + (clip_rectangle.height - height) / 2, + pixmap_width, height); + + if (layout) + { + gint row_center_offset = 1.5 + (clist->row_height - logical_rect.height - 1) / 2; - if (((GtkCTreeRow *)clist_row)->children) - { - if (clist_row->state == GTK_STATE_SELECTED) - { - if (clist_row->fg_set) - tgc = clist->fg_gc; - else - tgc = widget->style->fg_gc[GTK_STATE_NORMAL]; - cgc = tgc; - } - else - { - cgc = - GTK_WIDGET(clist)->style->fg_gc[GTK_STATE_SELECTED]; - tgc = fg_gc; - } - - gdk_gc_set_clip_rectangle (cgc, rect); - - switch (ctree->line_style) - { - case GTK_CTREE_LINES_NONE: - if (!((GtkCTreeRow *)clist_row)->expanded) - { - points[0].x = xdest - xoffset - (PM_SIZE+2) / 6 - 2; - points[0].y = clip_rectangle.y + yoffset - 1; - points[1].x = points[0].x; - points[1].y = points[0].y + (PM_SIZE+2); - points[2].x = points[0].x - 2 * (PM_SIZE+2) / 3 + 1; - points[2].y = points[0].y + (PM_SIZE+2) / 2; - } - else - { - points[0].x = xdest - xoffset; - points[0].y = clip_rectangle.y + yoffset + - (PM_SIZE+2) / 6; - points[1].x = points[0].x - (PM_SIZE+2); - points[1].y = points[0].y; - points[2].x = points[0].x - (PM_SIZE+2) / 2; - points[2].y = clip_rectangle.y + yoffset + - 2 * (PM_SIZE+2) / 3; - } - - gdk_draw_polygon (clist->clist_window, - GTK_WIDGET (clist)->style-> - fg_gc[GTK_STATE_SELECTED], - TRUE, points, 3); - gdk_draw_polygon (clist->clist_window, tgc, FALSE, - points, 3); - break; - case GTK_CTREE_LINES_TABBED: - xcenter = xdest - PM_SIZE - 2; - - gdk_draw_arc (clist->clist_window, - GTK_WIDGET (clist)->style-> - fg_gc[GTK_STATE_SELECTED], - TRUE, - xcenter - PM_SIZE/2, - ycenter - PM_SIZE/2, - PM_SIZE, PM_SIZE, 0, 360 * 64); - - gdk_draw_line (clist->clist_window, tgc, - xcenter - 2, - ycenter, - xcenter + 2, - ycenter); - - if (!((GtkCTreeRow *)clist_row)->expanded) - { - gdk_draw_line (clist->clist_window, tgc, xcenter, - clip_rectangle.y + yoffset + 2, - xcenter, clip_rectangle.y + yoffset - + PM_SIZE - 2); - } - break; - default: - gdk_draw_rectangle (clist->clist_window, - GTK_WIDGET(clist)->style-> - fg_gc[GTK_STATE_SELECTED], TRUE, - xdest - xoffset - PM_SIZE, - clip_rectangle.y + yoffset, - PM_SIZE, PM_SIZE); - - gdk_draw_rectangle (clist->clist_window, tgc, FALSE, - xdest - xoffset - PM_SIZE, - clip_rectangle.y + yoffset, - PM_SIZE, PM_SIZE); - - gdk_draw_line (clist->clist_window, tgc, - xdest - xoffset - 2, ycenter, - xdest - xoffset - PM_SIZE + 2, ycenter); - - if (!((GtkCTreeRow *)clist_row)->expanded) - { - xcenter = xdest - (ctree->tree_indent / 2); - gdk_draw_line (clist->clist_window, tgc, xcenter, - clip_rectangle.y + yoffset + 2, - xcenter, clip_rectangle.y + yoffset - + PM_SIZE - 2); - } - } - gdk_gc_set_clip_rectangle (cgc, NULL); - } - - xdest -= (ctree->tree_indent + pixmap_width - + clist_row->cell[i].horizontal); - - if (pixmap_width && xdest + pixmap_width >= rect->x && - xdest <= rect->x + rect->width) - draw_pixmap = TRUE; - break; - default : - break; - } - - if (draw_pixmap) + if (clist->column[i].justification == GTK_JUSTIFY_RIGHT) { - if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask) - { - gdk_gc_set_clip_mask - (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask); - gdk_gc_set_clip_origin (fg_gc, xdest, ydest); - } - - if (xdest < clip_rectangle.x) - { - xsrc = clip_rectangle.x - xdest; - pixmap_width -= xsrc; - xdest = clip_rectangle.x; - } - - if (xdest + pixmap_width > - clip_rectangle.x + clip_rectangle.width) - pixmap_width = - (clip_rectangle.x + clip_rectangle.width) - xdest; - - if (ydest < clip_rectangle.y) - { - ysrc = clip_rectangle.y - ydest; - height -= ysrc; - ydest = clip_rectangle.y; - } - - if (ydest + height > clip_rectangle.y + clip_rectangle.height) - height = (clip_rectangle.y + clip_rectangle.height) - ydest; - - gdk_draw_pixmap (clist->clist_window, fg_gc, - GTK_CELL_PIXTEXT - (clist_row->cell[i])->pixmap, - xsrc, ysrc, xdest, ydest, - pixmap_width, height); - } - - if (string_width) - { - gint delta; - - if (clist->column[i].justification == GTK_JUSTIFY_RIGHT) - xdest -= (GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing + - string_width); - else - xdest += (GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing + - pixmap_width); - - delta = CELL_SPACING - (rect->y - clip_rectangle.y); - if (delta > 0) - { - rect->y += delta; - rect->height -= delta; - } - - gdk_gc_set_clip_rectangle (fg_gc, rect); - - gdk_draw_string - (clist->clist_window, widget->style->font, fg_gc, xdest, - row_rectangle.y + clist->row_center_offset + - clist_row->cell[i].vertical, - GTK_CELL_PIXTEXT (clist_row->cell[i])->text); + offset = (old_offset - string_width); + if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap) + offset -= GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing; } - gdk_gc_set_clip_rectangle (fg_gc, NULL); - } - else - { - switch (clist_row->cell[i].type) + else { - case GTK_CELL_EMPTY: - continue; - break; - - case GTK_CELL_TEXT: - gdk_gc_set_clip_rectangle (fg_gc, rect); - - gdk_draw_string (clist->clist_window, - widget->style->font, - fg_gc, - offset + clist_row->cell[i].horizontal, - row_rectangle.y + clist->row_center_offset + - clist_row->cell[i].vertical, - GTK_CELL_TEXT (clist_row->cell[i])->text); - - gdk_gc_set_clip_rectangle (fg_gc, NULL); - break; - - case GTK_CELL_PIXMAP: - xsrc = 0; - ysrc = 0; - xdest = offset + clist_row->cell[i].horizontal; - ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - - height / 2 + clist_row->cell[i].vertical; - - if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask) - { - gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXMAP - (clist_row->cell[i])->mask); - gdk_gc_set_clip_origin (fg_gc, xdest, ydest); - } - - if (xdest < clip_rectangle.x) - { - xsrc = clip_rectangle.x - xdest; - pixmap_width -= xsrc; - xdest = clip_rectangle.x; - } - - if (xdest + pixmap_width > - clip_rectangle.x + clip_rectangle.width) - pixmap_width = (clip_rectangle.x + clip_rectangle.width) - - xdest; - - if (ydest < clip_rectangle.y) - { - ysrc = clip_rectangle.y - ydest; - height -= ysrc; - ydest = clip_rectangle.y; - } - - if (ydest + height > clip_rectangle.y + clip_rectangle.height) - height = (clip_rectangle.y + clip_rectangle.height) - ydest; - - gdk_draw_pixmap (clist->clist_window, fg_gc, - GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, - xsrc, ysrc, xdest, ydest, pixmap_width, height); - - if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask) - { - gdk_gc_set_clip_origin (fg_gc, 0, 0); - gdk_gc_set_clip_mask (fg_gc, NULL); - } - break; - - case GTK_CELL_PIXTEXT: - /* draw the pixmap */ - xsrc = 0; - ysrc = 0; - xdest = offset + clist_row->cell[i].horizontal; - ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - - height / 2 + clist_row->cell[i].vertical; - - if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask) - { - gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXTEXT - (clist_row->cell[i])->mask); - gdk_gc_set_clip_origin (fg_gc, xdest, ydest); - } - - if (xdest < clip_rectangle.x) - { - xsrc = clip_rectangle.x - xdest; - pixmap_width -= xsrc; - xdest = clip_rectangle.x; - } - - if (xdest + pixmap_width > - clip_rectangle.x + clip_rectangle.width) - pixmap_width = (clip_rectangle.x + clip_rectangle.width) - - xdest; - - if (ydest < clip_rectangle.y) - { - ysrc = clip_rectangle.y - ydest; - height -= ysrc; - ydest = clip_rectangle.y; - } - - if (ydest + height > clip_rectangle.y + clip_rectangle.height) - height = (clip_rectangle.y + clip_rectangle.height) - ydest; - - gdk_draw_pixmap (clist->clist_window, fg_gc, - GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap, - xsrc, ysrc, xdest, ydest, pixmap_width, height); - - gdk_gc_set_clip_origin (fg_gc, 0, 0); - - xdest += pixmap_width + GTK_CELL_PIXTEXT - (clist_row->cell[i])->spacing; + if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap) + offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing; + } - /* draw the string */ - gdk_gc_set_clip_rectangle (fg_gc, rect); - - gdk_draw_string (clist->clist_window, widget->style->font, fg_gc, - xdest, - row_rectangle.y + clist->row_center_offset + - clist_row->cell[i].vertical, - GTK_CELL_PIXTEXT (clist_row->cell[i])->text); - - gdk_gc_set_clip_rectangle (fg_gc, NULL); - - break; + gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle); + gdk_draw_layout (clist->clist_window, fg_gc, + offset, + row_rectangle.y + row_center_offset + clist_row->cell[i].vertical, + layout); - case GTK_CELL_WIDGET: - /* unimplemented */ - continue; - break; - - default: - continue; - break; - } + g_object_unref (G_OBJECT (layout)); } + gdk_gc_set_clip_rectangle (fg_gc, NULL); } - if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget)) + + /* draw focus rectangle */ + if (clist->focus_row == row && + GTK_WIDGET_CAN_FOCUS (widget) && GTK_WIDGET_HAS_FOCUS (widget)) { - if (area) - { - if (gdk_rectangle_intersect (area, &row_rectangle, - &intersect_rectangle)) - { - gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle); - gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, - row_rectangle.x, row_rectangle.y, - row_rectangle.width - 1, - row_rectangle.height - 1); - gdk_gc_set_clip_rectangle (clist->xor_gc, NULL); - } - } - else + if (!area) gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, row_rectangle.x, row_rectangle.y, row_rectangle.width - 1, row_rectangle.height - 1); + else if (gdk_rectangle_intersect (area, &row_rectangle, + &intersect_rectangle)) + { + gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle); + gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, + row_rectangle.x, row_rectangle.y, + row_rectangle.width - 1, + row_rectangle.height - 1); + gdk_gc_set_clip_rectangle (clist->xor_gc, NULL); + } } } @@ -2404,19 +2052,19 @@ tree_draw_node (GtkCTree *ctree, clist = GTK_CLIST (ctree); - if (!GTK_CLIST_FROZEN (clist) && gtk_ctree_is_visible (ctree, node)) + if (CLIST_UNFROZEN (clist) && gtk_ctree_is_viewable (ctree, node)) { GtkCTreeNode *work; gint num = 0; work = GTK_CTREE_NODE (clist->row_list); - while (work != node) + while (work && work != node) { work = GTK_CTREE_NODE_NEXT (work); num++; } - if (gtk_clist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE) - GTK_CLIST_CLASS_FW (clist)->draw_row + if (work && gtk_clist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE) + GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, num, GTK_CLIST_ROW ((GList *) node)); } } @@ -2449,21 +2097,23 @@ gtk_ctree_link (GtkCTree *ctree, gboolean update_focus_row) { GtkCList *clist; - GtkCTreeNode *list_end; + GList *list_end; + GList *list; + GList *work; gboolean visible = FALSE; gint rows = 0; - g_return_if_fail (!sibling || GTK_CTREE_ROW (sibling)->parent == parent); + if (sibling) + g_return_if_fail (GTK_CTREE_ROW (sibling)->parent == parent); g_return_if_fail (node != NULL); g_return_if_fail (node != sibling); g_return_if_fail (node != parent); clist = GTK_CLIST (ctree); - if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED) + if (update_focus_row && clist->selection_mode == GTK_SELECTION_MULTIPLE) { - if (clist->anchor != -1) - GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL); g_list_free (clist->undo_selection); g_list_free (clist->undo_unselection); @@ -2471,95 +2121,98 @@ gtk_ctree_link (GtkCTree *ctree, clist->undo_unselection = NULL; } - for (rows = 1, list_end = node; GTK_CTREE_NODE_NEXT (list_end); - list_end = GTK_CTREE_NODE_NEXT (list_end)) + for (rows = 1, list_end = (GList *)node; list_end->next; + list_end = list_end->next) rows++; GTK_CTREE_ROW (node)->parent = parent; GTK_CTREE_ROW (node)->sibling = sibling; - if (!parent || (parent && (gtk_ctree_is_visible (ctree, parent) && + if (!parent || (parent && (gtk_ctree_is_viewable (ctree, parent) && GTK_CTREE_ROW (parent)->expanded))) { visible = TRUE; clist->rows += rows; } - + + if (parent) + work = (GList *)(GTK_CTREE_ROW (parent)->children); + else + work = clist->row_list; if (sibling) { - GtkCTreeNode *work; - - if (parent) - work = GTK_CTREE_ROW (parent)->children; - else - work = GTK_CTREE_NODE (clist->row_list); - if (work != sibling) + if (work != (GList *)sibling) { while (GTK_CTREE_ROW (work)->sibling != sibling) - work = GTK_CTREE_ROW (work)->sibling; + work = (GList *)(GTK_CTREE_ROW (work)->sibling); GTK_CTREE_ROW (work)->sibling = node; } if (sibling == GTK_CTREE_NODE (clist->row_list)) - GTK_CTREE_NODE (clist->row_list) = node; + clist->row_list = (GList *) node; if (GTK_CTREE_NODE_PREV (sibling) && GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) == sibling) - GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) = node; + { + list = (GList *)GTK_CTREE_NODE_PREV (sibling); + list->next = (GList *)node; + } - GTK_CTREE_NODE_PREV (node) = GTK_CTREE_NODE_PREV (sibling); - GTK_CTREE_NODE_NEXT (list_end) = sibling; - GTK_CTREE_NODE_PREV (sibling) = list_end; + list = (GList *)node; + list->prev = (GList *)GTK_CTREE_NODE_PREV (sibling); + list_end->next = (GList *)sibling; + list = (GList *)sibling; + list->prev = list_end; if (parent && GTK_CTREE_ROW (parent)->children == sibling) GTK_CTREE_ROW (parent)->children = node; } else { - GtkCTreeNode *work; - - if (parent) - work = GTK_CTREE_ROW (parent)->children; - else - work = GTK_CTREE_NODE (clist->row_list); - if (work) { /* find sibling */ while (GTK_CTREE_ROW (work)->sibling) - work = GTK_CTREE_ROW (work)->sibling; + work = (GList *)(GTK_CTREE_ROW (work)->sibling); GTK_CTREE_ROW (work)->sibling = node; /* find last visible child of sibling */ - work = gtk_ctree_last_visible (ctree, work); + work = (GList *) gtk_ctree_last_visible (ctree, + GTK_CTREE_NODE (work)); - GTK_CTREE_NODE_NEXT (list_end) = GTK_CTREE_NODE_NEXT (work); - if (GTK_CTREE_NODE_NEXT (work)) - GTK_CTREE_NODE_PREV (GTK_CTREE_NODE_NEXT (work)) = list_end; - GTK_CTREE_NODE_NEXT (work) = node; - GTK_CTREE_NODE_PREV (node) = work; + list_end->next = work->next; + if (work->next) + list = work->next->prev = list_end; + work->next = (GList *)node; + list = (GList *)node; + list->prev = work; } else { if (parent) { GTK_CTREE_ROW (parent)->children = node; - GTK_CTREE_NODE_PREV (node) = parent; + list = (GList *)node; + list->prev = (GList *)parent; if (GTK_CTREE_ROW (parent)->expanded) { - GTK_CTREE_NODE_NEXT (list_end)= GTK_CTREE_NODE_NEXT (parent); + list_end->next = (GList *)GTK_CTREE_NODE_NEXT (parent); if (GTK_CTREE_NODE_NEXT(parent)) - GTK_CTREE_NODE_PREV (GTK_CTREE_NODE_NEXT (parent)) = - list_end; - GTK_CTREE_NODE_NEXT (parent) = node; + { + list = (GList *)GTK_CTREE_NODE_NEXT (parent); + list->prev = list_end; + } + list = (GList *)parent; + list->next = (GList *)node; } else - GTK_CTREE_NODE_NEXT (list_end) = NULL; + list_end->next = NULL; } else { - GTK_CTREE_NODE (clist->row_list) = node; - GTK_CTREE_NODE_PREV (node) = NULL; - GTK_CTREE_NODE_NEXT (list_end) = NULL; + clist->row_list = (GList *)node; + list = (GList *)node; + list->prev = NULL; + list_end->next = NULL; } } } @@ -2567,8 +2220,8 @@ gtk_ctree_link (GtkCTree *ctree, gtk_ctree_pre_recursive (ctree, node, tree_update_level, NULL); if (clist->row_list_end == NULL || - GTK_CTREE_NODE (clist->row_list_end->next) == node) - GTK_CTREE_NODE (clist->row_list_end) = list_end; + clist->row_list_end->next == (GList *)node) + clist->row_list_end = list_end; if (visible && update_focus_row) { @@ -2595,17 +2248,16 @@ gtk_ctree_unlink (GtkCTree *ctree, gint visible; GtkCTreeNode *work; GtkCTreeNode *parent; + GList *list; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); clist = GTK_CLIST (ctree); - if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED) + if (update_focus_row && clist->selection_mode == GTK_SELECTION_MULTIPLE) { - if (clist->anchor != -1) - GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL); g_list_free (clist->undo_selection); g_list_free (clist->undo_unselection); @@ -2613,7 +2265,7 @@ gtk_ctree_unlink (GtkCTree *ctree, clist->undo_unselection = NULL; } - visible = gtk_ctree_is_visible (ctree, node); + visible = gtk_ctree_is_viewable (ctree, node); /* clist->row_list_end unlinked ? */ if (visible && @@ -2621,7 +2273,7 @@ gtk_ctree_unlink (GtkCTree *ctree, (GTK_CTREE_ROW (node)->children && gtk_ctree_is_ancestor (ctree, node, GTK_CTREE_NODE (clist->row_list_end))))) - GTK_CTREE_NODE (clist->row_list_end) = GTK_CTREE_NODE_PREV (node); + clist->row_list_end = (GList *) (GTK_CTREE_NODE_PREV (node)); /* update list */ rows = 0; @@ -2642,23 +2294,35 @@ gtk_ctree_unlink (GtkCTree *ctree, gint pos; pos = g_list_position (clist->row_list, (GList *)node); - if (pos + rows + 1 < clist->focus_row) + if (pos + rows < clist->focus_row) clist->focus_row -= (rows + 1); else if (pos <= clist->focus_row) - clist->focus_row = pos - 1; + { + if (!GTK_CTREE_ROW (node)->sibling) + clist->focus_row = MAX (pos - 1, 0); + else + clist->focus_row = pos; + + clist->focus_row = MIN (clist->focus_row, clist->rows - 1); + } clist->undo_anchor = clist->focus_row; } } if (work) { - GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (work)) = NULL; - GTK_CTREE_NODE_PREV (work) = GTK_CTREE_NODE_PREV (node); + list = (GList *)GTK_CTREE_NODE_PREV (work); + list->next = NULL; + list = (GList *)work; + list->prev = (GList *)GTK_CTREE_NODE_PREV (node); } if (GTK_CTREE_NODE_PREV (node) && GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) == node) - GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) = work; + { + list = (GList *)GTK_CTREE_NODE_PREV (node); + list->next = (GList *)work; + } /* update tree */ parent = GTK_CTREE_ROW (node)->parent; @@ -2667,17 +2331,8 @@ gtk_ctree_unlink (GtkCTree *ctree, if (GTK_CTREE_ROW (parent)->children == node) { GTK_CTREE_ROW (parent)->children = GTK_CTREE_ROW (node)->sibling; - if (!GTK_CTREE_ROW (parent)->children && - GTK_CTREE_ROW (parent)->pixmap_closed) - { - GTK_CTREE_ROW (parent)->expanded = FALSE; - GTK_CELL_PIXTEXT - (GTK_CTREE_ROW(parent)->row.cell[ctree->tree_column])->pixmap = - GTK_CTREE_ROW (parent)->pixmap_closed; - GTK_CELL_PIXTEXT - (GTK_CTREE_ROW (parent)->row.cell[ctree->tree_column])->mask = - GTK_CTREE_ROW (parent)->mask_closed; - } + if (!GTK_CTREE_ROW (parent)->children) + gtk_ctree_collapse (ctree, parent); } else { @@ -2691,8 +2346,8 @@ gtk_ctree_unlink (GtkCTree *ctree, } else { - if (GTK_CTREE_NODE (clist->row_list) == node) - GTK_CTREE_NODE (clist->row_list) = GTK_CTREE_ROW (node)->sibling; + if (clist->row_list == (GList *)node) + clist->row_list = (GList *) (GTK_CTREE_ROW (node)->sibling); else { GtkCTreeNode *sibling; @@ -2705,6 +2360,55 @@ gtk_ctree_unlink (GtkCTree *ctree, } } +static void +real_row_move (GtkCList *clist, + gint source_row, + gint dest_row) +{ + GtkCTree *ctree; + GtkCTreeNode *node; + + g_return_if_fail (GTK_IS_CTREE (clist)); + + if (GTK_CLIST_AUTO_SORT (clist)) + return; + + if (source_row < 0 || source_row >= clist->rows || + dest_row < 0 || dest_row >= clist->rows || + source_row == dest_row) + return; + + ctree = GTK_CTREE (clist); + node = GTK_CTREE_NODE (g_list_nth (clist->row_list, source_row)); + + if (source_row < dest_row) + { + GtkCTreeNode *work; + + dest_row++; + work = GTK_CTREE_ROW (node)->children; + + while (work && GTK_CTREE_ROW (work)->level > GTK_CTREE_ROW (node)->level) + { + work = GTK_CTREE_NODE_NEXT (work); + dest_row++; + } + + if (dest_row > clist->rows) + dest_row = clist->rows; + } + + if (dest_row < clist->rows) + { + GtkCTreeNode *sibling; + + sibling = GTK_CTREE_NODE (g_list_nth (clist->row_list, dest_row)); + gtk_ctree_move (ctree, node, GTK_CTREE_ROW (sibling)->parent, sibling); + } + else + gtk_ctree_move (ctree, node, NULL, NULL); +} + static void real_tree_move (GtkCTree *ctree, GtkCTreeNode *node, @@ -2713,7 +2417,7 @@ real_tree_move (GtkCTree *ctree, { GtkCList *clist; GtkCTreeNode *work; - gboolean thaw = FALSE; + gboolean visible = FALSE; g_return_if_fail (ctree != NULL); g_return_if_fail (node != NULL); @@ -2730,10 +2434,11 @@ real_tree_move (GtkCTree *ctree, clist = GTK_CLIST (ctree); - if (clist->selection_mode == GTK_SELECTION_EXTENDED) + visible = gtk_ctree_is_viewable (ctree, node); + + if (clist->selection_mode == GTK_SELECTION_MULTIPLE) { - if (clist->anchor != -1) - GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL); g_list_free (clist->undo_selection); g_list_free (clist->undo_unselection); @@ -2741,7 +2446,7 @@ real_tree_move (GtkCTree *ctree, clist->undo_unselection = NULL; } - if (ctree->auto_sort) + if (GTK_CLIST_AUTO_SORT (clist)) { if (new_parent == GTK_CTREE_ROW (node)->parent) return; @@ -2751,7 +2456,8 @@ real_tree_move (GtkCTree *ctree, else new_sibling = GTK_CTREE_NODE (clist->row_list); - while (new_sibling && ctree->node_compare (ctree, node, new_sibling) > 0) + while (new_sibling && clist->compare + (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (new_sibling)) > 0) new_sibling = GTK_CTREE_ROW (new_sibling)->sibling; } @@ -2759,15 +2465,10 @@ real_tree_move (GtkCTree *ctree, new_sibling == GTK_CTREE_ROW (node)->sibling) return; - if (!GTK_CLIST_FROZEN (clist)) - { - gtk_clist_freeze (clist); - thaw = TRUE; - } + gtk_clist_freeze (clist); work = NULL; - if (gtk_ctree_is_visible (ctree, node) || - gtk_ctree_is_visible (ctree, new_sibling)) + if (gtk_ctree_is_viewable (ctree, node)) work = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row)); gtk_ctree_unlink (ctree, node, FALSE); @@ -2775,14 +2476,20 @@ real_tree_move (GtkCTree *ctree, if (work) { - while (work && !gtk_ctree_is_visible (ctree, work)) + while (work && !gtk_ctree_is_viewable (ctree, work)) work = GTK_CTREE_ROW (work)->parent; clist->focus_row = g_list_position (clist->row_list, (GList *)work); clist->undo_anchor = clist->focus_row; } - if (thaw) - gtk_clist_thaw (clist); + if (clist->column[ctree->tree_column].auto_resize && + !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) && + (visible || gtk_ctree_is_viewable (ctree, node))) + gtk_clist_set_column_width + (clist, ctree->tree_column, + gtk_clist_optimal_column_width (clist, ctree->tree_column)); + + gtk_clist_thaw (clist); } static void @@ -2792,7 +2499,6 @@ change_focus_row_expansion (GtkCTree *ctree, GtkCList *clist; GtkCTreeNode *node; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); clist = GTK_CLIST (ctree); @@ -2834,66 +2540,141 @@ real_tree_expand (GtkCTree *ctree, { GtkCList *clist; GtkCTreeNode *work; + GtkRequisition requisition; + gboolean visible; gint level; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); - if (!node || GTK_CTREE_ROW (node)->expanded) + if (!node || GTK_CTREE_ROW (node)->expanded || GTK_CTREE_ROW (node)->is_leaf) return; clist = GTK_CLIST (ctree); - if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0) - GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL); GTK_CTREE_ROW (node)->expanded = TRUE; level = GTK_CTREE_ROW (node)->level; + visible = gtk_ctree_is_viewable (ctree, node); + /* get cell width if tree_column is auto resized */ + if (visible && clist->column[ctree->tree_column].auto_resize && + !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + GTK_CLIST_GET_CLASS (clist)->cell_size_request + (clist, >K_CTREE_ROW (node)->row, ctree->tree_column, &requisition); + + /* unref/unset closed pixmap */ + if (GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap) + { + gdk_pixmap_unref + (GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap); + + GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL; + + if (GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask) + { + gdk_pixmap_unref + (GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask); + GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL; + } + } + + /* set/ref opened pixmap */ if (GTK_CTREE_ROW (node)->pixmap_opened) { GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = - GTK_CTREE_ROW (node)->pixmap_opened; - GTK_CELL_PIXTEXT - (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = - GTK_CTREE_ROW (node)->mask_opened; + gdk_pixmap_ref (GTK_CTREE_ROW (node)->pixmap_opened); + + if (GTK_CTREE_ROW (node)->mask_opened) + GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = + gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_opened); } + work = GTK_CTREE_ROW (node)->children; if (work) { - GtkCList *clist; + GList *list = (GList *)work; + gint *cell_width = NULL; gint tmp = 0; gint row; - - clist = GTK_CLIST (ctree); - - while (GTK_CTREE_NODE_NEXT (work)) + gint i; + + if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) { - work = GTK_CTREE_NODE_NEXT (work); - tmp++; + cell_width = g_new0 (gint, clist->columns); + if (clist->column[ctree->tree_column].auto_resize) + cell_width[ctree->tree_column] = requisition.width; + + while (work) + { + /* search maximum cell widths of auto_resize columns */ + for (i = 0; i < clist->columns; i++) + if (clist->column[i].auto_resize) + { + GTK_CLIST_GET_CLASS (clist)->cell_size_request + (clist, >K_CTREE_ROW (work)->row, i, &requisition); + cell_width[i] = MAX (requisition.width, cell_width[i]); + } + + list = (GList *)work; + work = GTK_CTREE_NODE_NEXT (work); + tmp++; + } } + else + while (work) + { + list = (GList *)work; + work = GTK_CTREE_NODE_NEXT (work); + tmp++; + } - GTK_CTREE_NODE_NEXT (work) = GTK_CTREE_NODE_NEXT (node); + list->next = (GList *)GTK_CTREE_NODE_NEXT (node); if (GTK_CTREE_NODE_NEXT (node)) - GTK_CTREE_NODE_PREV (GTK_CTREE_NODE_NEXT (node)) = work; + { + GList *tmp_list; + + tmp_list = (GList *)GTK_CTREE_NODE_NEXT (node); + tmp_list->prev = list; + } else - GTK_CTREE_NODE (clist->row_list_end) = work; + clist->row_list_end = list; - GTK_CTREE_NODE_NEXT (node) = GTK_CTREE_ROW (node)->children; - - if (gtk_ctree_is_visible (ctree, node)) + list = (GList *)node; + list->next = (GList *)(GTK_CTREE_ROW (node)->children); + + if (visible) { + /* resize auto_resize columns if needed */ + for (i = 0; i < clist->columns; i++) + if (clist->column[i].auto_resize && + cell_width[i] > clist->column[i].width) + gtk_clist_set_column_width (clist, i, cell_width[i]); + g_free (cell_width); + + /* update focus_row position */ row = g_list_position (clist->row_list, (GList *)node); if (row < clist->focus_row) - clist->focus_row += tmp + 1; - clist->rows += tmp + 1; - if (!GTK_CLIST_FROZEN (ctree)) - gtk_clist_thaw (clist); + clist->focus_row += tmp; + + clist->rows += tmp; + CLIST_REFRESH (clist); } } + else if (visible && clist->column[ctree->tree_column].auto_resize) + /* resize tree_column if needed */ + column_auto_resize (clist, >K_CTREE_ROW (node)->row, ctree->tree_column, + requisition.width); } static void @@ -2902,40 +2683,71 @@ real_tree_collapse (GtkCTree *ctree, { GtkCList *clist; GtkCTreeNode *work; + GtkRequisition requisition; + gboolean visible; gint level; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); - if (!node || !GTK_CTREE_ROW (node)->expanded) + if (!node || !GTK_CTREE_ROW (node)->expanded || + GTK_CTREE_ROW (node)->is_leaf) return; clist = GTK_CLIST (ctree); - if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0) - GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL); GTK_CTREE_ROW (node)->expanded = FALSE; level = GTK_CTREE_ROW (node)->level; + visible = gtk_ctree_is_viewable (ctree, node); + /* get cell width if tree_column is auto resized */ + if (visible && clist->column[ctree->tree_column].auto_resize && + !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + GTK_CLIST_GET_CLASS (clist)->cell_size_request + (clist, >K_CTREE_ROW (node)->row, ctree->tree_column, &requisition); + + /* unref/unset opened pixmap */ + if (GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap) + { + gdk_pixmap_unref + (GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap); + + GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL; + + if (GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask) + { + gdk_pixmap_unref + (GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask); + GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL; + } + } + + /* set/ref closed pixmap */ if (GTK_CTREE_ROW (node)->pixmap_closed) { GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = - GTK_CTREE_ROW (node)->pixmap_closed; - GTK_CELL_PIXTEXT - (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = - GTK_CTREE_ROW (node)->mask_closed; + gdk_pixmap_ref (GTK_CTREE_ROW (node)->pixmap_closed); + + if (GTK_CTREE_ROW (node)->mask_closed) + GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = + gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_closed); } work = GTK_CTREE_ROW (node)->children; if (work) { - GtkCList *clist; gint tmp = 0; gint row; - - clist = GTK_CLIST (ctree); + GList *list; while (work && GTK_CTREE_ROW (work)->level > level) { @@ -2945,85 +2757,319 @@ real_tree_collapse (GtkCTree *ctree, if (work) { - GTK_CTREE_NODE_NEXT (node) = work; - GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (work)) = NULL; - GTK_CTREE_NODE_PREV (work) = node; + list = (GList *)node; + list->next = (GList *)work; + list = (GList *)GTK_CTREE_NODE_PREV (work); + list->next = NULL; + list = (GList *)work; + list->prev = (GList *)node; } else { - GTK_CTREE_NODE_NEXT (node) = NULL; - GTK_CTREE_NODE (clist->row_list_end) = node; + list = (GList *)node; + list->next = NULL; + clist->row_list_end = (GList *)node; } - if (gtk_ctree_is_visible (ctree, node)) + if (visible) { + /* resize auto_resize columns if needed */ + auto_resize_columns (clist); + row = g_list_position (clist->row_list, (GList *)node); if (row < clist->focus_row) clist->focus_row -= tmp; clist->rows -= tmp; - if (!GTK_CLIST_FROZEN (ctree)) - gtk_clist_thaw (clist); + CLIST_REFRESH (clist); } } + else if (visible && clist->column[ctree->tree_column].auto_resize && + !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + /* resize tree_column if needed */ + column_auto_resize (clist, >K_CTREE_ROW (node)->row, ctree->tree_column, + requisition.width); + } static void -cell_set_text (GtkCList *clist, - GtkCListRow *clist_row, - gint column, - gchar *text) +column_auto_resize (GtkCList *clist, + GtkCListRow *clist_row, + gint column, + gint old_width) { - cell_empty (clist, clist_row, column); + /* resize column if needed for auto_resize */ + GtkRequisition requisition; - if (text) + if (!clist->column[column].auto_resize || + GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + return; + + if (clist_row) + GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row, + column, &requisition); + else + requisition.width = 0; + + if (requisition.width > clist->column[column].width) + gtk_clist_set_column_width (clist, column, requisition.width); + else if (requisition.width < old_width && + old_width == clist->column[column].width) { - clist_row->cell[column].type = GTK_CELL_TEXT; - GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text); + GList *list; + gint new_width; + + /* run a "gtk_clist_optimal_column_width" but break, if + * the column doesn't shrink */ + if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[column].button) + new_width = (clist->column[column].button->requisition.width - + (CELL_SPACING + (2 * COLUMN_INSET))); + else + new_width = 0; + + for (list = clist->row_list; list; list = list->next) + { + GTK_CLIST_GET_CLASS (clist)->cell_size_request + (clist, GTK_CLIST_ROW (list), column, &requisition); + new_width = MAX (new_width, requisition.width); + if (new_width == clist->column[column].width) + break; + } + if (new_width < clist->column[column].width) + gtk_clist_set_column_width (clist, column, new_width); } } static void -cell_set_pixmap (GtkCList *clist, - GtkCListRow *clist_row, - gint column, - GdkPixmap *pixmap, - GdkBitmap *mask) +auto_resize_columns (GtkCList *clist) { - cell_empty (clist, clist_row, column); + gint i; - if (pixmap) + if (GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + return; + + for (i = 0; i < clist->columns; i++) + column_auto_resize (clist, NULL, i, clist->column[i].width); +} + +static void +cell_size_request (GtkCList *clist, + GtkCListRow *clist_row, + gint column, + GtkRequisition *requisition) +{ + GtkCTree *ctree; + gint width; + gint height; + PangoLayout *layout; + PangoRectangle logical_rect; + + g_return_if_fail (GTK_IS_CTREE (clist)); + g_return_if_fail (requisition != NULL); + + ctree = GTK_CTREE (clist); + + layout = _gtk_clist_create_cell_layout (clist, clist_row, column); + if (layout) + { + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + + requisition->width = logical_rect.width; + requisition->height = logical_rect.height; + + g_object_unref (G_OBJECT (layout)); + } + else + { + requisition->width = 0; + requisition->height = 0; + } + + switch (clist_row->cell[column].type) { - clist_row->cell[column].type = GTK_CELL_PIXMAP; - GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap; - GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask; + case GTK_CELL_PIXTEXT: + if (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap) + { + gdk_window_get_size (GTK_CELL_PIXTEXT + (clist_row->cell[column])->pixmap, + &width, &height); + width += GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing; + } + else + width = height = 0; + + requisition->width += width; + requisition->height = MAX (requisition->height, height); + + if (column == ctree->tree_column) + { + requisition->width += (ctree->tree_spacing + ctree->tree_indent * + (((GtkCTreeRow *) clist_row)->level - 1)); + switch (ctree->expander_style) + { + case GTK_CTREE_EXPANDER_NONE: + break; + case GTK_CTREE_EXPANDER_TRIANGLE: + requisition->width += PM_SIZE + 3; + break; + case GTK_CTREE_EXPANDER_SQUARE: + case GTK_CTREE_EXPANDER_CIRCULAR: + requisition->width += PM_SIZE + 1; + break; + } + if (ctree->line_style == GTK_CTREE_LINES_TABBED) + requisition->width += 3; + } + break; + case GTK_CELL_PIXMAP: + gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap, + &width, &height); + requisition->width += width; + requisition->height = MAX (requisition->height, height); + break; + default: + requisition->width = 0; + requisition->height = 0; + break; } + + requisition->width += clist_row->cell[column].horizontal; + requisition->height += clist_row->cell[column].vertical; } static void -cell_set_pixtext (GtkCList *clist, - GtkCListRow *clist_row, - gint column, - gchar *text, - guint8 spacing, - GdkPixmap *pixmap, - GdkBitmap *mask) +set_cell_contents (GtkCList *clist, + GtkCListRow *clist_row, + gint column, + GtkCellType type, + const gchar *text, + guint8 spacing, + GdkPixmap *pixmap, + GdkBitmap *mask) { - cell_empty (clist, clist_row, column); + gboolean visible = FALSE; + GtkCTree *ctree; + GtkRequisition requisition; + gchar *old_text = NULL; + GdkPixmap *old_pixmap = NULL; + GdkBitmap *old_mask = NULL; + + g_return_if_fail (GTK_IS_CTREE (clist)); + g_return_if_fail (clist_row != NULL); + + ctree = GTK_CTREE (clist); + + if (clist->column[column].auto_resize && + !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + { + GtkCTreeNode *parent; + + parent = ((GtkCTreeRow *)clist_row)->parent; + if (!parent || (parent && GTK_CTREE_ROW (parent)->expanded && + gtk_ctree_is_viewable (ctree, parent))) + { + visible = TRUE; + GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row, + column, &requisition); + } + } + + switch (clist_row->cell[column].type) + { + case GTK_CELL_EMPTY: + break; + case GTK_CELL_TEXT: + old_text = GTK_CELL_TEXT (clist_row->cell[column])->text; + break; + case GTK_CELL_PIXMAP: + old_pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap; + old_mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask; + break; + case GTK_CELL_PIXTEXT: + old_text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text; + old_pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap; + old_mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask; + break; + case GTK_CELL_WIDGET: + /* unimplimented */ + break; + + default: + break; + } - if (text && pixmap) + clist_row->cell[column].type = GTK_CELL_EMPTY; + if (column == ctree->tree_column && type != GTK_CELL_EMPTY) + type = GTK_CELL_PIXTEXT; + + /* Note that pixmap and mask were already ref'ed by the caller + */ + switch (type) { - clist_row->cell[column].type = GTK_CELL_PIXTEXT; - GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text); - GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing; - GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap; - GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask; + case GTK_CELL_TEXT: + if (text) + { + clist_row->cell[column].type = GTK_CELL_TEXT; + GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text); + } + break; + case GTK_CELL_PIXMAP: + if (pixmap) + { + clist_row->cell[column].type = GTK_CELL_PIXMAP; + GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap; + /* We set the mask even if it is NULL */ + GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask; + } + break; + case GTK_CELL_PIXTEXT: + if (column == ctree->tree_column) + { + clist_row->cell[column].type = GTK_CELL_PIXTEXT; + GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing; + if (text) + GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text); + else + GTK_CELL_PIXTEXT (clist_row->cell[column])->text = NULL; + if (pixmap) + { + GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap; + GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask; + } + else + { + GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = NULL; + GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = NULL; + } + } + else if (text && pixmap) + { + clist_row->cell[column].type = GTK_CELL_PIXTEXT; + GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text); + GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing; + GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap; + GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask; + } + break; + default: + break; } + + if (visible && clist->column[column].auto_resize && + !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + column_auto_resize (clist, clist_row, column, requisition.width); + + if (old_text) + g_free (old_text); + if (old_pixmap) + gdk_pixmap_unref (old_pixmap); + if (old_mask) + gdk_pixmap_unref (old_mask); } static void set_node_info (GtkCTree *ctree, GtkCTreeNode *node, - gchar *text, + const gchar *text, guint8 spacing, GdkPixmap *pixmap_closed, GdkBitmap *mask_closed, @@ -3032,8 +3078,6 @@ set_node_info (GtkCTree *ctree, gboolean is_leaf, gboolean expanded) { - GtkCellPixText *tree_cell; - if (GTK_CTREE_ROW (node)->pixmap_opened) { gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_opened); @@ -3068,51 +3112,20 @@ set_node_info (GtkCTree *ctree, GTK_CTREE_ROW (node)->is_leaf = is_leaf; GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded; - GTK_CTREE_ROW (node)->row.cell[ctree->tree_column].type = GTK_CELL_PIXTEXT; - - tree_cell = GTK_CELL_PIXTEXT (GTK_CTREE_ROW - (node)->row.cell[ctree->tree_column]); - - if (tree_cell->text) - g_free (tree_cell->text); - - tree_cell->text = g_strdup (text); - tree_cell->spacing = spacing; - if (GTK_CTREE_ROW (node)->expanded) - { - tree_cell->pixmap = pixmap_opened; - tree_cell->mask = mask_opened; - } - else - { - tree_cell->pixmap = pixmap_closed; - tree_cell->mask = mask_closed; - } -} - -static void -tree_delete (GtkCTree *ctree, - GtkCTreeNode *node, - gpointer data) -{ - GtkCList *clist; - - clist = GTK_CLIST (ctree); - - if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED) - { - GList *work; - - work = g_list_find (clist->selection, node); - if (work) - { - if (clist->selection_end && clist->selection_end == work) - clist->selection_end = clist->selection_end->prev; - clist->selection = g_list_remove (clist->selection, node); - } - } + gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column, + text, spacing, pixmap_opened, mask_opened); + else + gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column, + text, spacing, pixmap_closed, mask_closed); +} +static void +tree_delete (GtkCTree *ctree, + GtkCTreeNode *node, + gpointer data) +{ + tree_unselect (ctree, node, NULL); row_delete (ctree, GTK_CTREE_ROW (node)); g_list_free_1 ((GList *)node); } @@ -3146,7 +3159,8 @@ tree_select (GtkCTree *ctree, GtkCTreeNode *node, gpointer data) { - if (node && GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED) + if (node && GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED && + GTK_CTREE_ROW (node)->row.selectable) gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], node, -1); } @@ -3218,15 +3232,18 @@ row_new (GtkCTree *ctree) ctree_row->row.cell[i].type = GTK_CELL_EMPTY; ctree_row->row.cell[i].vertical = 0; ctree_row->row.cell[i].horizontal = 0; + ctree_row->row.cell[i].style = NULL; } GTK_CELL_PIXTEXT (ctree_row->row.cell[ctree->tree_column])->text = NULL; - ctree_row->row.fg_set = FALSE; - ctree_row->row.bg_set = FALSE; - ctree_row->row.state = GTK_STATE_NORMAL; - ctree_row->row.data = NULL; - ctree_row->row.destroy = NULL; + ctree_row->row.fg_set = FALSE; + ctree_row->row.bg_set = FALSE; + ctree_row->row.style = NULL; + ctree_row->row.selectable = TRUE; + ctree_row->row.state = GTK_STATE_NORMAL; + ctree_row->row.data = NULL; + ctree_row->row.destroy = NULL; ctree_row->level = 0; ctree_row->expanded = FALSE; @@ -3251,7 +3268,23 @@ row_delete (GtkCTree *ctree, clist = GTK_CLIST (ctree); for (i = 0; i < clist->columns; i++) - cell_empty (clist, &(ctree_row->row), i); + { + GTK_CLIST_GET_CLASS (clist)->set_cell_contents + (clist, &(ctree_row->row), i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL); + if (ctree_row->row.cell[i].style) + { + if (GTK_WIDGET_REALIZED (ctree)) + gtk_style_detach (ctree_row->row.cell[i].style); + g_object_unref (ctree_row->row.cell[i].style); + } + } + + if (ctree_row->row.style) + { + if (GTK_WIDGET_REALIZED (ctree)) + gtk_style_detach (ctree_row->row.style); + g_object_unref (ctree_row->row.style); + } if (ctree_row->pixmap_closed) { @@ -3268,54 +3301,18 @@ row_delete (GtkCTree *ctree, } if (ctree_row->row.destroy) - ctree_row->row.destroy (ctree_row->row.data); - - g_mem_chunk_free (clist->cell_mem_chunk, ctree_row->row.cell); - g_mem_chunk_free (clist->row_mem_chunk, ctree_row); -} - -static void -cell_empty (GtkCList *clist, - GtkCListRow *clist_row, - gint column) -{ - switch (clist_row->cell[column].type) { - case GTK_CELL_EMPTY: - break; - - case GTK_CELL_TEXT: - g_free (GTK_CELL_TEXT (clist_row->cell[column])->text); - break; - - case GTK_CELL_PIXMAP: - gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap); - if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask) - gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask); - break; - - case GTK_CELL_PIXTEXT: - if (GTK_CTREE (clist)->tree_column == column) - { - if (GTK_CELL_PIXTEXT (clist_row->cell[column])->text) - g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text); - break; - } - g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text); - gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap); - if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask) - gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask); - break; + GtkDestroyNotify dnotify = ctree_row->row.destroy; + gpointer ddata = ctree_row->row.data; - case GTK_CELL_WIDGET: - /* unimplemented */ - break; - - default: - break; + ctree_row->row.destroy = NULL; + ctree_row->row.data = NULL; + + dnotify (ddata); } - clist_row->cell[column].type = GTK_CELL_EMPTY; + g_mem_chunk_free (clist->cell_mem_chunk, ctree_row->row.cell); + g_mem_chunk_free (clist->row_mem_chunk, ctree_row); } static void @@ -3326,10 +3323,10 @@ real_select_row (GtkCList *clist, { GList *node; - g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CTREE (clist)); - if ((node = g_list_nth (clist->row_list, row))) + if ((node = g_list_nth (clist->row_list, row)) && + GTK_CTREE_ROW (node)->row.selectable) gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_SELECT_ROW], node, column); } @@ -3342,7 +3339,6 @@ real_unselect_row (GtkCList *clist, { GList *node; - g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CTREE (clist)); if ((node = g_list_nth (clist->row_list, row))) @@ -3360,10 +3356,10 @@ real_tree_select (GtkCTree *ctree, GtkCTreeNode *sel_row; gboolean node_selected; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); - if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED) + if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED || + !GTK_CTREE_ROW (node)->row.selectable) return; clist = GTK_CLIST (ctree); @@ -3415,7 +3411,6 @@ real_tree_unselect (GtkCTree *ctree, { GtkCList *clist; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); if (!node || GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED) @@ -3433,47 +3428,13 @@ real_tree_unselect (GtkCTree *ctree, tree_draw_node (ctree, node); } -static void -tree_toggle_selection (GtkCTree *ctree, - GtkCTreeNode *node, - gint column) -{ - GtkCList *clist; - - g_return_if_fail (ctree != NULL); - g_return_if_fail (GTK_IS_CTREE (ctree)); - - clist = GTK_CLIST (ctree); - - switch (clist->selection_mode) - { - case GTK_SELECTION_SINGLE: - case GTK_SELECTION_MULTIPLE: - if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED) - gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW], - node, column); - else if (node) - gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], - node, column); - break; - - case GTK_SELECTION_BROWSE: - if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL) - gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], - node, column); - break; - - case GTK_SELECTION_EXTENDED: - break; - } -} - static void select_row_recursive (GtkCTree *ctree, GtkCTreeNode *node, gpointer data) { - if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED) + if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED || + !GTK_CTREE_ROW (node)->row.selectable) return; GTK_CLIST (ctree)->undo_unselection = @@ -3486,9 +3447,7 @@ real_select_all (GtkCList *clist) { GtkCTree *ctree; GtkCTreeNode *node; - gboolean thaw = FALSE; - g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CTREE (clist)); ctree = GTK_CTREE (clist); @@ -3499,13 +3458,9 @@ real_select_all (GtkCList *clist) case GTK_SELECTION_BROWSE: return; - case GTK_SELECTION_EXTENDED: + case GTK_SELECTION_MULTIPLE: - if (!GTK_CLIST_FROZEN (clist)) - { - gtk_clist_freeze (clist); - thaw = TRUE; - } + gtk_clist_freeze (clist); g_list_free (clist->undo_selection); g_list_free (clist->undo_unselection); @@ -3521,13 +3476,12 @@ real_select_all (GtkCList *clist) node = GTK_CTREE_NODE_NEXT (node)) gtk_ctree_pre_recursive (ctree, node, select_row_recursive, NULL); - if (thaw) - gtk_clist_thaw (clist); + gtk_clist_thaw (clist); break; - case GTK_SELECTION_MULTIPLE: - gtk_ctree_select_recursive (ctree, NULL); - break;; + default: + /* do nothing */ + break; } } @@ -3538,7 +3492,6 @@ real_unselect_all (GtkCList *clist) GtkCTreeNode *node; GList *list; - g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CTREE (clist)); ctree = GTK_CTREE (clist); @@ -3555,7 +3508,7 @@ real_unselect_all (GtkCList *clist) } break; - case GTK_SELECTION_EXTENDED: + case GTK_SELECTION_MULTIPLE: g_list_free (clist->undo_selection); g_list_free (clist->undo_unselection); clist->undo_selection = NULL; @@ -3593,52 +3546,35 @@ ctree_is_hot_spot (GtkCTree *ctree, gint xl; gint yu; - g_return_val_if_fail (ctree != NULL, FALSE); g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE); g_return_val_if_fail (node != NULL, FALSE); - tree_row = GTK_CTREE_ROW (node); clist = GTK_CLIST (ctree); - cell = GTK_CELL_PIXTEXT(tree_row->row.cell[ctree->tree_column]); + if (!clist->column[ctree->tree_column].visible || + ctree->expander_style == GTK_CTREE_EXPANDER_NONE) + return FALSE; + + tree_row = GTK_CTREE_ROW (node); + + cell = GTK_CELL_PIXTEXT (tree_row->row.cell[ctree->tree_column]); - yu = ROW_TOP_YPIXEL (clist, row) + (clist->row_height - PM_SIZE) / 2; + yu = (ROW_TOP_YPIXEL (clist, row) + (clist->row_height - PM_SIZE) / 2 - + (clist->row_height - 1) % 2); if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT) - { - xl = clist->column[ctree->tree_column].area.x - + clist->column[ctree->tree_column].area.width + clist->hoffset - /*+ cell->horizontal +*/ - - (tree_row->level - 1) * ctree->tree_indent - - PM_SIZE - 1 - - (ctree->line_style == GTK_CTREE_LINES_TABBED) * ((PM_SIZE / 2) + 1); - } + xl = (clist->column[ctree->tree_column].area.x + + clist->column[ctree->tree_column].area.width - 1 + clist->hoffset - + (tree_row->level - 1) * ctree->tree_indent - PM_SIZE - + (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3); else - { - xl = clist->column[ctree->tree_column].area.x + clist->hoffset - + cell->horizontal + (tree_row->level - 1) * ctree->tree_indent + - (ctree->line_style == GTK_CTREE_LINES_TABBED) * ((PM_SIZE / 2) + 2); - } + xl = (clist->column[ctree->tree_column].area.x + clist->hoffset + + (tree_row->level - 1) * ctree->tree_indent + + (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3); return (x >= xl && x <= xl + PM_SIZE && y >= yu && y <= yu + PM_SIZE); } -static gint -default_compare (GtkCTree *ctree, - const GtkCTreeNode *node1, - const GtkCTreeNode *node2) -{ - char *text1; - char *text2; - - text1 = GTK_CELL_PIXTEXT (GTK_CTREE_ROW - (node1)->row.cell[ctree->tree_column])->text; - text2 = GTK_CELL_PIXTEXT (GTK_CTREE_ROW - (node2)->row.cell[ctree->tree_column])->text; - return strcmp (text1, text2); -} - - /*********************************************************** *********************************************************** *** Public interface *** @@ -3650,49 +3586,42 @@ default_compare (GtkCTree *ctree, * Creation, insertion, deletion * ***********************************************************/ -void -gtk_ctree_construct (GtkCTree *ctree, - gint columns, - gint tree_column, - gchar *titles[]) +static GObject* +gtk_ctree_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) { - GtkCList *clist; - - g_return_if_fail (ctree != NULL); - g_return_if_fail (GTK_IS_CTREE (ctree)); - g_return_if_fail (GTK_CLIST_CONSTRUCTED (ctree) == FALSE); - - clist = GTK_CLIST (ctree); - - clist->row_mem_chunk = g_mem_chunk_new ("ctree row mem chunk", - sizeof (GtkCTreeRow), - sizeof (GtkCTreeRow) - * CLIST_OPTIMUM_SIZE, - G_ALLOC_AND_FREE); + GObject *object = G_OBJECT_CLASS (parent_class)->constructor (type, + n_construct_properties, + construct_properties); - clist->cell_mem_chunk = g_mem_chunk_new ("ctree cell mem chunk", - sizeof (GtkCell) * columns, - sizeof (GtkCell) * columns - * CLIST_OPTIMUM_SIZE, - G_ALLOC_AND_FREE); - - ctree->tree_column = tree_column; - - gtk_clist_construct (clist, columns, titles); + return object; } -GtkWidget * -gtk_ctree_new_with_titles (gint columns, - gint tree_column, - gchar *titles[]) +GtkWidget* +gtk_ctree_new_with_titles (gint columns, + gint tree_column, + gchar *titles[]) { GtkWidget *widget; g_return_val_if_fail (columns > 0, NULL); g_return_val_if_fail (tree_column >= 0 && tree_column < columns, NULL); - widget = gtk_type_new (GTK_TYPE_CTREE); - gtk_ctree_construct (GTK_CTREE (widget), columns, tree_column, titles); + widget = gtk_widget_new (GTK_TYPE_CTREE, + "n_columns", columns, + "tree_column", tree_column, + NULL); + if (titles) + { + GtkCList *clist = GTK_CLIST (widget); + guint i; + + for (i = 0; i < columns; i++) + gtk_clist_set_column_title (clist, i, titles[i]); + gtk_clist_column_titles_show (clist); + } + return widget; } @@ -3703,27 +3632,52 @@ gtk_ctree_new (gint columns, return gtk_ctree_new_with_titles (columns, tree_column, NULL); } +static gint +real_insert_row (GtkCList *clist, + gint row, + gchar *text[]) +{ + GtkCTreeNode *parent = NULL; + GtkCTreeNode *sibling; + GtkCTreeNode *node; + + g_return_val_if_fail (GTK_IS_CTREE (clist), -1); + + sibling = GTK_CTREE_NODE (g_list_nth (clist->row_list, row)); + if (sibling) + parent = GTK_CTREE_ROW (sibling)->parent; + + node = gtk_ctree_insert_node (GTK_CTREE (clist), parent, sibling, text, 5, + NULL, NULL, NULL, NULL, TRUE, FALSE); + + if (GTK_CLIST_AUTO_SORT (clist) || !sibling) + return g_list_position (clist->row_list, (GList *) node); + + return row; +} + GtkCTreeNode * -gtk_ctree_insert (GtkCTree *ctree, - GtkCTreeNode *parent, - GtkCTreeNode *sibling, - gchar *text[], - guint8 spacing, - GdkPixmap *pixmap_closed, - GdkBitmap *mask_closed, - GdkPixmap *pixmap_opened, - GdkBitmap *mask_opened, - gboolean is_leaf, - gboolean expanded) +gtk_ctree_insert_node (GtkCTree *ctree, + GtkCTreeNode *parent, + GtkCTreeNode *sibling, + gchar *text[], + guint8 spacing, + GdkPixmap *pixmap_closed, + GdkBitmap *mask_closed, + GdkPixmap *pixmap_opened, + GdkBitmap *mask_opened, + gboolean is_leaf, + gboolean expanded) { GtkCList *clist; GtkCTreeRow *new_row; GtkCTreeNode *node; + GList *list; gint i; - g_return_val_if_fail (ctree != NULL, NULL); - g_return_val_if_fail (!sibling || GTK_CTREE_ROW (sibling)->parent == parent, - NULL); + g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL); + if (sibling) + g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL); if (parent && GTK_CTREE_ROW (parent)->is_leaf) return NULL; @@ -3732,33 +3686,52 @@ gtk_ctree_insert (GtkCTree *ctree, /* create the row */ new_row = row_new (ctree); - node = GTK_CTREE_NODE (g_list_alloc ()); - GTK_CTREE_ROW (node) = new_row; + list = g_list_alloc (); + list->data = new_row; + node = GTK_CTREE_NODE (list); if (text) for (i = 0; i < clist->columns; i++) if (text[i] && i != ctree->tree_column) - cell_set_text (clist, &(new_row->row), i, text[i]); + GTK_CLIST_GET_CLASS (clist)->set_cell_contents + (clist, &(new_row->row), i, GTK_CELL_TEXT, text[i], 0, NULL, NULL); - set_node_info (ctree, node, text[ctree->tree_column], spacing, pixmap_closed, + set_node_info (ctree, node, text ? + text[ctree->tree_column] : NULL, spacing, pixmap_closed, mask_closed, pixmap_opened, mask_opened, is_leaf, expanded); /* sorted insertion */ - if (ctree->auto_sort) + if (GTK_CLIST_AUTO_SORT (clist)) { if (parent) sibling = GTK_CTREE_ROW (parent)->children; else sibling = GTK_CTREE_NODE (clist->row_list); - while (sibling && ctree->node_compare (ctree, node, sibling) > 0) + while (sibling && clist->compare + (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (sibling)) > 0) sibling = GTK_CTREE_ROW (sibling)->sibling; } gtk_ctree_link (ctree, node, parent, sibling, TRUE); - if (!GTK_CLIST_FROZEN (clist)) - gtk_clist_thaw (clist); + if (text && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) && + gtk_ctree_is_viewable (ctree, node)) + { + for (i = 0; i < clist->columns; i++) + if (clist->column[i].auto_resize) + column_auto_resize (clist, &(new_row->row), i, 0); + } + + if (clist->rows == 1) + { + clist->focus_row = 0; + if (clist->selection_mode == GTK_SELECTION_BROWSE) + gtk_ctree_select (ctree, node); + } + + + CLIST_REFRESH (clist); return node; } @@ -3771,48 +3744,49 @@ gtk_ctree_insert_gnode (GtkCTree *ctree, GtkCTreeGNodeFunc func, gpointer data) { + GtkCList *clist; GtkCTreeNode *cnode = NULL; GtkCTreeNode *child = NULL; GtkCTreeNode *new_child; - GtkCTreeRow *new_row; - gboolean thaw; + GList *list; GNode *work; guint depth = 1; - g_return_val_if_fail (ctree != NULL, NULL); + g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL); g_return_val_if_fail (gnode != NULL, NULL); g_return_val_if_fail (func != NULL, NULL); if (sibling) g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL); + clist = GTK_CLIST (ctree); + if (parent) depth = GTK_CTREE_ROW (parent)->level + 1; - if (!(new_row = row_new (ctree))) - return NULL; - if (!(cnode = GTK_CTREE_NODE (g_list_alloc ()))) - return NULL; - GTK_CTREE_ROW (cnode) = new_row; + list = g_list_alloc (); + list->data = row_new (ctree); + cnode = GTK_CTREE_NODE (list); + + gtk_clist_freeze (clist); set_node_info (ctree, cnode, "", 0, NULL, NULL, NULL, NULL, TRUE, FALSE); if (!func (ctree, depth, gnode, cnode, data)) { tree_delete_row (ctree, cnode, NULL); + gtk_clist_thaw (clist); return NULL; } - if ((thaw = !GTK_CLIST_FROZEN (GTK_CLIST (ctree)))) - gtk_clist_freeze (GTK_CLIST (ctree)); - - if (ctree->auto_sort) + if (GTK_CLIST_AUTO_SORT (clist)) { if (parent) sibling = GTK_CTREE_ROW (parent)->children; else - sibling = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list); + sibling = GTK_CTREE_NODE (clist->row_list); - while (sibling && ctree->node_compare (ctree, cnode, sibling) > 0) + while (sibling && clist->compare + (clist, GTK_CTREE_ROW (cnode), GTK_CTREE_ROW (sibling)) > 0) sibling = GTK_CTREE_ROW (sibling)->sibling; } @@ -3826,41 +3800,103 @@ gtk_ctree_insert_gnode (GtkCTree *ctree, child = new_child; } - if (thaw) - gtk_clist_thaw (GTK_CLIST (ctree)); + gtk_clist_thaw (clist); return cnode; } +GNode * +gtk_ctree_export_to_gnode (GtkCTree *ctree, + GNode *parent, + GNode *sibling, + GtkCTreeNode *node, + GtkCTreeGNodeFunc func, + gpointer data) +{ + GtkCTreeNode *work; + GNode *gnode; + gint depth; + + g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL); + g_return_val_if_fail (node != NULL, NULL); + g_return_val_if_fail (func != NULL, NULL); + if (sibling) + { + g_return_val_if_fail (parent != NULL, NULL); + g_return_val_if_fail (sibling->parent == parent, NULL); + } + + gnode = g_node_new (NULL); + depth = g_node_depth (parent) + 1; + + if (!func (ctree, depth, gnode, node, data)) + { + g_node_destroy (gnode); + return NULL; + } + + if (parent) + g_node_insert_before (parent, sibling, gnode); + + if (!GTK_CTREE_ROW (node)->is_leaf) + { + GNode *new_sibling = NULL; + + for (work = GTK_CTREE_ROW (node)->children; work; + work = GTK_CTREE_ROW (work)->sibling) + new_sibling = gtk_ctree_export_to_gnode (ctree, gnode, new_sibling, + work, func, data); + + g_node_reverse_children (gnode); + } + + return gnode; +} + +static void +real_remove_row (GtkCList *clist, + gint row) +{ + GtkCTreeNode *node; + + g_return_if_fail (GTK_IS_CTREE (clist)); + + node = GTK_CTREE_NODE (g_list_nth (clist->row_list, row)); + + if (node) + gtk_ctree_remove_node (GTK_CTREE (clist), node); +} + void -gtk_ctree_remove (GtkCTree *ctree, - GtkCTreeNode *node) +gtk_ctree_remove_node (GtkCTree *ctree, + GtkCTreeNode *node) { GtkCList *clist; - gboolean thaw = FALSE; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); clist = GTK_CLIST (ctree); - if (!GTK_CLIST_FROZEN (clist)) - { - gtk_clist_freeze (clist); - thaw = TRUE; - } + gtk_clist_freeze (clist); if (node) { + gboolean visible; + + visible = gtk_ctree_is_viewable (ctree, node); gtk_ctree_unlink (ctree, node, TRUE); gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_delete), NULL); + if (clist->selection_mode == GTK_SELECTION_BROWSE && !clist->selection && + clist->focus_row >= 0) + gtk_clist_select_row (clist, clist->focus_row, -1); + + auto_resize_columns (clist); } else gtk_clist_clear (clist); - if (thaw) - gtk_clist_thaw (clist); + gtk_clist_thaw (clist); } static void @@ -3870,23 +3906,16 @@ real_clear (GtkCList *clist) GtkCTreeNode *work; GtkCTreeNode *ptr; - g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CTREE (clist)); ctree = GTK_CTREE (clist); - ctree->drag_row = -1; - ctree->drag_rect = FALSE; - ctree->in_drag = FALSE; - ctree->drag_source = NULL; - ctree->drag_target = NULL; - ctree->drag_icon = NULL; - - /* remove all the rows */ + /* remove all rows */ work = GTK_CTREE_NODE (clist->row_list); clist->row_list = NULL; clist->row_list_end = NULL; + GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED); while (work) { ptr = work; @@ -3894,8 +3923,9 @@ real_clear (GtkCList *clist) gtk_ctree_post_recursive (ctree, ptr, GTK_CTREE_FUNC (tree_delete_row), NULL); } + GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED); - (parent_class->clear) (clist); + parent_class->clear (clist); } @@ -3914,7 +3944,6 @@ gtk_ctree_post_recursive (GtkCTree *ctree, GtkCTreeNode *work; GtkCTreeNode *tmp; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (func != NULL); @@ -3944,7 +3973,6 @@ gtk_ctree_post_recursive_to_depth (GtkCTree *ctree, GtkCTreeNode *work; GtkCTreeNode *tmp; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (func != NULL); @@ -3982,7 +4010,6 @@ gtk_ctree_pre_recursive (GtkCTree *ctree, GtkCTreeNode *work; GtkCTreeNode *tmp; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (func != NULL); @@ -4012,7 +4039,6 @@ gtk_ctree_pre_recursive_to_depth (GtkCTree *ctree, GtkCTreeNode *work; GtkCTreeNode *tmp; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (func != NULL); @@ -4043,12 +4069,11 @@ gtk_ctree_pre_recursive_to_depth (GtkCTree *ctree, } gboolean -gtk_ctree_is_visible (GtkCTree *ctree, - GtkCTreeNode *node) +gtk_ctree_is_viewable (GtkCTree *ctree, + GtkCTreeNode *node) { GtkCTreeRow *work; - g_return_val_if_fail (ctree != NULL, FALSE); g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE); g_return_val_if_fail (node != NULL, FALSE); @@ -4067,7 +4092,6 @@ GtkCTreeNode * gtk_ctree_last (GtkCTree *ctree, GtkCTreeNode *node) { - g_return_val_if_fail (ctree != NULL, NULL); g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL); if (!node) @@ -4083,17 +4107,16 @@ gtk_ctree_last (GtkCTree *ctree, } GtkCTreeNode * -gtk_ctree_find_glist_ptr (GtkCTree *ctree, - GtkCTreeRow *ctree_row) +gtk_ctree_find_node_ptr (GtkCTree *ctree, + GtkCTreeRow *ctree_row) { GtkCTreeNode *node; - g_return_val_if_fail (ctree != NULL, FALSE); g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE); g_return_val_if_fail (ctree_row != NULL, FALSE); if (ctree_row->parent) - node = GTK_CTREE_ROW(ctree_row->parent)->children; + node = GTK_CTREE_ROW (ctree_row->parent)->children; else node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list); @@ -4103,6 +4126,18 @@ gtk_ctree_find_glist_ptr (GtkCTree *ctree, return node; } +GtkCTreeNode * +gtk_ctree_node_nth (GtkCTree *ctree, + guint row) +{ + g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL); + + if ((row < 0) || (row >= GTK_CLIST(ctree)->rows)) + return NULL; + + return GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list, row)); +} + gboolean gtk_ctree_find (GtkCTree *ctree, GtkCTreeNode *node, @@ -4133,9 +4168,13 @@ gtk_ctree_is_ancestor (GtkCTree *ctree, GtkCTreeNode *node, GtkCTreeNode *child) { + g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE); g_return_val_if_fail (node != NULL, FALSE); - return gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child); + if (GTK_CTREE_ROW (node)->children) + return gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child); + + return FALSE; } GtkCTreeNode * @@ -4161,6 +4200,39 @@ gtk_ctree_find_by_row_data (GtkCTree *ctree, return NULL; } +GList * +gtk_ctree_find_all_by_row_data (GtkCTree *ctree, + GtkCTreeNode *node, + gpointer data) +{ + GList *list = NULL; + + g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL); + + /* if node == NULL then look in the whole tree */ + if (!node) + node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list); + + while (node) + { + if (GTK_CTREE_ROW (node)->row.data == data) + list = g_list_append (list, node); + + if (GTK_CTREE_ROW (node)->children) + { + GList *sub_list; + + sub_list = gtk_ctree_find_all_by_row_data (ctree, + GTK_CTREE_ROW + (node)->children, + data); + list = g_list_concat (list, sub_list); + } + node = GTK_CTREE_ROW (node)->sibling; + } + return list; +} + GtkCTreeNode * gtk_ctree_find_by_row_data_custom (GtkCTree *ctree, GtkCTreeNode *node, @@ -4187,6 +4259,42 @@ gtk_ctree_find_by_row_data_custom (GtkCTree *ctree, return NULL; } +GList * +gtk_ctree_find_all_by_row_data_custom (GtkCTree *ctree, + GtkCTreeNode *node, + gpointer data, + GCompareFunc func) +{ + GList *list = NULL; + + g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL); + g_return_val_if_fail (func != NULL, NULL); + + /* if node == NULL then look in the whole tree */ + if (!node) + node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list); + + while (node) + { + if (!func (GTK_CTREE_ROW (node)->row.data, data)) + list = g_list_append (list, node); + + if (GTK_CTREE_ROW (node)->children) + { + GList *sub_list; + + sub_list = gtk_ctree_find_all_by_row_data_custom (ctree, + GTK_CTREE_ROW + (node)->children, + data, + func); + list = g_list_concat (list, sub_list); + } + node = GTK_CTREE_ROW (node)->sibling; + } + return list; +} + gboolean gtk_ctree_is_hot_spot (GtkCTree *ctree, gint x, @@ -4196,7 +4304,6 @@ gtk_ctree_is_hot_spot (GtkCTree *ctree, gint column; gint row; - g_return_val_if_fail (ctree != NULL, FALSE); g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE); if (gtk_clist_get_selection_info (GTK_CLIST (ctree), x, y, &row, &column)) @@ -4218,7 +4325,6 @@ gtk_ctree_move (GtkCTree *ctree, GtkCTreeNode *new_parent, GtkCTreeNode *new_sibling) { - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); @@ -4230,7 +4336,6 @@ void gtk_ctree_expand (GtkCTree *ctree, GtkCTreeNode *node) { - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); @@ -4247,7 +4352,6 @@ gtk_ctree_expand_recursive (GtkCTree *ctree, GtkCList *clist; gboolean thaw = FALSE; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); clist = GTK_CLIST (ctree); @@ -4255,8 +4359,7 @@ gtk_ctree_expand_recursive (GtkCTree *ctree, if (node && GTK_CTREE_ROW (node)->is_leaf) return; - if (((node && gtk_ctree_is_visible (ctree, node)) || !node) && - !GTK_CLIST_FROZEN (clist)) + if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node))) { gtk_clist_freeze (clist); thaw = TRUE; @@ -4276,7 +4379,6 @@ gtk_ctree_expand_to_depth (GtkCTree *ctree, GtkCList *clist; gboolean thaw = FALSE; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); clist = GTK_CLIST (ctree); @@ -4284,8 +4386,7 @@ gtk_ctree_expand_to_depth (GtkCTree *ctree, if (node && GTK_CTREE_ROW (node)->is_leaf) return; - if (((node && gtk_ctree_is_visible (ctree, node)) || !node) && - !GTK_CLIST_FROZEN (clist)) + if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node))) { gtk_clist_freeze (clist); thaw = TRUE; @@ -4302,7 +4403,6 @@ void gtk_ctree_collapse (GtkCTree *ctree, GtkCTreeNode *node) { - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); @@ -4318,8 +4418,8 @@ gtk_ctree_collapse_recursive (GtkCTree *ctree, { GtkCList *clist; gboolean thaw = FALSE; + gint i; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); if (node && GTK_CTREE_ROW (node)->is_leaf) @@ -4327,14 +4427,19 @@ gtk_ctree_collapse_recursive (GtkCTree *ctree, clist = GTK_CLIST (ctree); - if (((node && gtk_ctree_is_visible (ctree, node)) || !node) && - !GTK_CLIST_FROZEN (clist)) + if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node))) { gtk_clist_freeze (clist); thaw = TRUE; } + GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED); gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_collapse), NULL); + GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED); + for (i = 0; i < clist->columns; i++) + if (clist->column[i].auto_resize) + gtk_clist_set_column_width (clist, i, + gtk_clist_optimal_column_width (clist, i)); if (thaw) gtk_clist_thaw (clist); @@ -4347,8 +4452,8 @@ gtk_ctree_collapse_to_depth (GtkCTree *ctree, { GtkCList *clist; gboolean thaw = FALSE; + gint i; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); if (node && GTK_CTREE_ROW (node)->is_leaf) @@ -4356,16 +4461,21 @@ gtk_ctree_collapse_to_depth (GtkCTree *ctree, clist = GTK_CLIST (ctree); - if (((node && gtk_ctree_is_visible (ctree, node)) || !node) && - !GTK_CLIST_FROZEN (clist)) + if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node))) { gtk_clist_freeze (clist); thaw = TRUE; } + GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED); gtk_ctree_post_recursive_to_depth (ctree, node, depth, GTK_CTREE_FUNC (tree_collapse_to_depth), GINT_TO_POINTER (depth)); + GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED); + for (i = 0; i < clist->columns; i++) + if (clist->column[i].auto_resize) + gtk_clist_set_column_width (clist, i, + gtk_clist_optimal_column_width (clist, i)); if (thaw) gtk_clist_thaw (clist); @@ -4375,7 +4485,6 @@ void gtk_ctree_toggle_expansion (GtkCTree *ctree, GtkCTreeNode *node) { - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); @@ -4392,7 +4501,6 @@ gtk_ctree_toggle_expansion_recursive (GtkCTree *ctree, GtkCList *clist; gboolean thaw = FALSE; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); if (node && GTK_CTREE_ROW (node)->is_leaf) @@ -4400,8 +4508,7 @@ gtk_ctree_toggle_expansion_recursive (GtkCTree *ctree, clist = GTK_CLIST (ctree); - if (((node && gtk_ctree_is_visible (ctree, node)) || !node) && - !GTK_CLIST_FROZEN (clist)) + if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node))) { gtk_clist_freeze (clist); thaw = TRUE; @@ -4418,19 +4525,18 @@ void gtk_ctree_select (GtkCTree *ctree, GtkCTreeNode *node) { - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); - gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], - node, -1); + if (GTK_CTREE_ROW (node)->row.selectable) + gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], + node, -1); } void gtk_ctree_unselect (GtkCTree *ctree, GtkCTreeNode *node) { - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); @@ -4460,7 +4566,6 @@ gtk_ctree_real_select_recursive (GtkCTree *ctree, GtkCList *clist; gboolean thaw = FALSE; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); clist = GTK_CLIST (ctree); @@ -4471,17 +4576,15 @@ gtk_ctree_real_select_recursive (GtkCTree *ctree, (!state && clist->selection_mode == GTK_SELECTION_BROWSE)) return; - if (((node && gtk_ctree_is_visible (ctree, node)) || !node) && - !GTK_CLIST_FROZEN (clist)) + if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node))) { gtk_clist_freeze (clist); thaw = TRUE; } - if (clist->selection_mode == GTK_SELECTION_EXTENDED) + if (clist->selection_mode == GTK_SELECTION_MULTIPLE) { - if (clist->anchor != -1) - GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL); g_list_free (clist->undo_selection); g_list_free (clist->undo_unselection); @@ -4507,35 +4610,40 @@ gtk_ctree_real_select_recursive (GtkCTree *ctree, void -gtk_ctree_set_text (GtkCTree *ctree, - GtkCTreeNode *node, - gint column, - gchar *text) +gtk_ctree_node_set_text (GtkCTree *ctree, + GtkCTreeNode *node, + gint column, + const gchar *text) { - g_return_if_fail (ctree != NULL); + GtkCList *clist; + g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); - g_return_if_fail (ctree->tree_column != column); if (column < 0 || column >= GTK_CLIST (ctree)->columns) return; + + clist = GTK_CLIST (ctree); + + GTK_CLIST_GET_CLASS (clist)->set_cell_contents + (clist, &(GTK_CTREE_ROW (node)->row), column, GTK_CELL_TEXT, + text, 0, NULL, NULL); - cell_set_text (GTK_CLIST (ctree), &(GTK_CTREE_ROW(node)->row), column, text); tree_draw_node (ctree, node); } void -gtk_ctree_set_pixmap (GtkCTree *ctree, - GtkCTreeNode *node, - gint column, - GdkPixmap *pixmap, - GdkBitmap *mask) +gtk_ctree_node_set_pixmap (GtkCTree *ctree, + GtkCTreeNode *node, + gint column, + GdkPixmap *pixmap, + GdkBitmap *mask) { - g_return_if_fail (ctree != NULL); + GtkCList *clist; + g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); g_return_if_fail (pixmap != NULL); - g_return_if_fail (ctree->tree_column != column); if (column < 0 || column >= GTK_CLIST (ctree)->columns) return; @@ -4544,42 +4652,53 @@ gtk_ctree_set_pixmap (GtkCTree *ctree, if (mask) gdk_pixmap_ref (mask); - cell_set_pixmap (GTK_CLIST (ctree), &(GTK_CTREE_ROW (node)->row), column, - pixmap, mask); + clist = GTK_CLIST (ctree); + + GTK_CLIST_GET_CLASS (clist)->set_cell_contents + (clist, &(GTK_CTREE_ROW (node)->row), column, GTK_CELL_PIXMAP, + NULL, 0, pixmap, mask); + tree_draw_node (ctree, node); } void -gtk_ctree_set_pixtext (GtkCTree *ctree, - GtkCTreeNode *node, - gint column, - gchar *text, - guint8 spacing, - GdkPixmap *pixmap, - GdkBitmap *mask) +gtk_ctree_node_set_pixtext (GtkCTree *ctree, + GtkCTreeNode *node, + gint column, + const gchar *text, + guint8 spacing, + GdkPixmap *pixmap, + GdkBitmap *mask) { - g_return_if_fail (ctree != NULL); + GtkCList *clist; + g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); - g_return_if_fail (pixmap != NULL); - g_return_if_fail (ctree->tree_column != column); - + if (column != ctree->tree_column) + g_return_if_fail (pixmap != NULL); if (column < 0 || column >= GTK_CLIST (ctree)->columns) return; - gdk_pixmap_ref (pixmap); - if (mask) - gdk_pixmap_ref (mask); + clist = GTK_CLIST (ctree); + + if (pixmap) + { + gdk_pixmap_ref (pixmap); + if (mask) + gdk_pixmap_ref (mask); + } + + GTK_CLIST_GET_CLASS (clist)->set_cell_contents + (clist, &(GTK_CTREE_ROW (node)->row), column, GTK_CELL_PIXTEXT, + text, spacing, pixmap, mask); - cell_set_pixtext (GTK_CLIST (ctree), &(GTK_CTREE_ROW (node)->row), column, - text, spacing, pixmap, mask); tree_draw_node (ctree, node); } void gtk_ctree_set_node_info (GtkCTree *ctree, GtkCTreeNode *node, - gchar *text, + const gchar *text, guint8 spacing, GdkPixmap *pixmap_closed, GdkBitmap *mask_closed, @@ -4591,7 +4710,6 @@ gtk_ctree_set_node_info (GtkCTree *ctree, gboolean old_leaf; gboolean old_expanded; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); @@ -4607,8 +4725,8 @@ gtk_ctree_set_node_info (GtkCTree *ctree, while (work) { ptr = work; - work = GTK_CTREE_ROW(work)->sibling; - gtk_ctree_remove (ctree, ptr); + work = GTK_CTREE_ROW (work)->sibling; + gtk_ctree_remove_node (ctree, ptr); } } @@ -4630,31 +4748,110 @@ gtk_ctree_set_node_info (GtkCTree *ctree, } void -gtk_ctree_set_shift (GtkCTree *ctree, - GtkCTreeNode *node, - gint column, - gint vertical, - gint horizontal) +gtk_ctree_node_set_shift (GtkCTree *ctree, + GtkCTreeNode *node, + gint column, + gint vertical, + gint horizontal) { - g_return_if_fail (ctree != NULL); + GtkCList *clist; + GtkRequisition requisition; + gboolean visible = FALSE; + g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); if (column < 0 || column >= GTK_CLIST (ctree)->columns) return; + clist = GTK_CLIST (ctree); + + if (clist->column[column].auto_resize && + !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + { + visible = gtk_ctree_is_viewable (ctree, node); + if (visible) + GTK_CLIST_GET_CLASS (clist)->cell_size_request + (clist, >K_CTREE_ROW (node)->row, column, &requisition); + } + GTK_CTREE_ROW (node)->row.cell[column].vertical = vertical; GTK_CTREE_ROW (node)->row.cell[column].horizontal = horizontal; + if (visible) + column_auto_resize (clist, >K_CTREE_ROW (node)->row, + column, requisition.width); + tree_draw_node (ctree, node); } +static void +remove_grab (GtkCList *clist) +{ + if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) + { + gtk_grab_remove (GTK_WIDGET (clist)); + gdk_pointer_ungrab (GDK_CURRENT_TIME); + } + + if (clist->htimer) + { + gtk_timeout_remove (clist->htimer); + clist->htimer = 0; + } + + if (clist->vtimer) + { + gtk_timeout_remove (clist->vtimer); + clist->vtimer = 0; + } +} + +void +gtk_ctree_node_set_selectable (GtkCTree *ctree, + GtkCTreeNode *node, + gboolean selectable) +{ + g_return_if_fail (GTK_IS_CTREE (ctree)); + g_return_if_fail (node != NULL); + + if (selectable == GTK_CTREE_ROW (node)->row.selectable) + return; + + GTK_CTREE_ROW (node)->row.selectable = selectable; + + if (!selectable && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED) + { + GtkCList *clist; + + clist = GTK_CLIST (ctree); + + if (clist->anchor >= 0 && + clist->selection_mode == GTK_SELECTION_MULTIPLE) + { + clist->drag_button = 0; + remove_grab (clist); + + GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL); + } + gtk_ctree_unselect (ctree, node); + } +} + +gboolean +gtk_ctree_node_get_selectable (GtkCTree *ctree, + GtkCTreeNode *node) +{ + g_return_val_if_fail (node != NULL, FALSE); + + return GTK_CTREE_ROW (node)->row.selectable; +} + GtkCellType -gtk_ctree_get_cell_type (GtkCTree *ctree, - GtkCTreeNode *node, - gint column) +gtk_ctree_node_get_cell_type (GtkCTree *ctree, + GtkCTreeNode *node, + gint column) { - g_return_val_if_fail (ctree != NULL, -1); g_return_val_if_fail (GTK_IS_CTREE (ctree), -1); g_return_val_if_fail (node != NULL, -1); @@ -4664,71 +4861,68 @@ gtk_ctree_get_cell_type (GtkCTree *ctree, return GTK_CTREE_ROW (node)->row.cell[column].type; } -gint -gtk_ctree_get_text (GtkCTree *ctree, - GtkCTreeNode *node, - gint column, - gchar **text) +gboolean +gtk_ctree_node_get_text (GtkCTree *ctree, + GtkCTreeNode *node, + gint column, + gchar **text) { - g_return_val_if_fail (ctree != NULL, 0); - g_return_val_if_fail (GTK_IS_CTREE (ctree), 0); - g_return_val_if_fail (node != NULL, 0); + g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE); + g_return_val_if_fail (node != NULL, FALSE); if (column < 0 || column >= GTK_CLIST (ctree)->columns) - return 0; + return FALSE; if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_TEXT) - return 0; + return FALSE; if (text) *text = GTK_CELL_TEXT (GTK_CTREE_ROW (node)->row.cell[column])->text; - return 1; + return TRUE; } -gint -gtk_ctree_get_pixmap (GtkCTree *ctree, - GtkCTreeNode *node, - gint column, - GdkPixmap **pixmap, - GdkBitmap **mask) +gboolean +gtk_ctree_node_get_pixmap (GtkCTree *ctree, + GtkCTreeNode *node, + gint column, + GdkPixmap **pixmap, + GdkBitmap **mask) { - g_return_val_if_fail (ctree != NULL, 0); - g_return_val_if_fail (GTK_IS_CTREE (ctree), 0); - g_return_val_if_fail (node != NULL, 0); + g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE); + g_return_val_if_fail (node != NULL, FALSE); if (column < 0 || column >= GTK_CLIST (ctree)->columns) - return 0; + return FALSE; if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXMAP) - return 0; + return FALSE; if (pixmap) - *pixmap = GTK_CELL_PIXMAP (GTK_CTREE_ROW(node)->row.cell[column])->pixmap; + *pixmap = GTK_CELL_PIXMAP (GTK_CTREE_ROW (node)->row.cell[column])->pixmap; if (mask) *mask = GTK_CELL_PIXMAP (GTK_CTREE_ROW (node)->row.cell[column])->mask; - return 1; + return TRUE; } -gint -gtk_ctree_get_pixtext (GtkCTree *ctree, - GtkCTreeNode *node, - gint column, - gchar **text, - guint8 *spacing, - GdkPixmap **pixmap, - GdkBitmap **mask) +gboolean +gtk_ctree_node_get_pixtext (GtkCTree *ctree, + GtkCTreeNode *node, + gint column, + gchar **text, + guint8 *spacing, + GdkPixmap **pixmap, + GdkBitmap **mask) { - g_return_val_if_fail (ctree != NULL, 0); - g_return_val_if_fail (GTK_IS_CTREE (ctree), 0); - g_return_val_if_fail (node != NULL, 0); + g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE); + g_return_val_if_fail (node != NULL, FALSE); if (column < 0 || column >= GTK_CLIST (ctree)->columns) - return 0; + return FALSE; if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXTEXT) - return 0; + return FALSE; if (text) *text = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->text; @@ -4741,10 +4935,10 @@ gtk_ctree_get_pixtext (GtkCTree *ctree, if (mask) *mask = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->mask; - return 1; + return TRUE; } -gint +gboolean gtk_ctree_get_node_info (GtkCTree *ctree, GtkCTreeNode *node, gchar **text, @@ -4756,9 +4950,8 @@ gtk_ctree_get_node_info (GtkCTree *ctree, gboolean *is_leaf, gboolean *expanded) { - g_return_val_if_fail (ctree != NULL, 0); - g_return_val_if_fail (GTK_IS_CTREE (ctree), 0); - g_return_val_if_fail (node != NULL, 0); + g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE); + g_return_val_if_fail (node != NULL, FALSE); if (text) *text = GTK_CELL_PIXTEXT @@ -4779,15 +4972,156 @@ gtk_ctree_get_node_info (GtkCTree *ctree, if (expanded) *expanded = GTK_CTREE_ROW (node)->expanded; - return 1; + return TRUE; } void -gtk_ctree_set_foreground (GtkCTree *ctree, - GtkCTreeNode *node, - GdkColor *color) +gtk_ctree_node_set_cell_style (GtkCTree *ctree, + GtkCTreeNode *node, + gint column, + GtkStyle *style) +{ + GtkCList *clist; + GtkRequisition requisition; + gboolean visible = FALSE; + + g_return_if_fail (GTK_IS_CTREE (ctree)); + g_return_if_fail (node != NULL); + + clist = GTK_CLIST (ctree); + + if (column < 0 || column >= clist->columns) + return; + + if (GTK_CTREE_ROW (node)->row.cell[column].style == style) + return; + + if (clist->column[column].auto_resize && + !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + { + visible = gtk_ctree_is_viewable (ctree, node); + if (visible) + GTK_CLIST_GET_CLASS (clist)->cell_size_request + (clist, >K_CTREE_ROW (node)->row, column, &requisition); + } + + if (GTK_CTREE_ROW (node)->row.cell[column].style) + { + if (GTK_WIDGET_REALIZED (ctree)) + gtk_style_detach (GTK_CTREE_ROW (node)->row.cell[column].style); + g_object_unref (GTK_CTREE_ROW (node)->row.cell[column].style); + } + + GTK_CTREE_ROW (node)->row.cell[column].style = style; + + if (GTK_CTREE_ROW (node)->row.cell[column].style) + { + g_object_ref (GTK_CTREE_ROW (node)->row.cell[column].style); + + if (GTK_WIDGET_REALIZED (ctree)) + GTK_CTREE_ROW (node)->row.cell[column].style = + gtk_style_attach (GTK_CTREE_ROW (node)->row.cell[column].style, + clist->clist_window); + } + + if (visible) + column_auto_resize (clist, >K_CTREE_ROW (node)->row, column, + requisition.width); + + tree_draw_node (ctree, node); +} + +GtkStyle * +gtk_ctree_node_get_cell_style (GtkCTree *ctree, + GtkCTreeNode *node, + gint column) +{ + g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL); + g_return_val_if_fail (node != NULL, NULL); + + if (column < 0 || column >= GTK_CLIST (ctree)->columns) + return NULL; + + return GTK_CTREE_ROW (node)->row.cell[column].style; +} + +void +gtk_ctree_node_set_row_style (GtkCTree *ctree, + GtkCTreeNode *node, + GtkStyle *style) +{ + GtkCList *clist; + GtkRequisition requisition; + gboolean visible; + gint *old_width = NULL; + gint i; + + g_return_if_fail (GTK_IS_CTREE (ctree)); + g_return_if_fail (node != NULL); + + clist = GTK_CLIST (ctree); + + if (GTK_CTREE_ROW (node)->row.style == style) + return; + + visible = gtk_ctree_is_viewable (ctree, node); + if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + { + old_width = g_new (gint, clist->columns); + for (i = 0; i < clist->columns; i++) + if (clist->column[i].auto_resize) + { + GTK_CLIST_GET_CLASS (clist)->cell_size_request + (clist, >K_CTREE_ROW (node)->row, i, &requisition); + old_width[i] = requisition.width; + } + } + + if (GTK_CTREE_ROW (node)->row.style) + { + if (GTK_WIDGET_REALIZED (ctree)) + gtk_style_detach (GTK_CTREE_ROW (node)->row.style); + g_object_unref (GTK_CTREE_ROW (node)->row.style); + } + + GTK_CTREE_ROW (node)->row.style = style; + + if (GTK_CTREE_ROW (node)->row.style) + { + g_object_ref (GTK_CTREE_ROW (node)->row.style); + + if (GTK_WIDGET_REALIZED (ctree)) + GTK_CTREE_ROW (node)->row.style = + gtk_style_attach (GTK_CTREE_ROW (node)->row.style, + clist->clist_window); + } + + if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + { + for (i = 0; i < clist->columns; i++) + if (clist->column[i].auto_resize) + column_auto_resize (clist, >K_CTREE_ROW (node)->row, i, + old_width[i]); + g_free (old_width); + } + tree_draw_node (ctree, node); +} + +GtkStyle * +gtk_ctree_node_get_row_style (GtkCTree *ctree, + GtkCTreeNode *node) +{ + g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL); + g_return_val_if_fail (node != NULL, NULL); + + return GTK_CTREE_ROW (node)->row.style; +} + +void +gtk_ctree_node_set_foreground (GtkCTree *ctree, + GtkCTreeNode *node, + GdkColor *color) { - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); @@ -4795,6 +5129,9 @@ gtk_ctree_set_foreground (GtkCTree *ctree, { GTK_CTREE_ROW (node)->row.foreground = *color; GTK_CTREE_ROW (node)->row.fg_set = TRUE; + if (GTK_WIDGET_REALIZED (ctree)) + gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (ctree)), + >K_CTREE_ROW (node)->row.foreground); } else GTK_CTREE_ROW (node)->row.fg_set = FALSE; @@ -4803,11 +5140,10 @@ gtk_ctree_set_foreground (GtkCTree *ctree, } void -gtk_ctree_set_background (GtkCTree *ctree, - GtkCTreeNode *node, - GdkColor *color) +gtk_ctree_node_set_background (GtkCTree *ctree, + GtkCTreeNode *node, + GdkColor *color) { - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (node != NULL); @@ -4815,6 +5151,9 @@ gtk_ctree_set_background (GtkCTree *ctree, { GTK_CTREE_ROW (node)->row.background = *color; GTK_CTREE_ROW (node)->row.bg_set = TRUE; + if (GTK_WIDGET_REALIZED (ctree)) + gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (ctree)), + >K_CTREE_ROW (node)->row.background); } else GTK_CTREE_ROW (node)->row.bg_set = FALSE; @@ -4823,52 +5162,59 @@ gtk_ctree_set_background (GtkCTree *ctree, } void -gtk_ctree_set_row_data (GtkCTree *ctree, - GtkCTreeNode *node, - gpointer data) +gtk_ctree_node_set_row_data (GtkCTree *ctree, + GtkCTreeNode *node, + gpointer data) { - gtk_ctree_set_row_data_full (ctree, node, data, NULL); + gtk_ctree_node_set_row_data_full (ctree, node, data, NULL); } void -gtk_ctree_set_row_data_full (GtkCTree *ctree, - GtkCTreeNode *node, - gpointer data, - GtkDestroyNotify destroy) +gtk_ctree_node_set_row_data_full (GtkCTree *ctree, + GtkCTreeNode *node, + gpointer data, + GtkDestroyNotify destroy) { - g_return_if_fail (ctree != NULL); + GtkDestroyNotify dnotify; + gpointer ddata; + g_return_if_fail (GTK_IS_CTREE (ctree)); + g_return_if_fail (node != NULL); + dnotify = GTK_CTREE_ROW (node)->row.destroy; + ddata = GTK_CTREE_ROW (node)->row.data; + GTK_CTREE_ROW (node)->row.data = data; GTK_CTREE_ROW (node)->row.destroy = destroy; + + if (dnotify) + dnotify (ddata); } gpointer -gtk_ctree_get_row_data (GtkCTree *ctree, - GtkCTreeNode *node) +gtk_ctree_node_get_row_data (GtkCTree *ctree, + GtkCTreeNode *node) { - g_return_val_if_fail (ctree != NULL, NULL); g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL); return node ? GTK_CTREE_ROW (node)->row.data : NULL; } void -gtk_ctree_moveto (GtkCTree *ctree, - GtkCTreeNode *node, - gint column, - gfloat row_align, - gfloat col_align) +gtk_ctree_node_moveto (GtkCTree *ctree, + GtkCTreeNode *node, + gint column, + gfloat row_align, + gfloat col_align) { gint row = -1; GtkCList *clist; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); clist = GTK_CLIST (ctree); - while (node && !gtk_ctree_is_visible (ctree, node)) + while (node && !gtk_ctree_is_viewable (ctree, node)) node = GTK_CTREE_ROW (node)->parent; if (node) @@ -4877,169 +5223,260 @@ gtk_ctree_moveto (GtkCTree *ctree, gtk_clist_moveto (clist, row, column, row_align, col_align); } +GtkVisibility gtk_ctree_node_is_visible (GtkCTree *ctree, + GtkCTreeNode *node) +{ + gint row; + + g_return_val_if_fail (ctree != NULL, 0); + g_return_val_if_fail (node != NULL, 0); + + row = g_list_position (GTK_CLIST (ctree)->row_list, (GList*) node); + return gtk_clist_row_is_visible (GTK_CLIST (ctree), row); +} + /*********************************************************** * GtkCTree specific functions * ***********************************************************/ - void gtk_ctree_set_indent (GtkCTree *ctree, gint indent) { - g_return_if_fail (ctree != NULL); + GtkCList *clist; + g_return_if_fail (GTK_IS_CTREE (ctree)); g_return_if_fail (indent >= 0); - if (indent != ctree->tree_indent) - { - ctree->tree_indent = indent; - if (!GTK_CLIST_FROZEN (ctree)) - gtk_clist_thaw (GTK_CLIST (ctree)); - } + if (indent == ctree->tree_indent) + return; + + clist = GTK_CLIST (ctree); + ctree->tree_indent = indent; + + if (clist->column[ctree->tree_column].auto_resize && + !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + gtk_clist_set_column_width + (clist, ctree->tree_column, + gtk_clist_optimal_column_width (clist, ctree->tree_column)); + else + CLIST_REFRESH (ctree); } void -gtk_ctree_set_reorderable (GtkCTree *ctree, - gboolean reorderable) +gtk_ctree_set_spacing (GtkCTree *ctree, + gint spacing) { - g_return_if_fail (ctree != NULL); + GtkCList *clist; + gint old_spacing; + g_return_if_fail (GTK_IS_CTREE (ctree)); + g_return_if_fail (spacing >= 0); - if (ctree->reorderable == (reorderable != 0)) + if (spacing == ctree->tree_spacing) return; - ctree->reorderable = (reorderable != 0); - - if (GTK_WIDGET_REALIZED (ctree)) - { - if (ctree->reorderable) - create_xor_gc (ctree); - else - gdk_gc_destroy (ctree->xor_gc); - } + clist = GTK_CLIST (ctree); + + old_spacing = ctree->tree_spacing; + ctree->tree_spacing = spacing; + + if (clist->column[ctree->tree_column].auto_resize && + !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + gtk_clist_set_column_width (clist, ctree->tree_column, + clist->column[ctree->tree_column].width + + spacing - old_spacing); + else + CLIST_REFRESH (ctree); } void -gtk_ctree_set_use_drag_icons (GtkCTree *ctree, - gboolean use_icons) +gtk_ctree_set_show_stub (GtkCTree *ctree, + gboolean show_stub) { - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); - if (ctree->use_icons == (use_icons != 0)) - return; + show_stub = show_stub != FALSE; + + if (show_stub != ctree->show_stub) + { + GtkCList *clist; - ctree->use_icons = (use_icons != 0); + clist = GTK_CLIST (ctree); + ctree->show_stub = show_stub; + + if (CLIST_UNFROZEN (clist) && clist->rows && + gtk_clist_row_is_visible (clist, 0) != GTK_VISIBILITY_NONE) + GTK_CLIST_GET_CLASS (clist)->draw_row + (clist, NULL, 0, GTK_CLIST_ROW (clist->row_list)); + } } void gtk_ctree_set_line_style (GtkCTree *ctree, GtkCTreeLineStyle line_style) { - g_return_if_fail (ctree != NULL); + GtkCList *clist; + GtkCTreeLineStyle old_style; + g_return_if_fail (GTK_IS_CTREE (ctree)); - if (line_style != ctree->line_style) - { - ctree->line_style = line_style; + if (line_style == ctree->line_style) + return; + + clist = GTK_CLIST (ctree); - if (!GTK_WIDGET_REALIZED (ctree)) - return; + old_style = ctree->line_style; + ctree->line_style = line_style; + + if (clist->column[ctree->tree_column].auto_resize && + !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + { + if (old_style == GTK_CTREE_LINES_TABBED) + gtk_clist_set_column_width + (clist, ctree->tree_column, + clist->column[ctree->tree_column].width - 3); + else if (line_style == GTK_CTREE_LINES_TABBED) + gtk_clist_set_column_width + (clist, ctree->tree_column, + clist->column[ctree->tree_column].width + 3); + } + if (GTK_WIDGET_REALIZED (ctree)) + { switch (line_style) { case GTK_CTREE_LINES_SOLID: if (GTK_WIDGET_REALIZED (ctree)) gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID, - None, None); + GDK_CAP_BUTT, GDK_JOIN_MITER); break; case GTK_CTREE_LINES_DOTTED: if (GTK_WIDGET_REALIZED (ctree)) gdk_gc_set_line_attributes (ctree->lines_gc, 1, - GDK_LINE_ON_OFF_DASH, None, None); + GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_MITER); gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2); break; case GTK_CTREE_LINES_TABBED: if (GTK_WIDGET_REALIZED (ctree)) gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID, - None, None); + GDK_CAP_BUTT, GDK_JOIN_MITER); break; case GTK_CTREE_LINES_NONE: break; default: return; } - if (!GTK_CLIST_FROZEN (ctree)) - gtk_clist_thaw (GTK_CLIST (ctree)); + CLIST_REFRESH (ctree); } } - -/*********************************************************** - * Tree sorting functions * - ***********************************************************/ - - -void -gtk_ctree_set_auto_sort (GtkCTree *ctree, - gboolean auto_sort) +void +gtk_ctree_set_expander_style (GtkCTree *ctree, + GtkCTreeExpanderStyle expander_style) { - g_return_if_fail (ctree != NULL); + GtkCList *clist; + GtkCTreeExpanderStyle old_style; + g_return_if_fail (GTK_IS_CTREE (ctree)); - - if (ctree->auto_sort == (auto_sort != 0)) + + if (expander_style == ctree->expander_style) return; - ctree->auto_sort = (auto_sort != 0); + clist = GTK_CLIST (ctree); - if (auto_sort) - gtk_ctree_sort_recursive (ctree, NULL); -} + old_style = ctree->expander_style; + ctree->expander_style = expander_style; -void -gtk_ctree_set_compare_func (GtkCTree *ctree, - GtkCTreeCompareFunc cmp_func) -{ - g_return_if_fail (ctree != NULL); - g_return_if_fail (GTK_IS_CTREE (ctree)); + if (clist->column[ctree->tree_column].auto_resize && + !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + { + gint new_width; - if (cmp_func == NULL) - ctree->node_compare = default_compare; - else - ctree->node_compare = cmp_func; + new_width = clist->column[ctree->tree_column].width; + switch (old_style) + { + case GTK_CTREE_EXPANDER_NONE: + break; + case GTK_CTREE_EXPANDER_TRIANGLE: + new_width -= PM_SIZE + 3; + break; + case GTK_CTREE_EXPANDER_SQUARE: + case GTK_CTREE_EXPANDER_CIRCULAR: + new_width -= PM_SIZE + 1; + break; + } + + switch (expander_style) + { + case GTK_CTREE_EXPANDER_NONE: + break; + case GTK_CTREE_EXPANDER_TRIANGLE: + new_width += PM_SIZE + 3; + break; + case GTK_CTREE_EXPANDER_SQUARE: + case GTK_CTREE_EXPANDER_CIRCULAR: + new_width += PM_SIZE + 1; + break; + } + + gtk_clist_set_column_width (clist, ctree->tree_column, new_width); + } + + if (GTK_WIDGET_DRAWABLE (clist)) + CLIST_REFRESH (clist); } + +/*********************************************************** + * Tree sorting functions * + ***********************************************************/ + + static void tree_sort (GtkCTree *ctree, GtkCTreeNode *node, gpointer data) { GtkCTreeNode *list_start; - GtkCTreeNode *max; + GtkCTreeNode *cmp; GtkCTreeNode *work; + GtkCList *clist; + + clist = GTK_CLIST (ctree); if (node) list_start = GTK_CTREE_ROW (node)->children; else - list_start = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list); + list_start = GTK_CTREE_NODE (clist->row_list); while (list_start) { - max = list_start; - work = GTK_CTREE_ROW (max)->sibling; + cmp = list_start; + work = GTK_CTREE_ROW (cmp)->sibling; while (work) { - if (ctree->node_compare (ctree, work, max) < 0) - max = work; + if (clist->sort_type == GTK_SORT_ASCENDING) + { + if (clist->compare + (clist, GTK_CTREE_ROW (work), GTK_CTREE_ROW (cmp)) < 0) + cmp = work; + } + else + { + if (clist->compare + (clist, GTK_CTREE_ROW (work), GTK_CTREE_ROW (cmp)) > 0) + cmp = work; + } work = GTK_CTREE_ROW (work)->sibling; } - if (max == list_start) - list_start = GTK_CTREE_ROW (max)->sibling; + if (cmp == list_start) + list_start = GTK_CTREE_ROW (cmp)->sibling; else { - gtk_ctree_unlink (ctree, max, FALSE); - gtk_ctree_link (ctree, max, node, list_start, FALSE); + gtk_ctree_unlink (ctree, cmp, FALSE); + gtk_ctree_link (ctree, cmp, node, list_start, FALSE); } } } @@ -5050,23 +5487,16 @@ gtk_ctree_sort_recursive (GtkCTree *ctree, { GtkCList *clist; GtkCTreeNode *focus_node = NULL; - gboolean thaw = FALSE; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); clist = GTK_CLIST (ctree); - if (!GTK_CLIST_FROZEN (clist)) - { - gtk_clist_freeze (clist); - thaw = TRUE; - } + gtk_clist_freeze (clist); - if (clist->selection_mode == GTK_SELECTION_EXTENDED) + if (clist->selection_mode == GTK_SELECTION_MULTIPLE) { - if (clist->anchor != -1) - GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL); g_list_free (clist->undo_selection); g_list_free (clist->undo_unselection); @@ -5074,7 +5504,7 @@ gtk_ctree_sort_recursive (GtkCTree *ctree, clist->undo_unselection = NULL; } - if (!node || (node && gtk_ctree_is_visible (ctree, node))) + if (!node || (node && gtk_ctree_is_viewable (ctree, node))) focus_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row)); @@ -5089,33 +5519,31 @@ gtk_ctree_sort_recursive (GtkCTree *ctree, clist->undo_anchor = clist->focus_row; } - if (thaw) - gtk_clist_thaw (clist); + gtk_clist_thaw (clist); +} + +static void +real_sort_list (GtkCList *clist) +{ + gtk_ctree_sort_recursive (GTK_CTREE (clist), NULL); } void -gtk_ctree_sort (GtkCTree *ctree, - GtkCTreeNode *node) +gtk_ctree_sort_node (GtkCTree *ctree, + GtkCTreeNode *node) { GtkCList *clist; GtkCTreeNode *focus_node = NULL; - gboolean thaw = FALSE; - g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); clist = GTK_CLIST (ctree); - if (!GTK_CLIST_FROZEN (clist)) - { - gtk_clist_freeze (clist); - thaw = TRUE; - } + gtk_clist_freeze (clist); - if (clist->selection_mode == GTK_SELECTION_EXTENDED) + if (clist->selection_mode == GTK_SELECTION_MULTIPLE) { - if (clist->anchor != -1) - GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL); g_list_free (clist->undo_selection); g_list_free (clist->undo_unselection); @@ -5123,7 +5551,7 @@ gtk_ctree_sort (GtkCTree *ctree, clist->undo_unselection = NULL; } - if (!node || (node && gtk_ctree_is_visible (ctree, node))) + if (!node || (node && gtk_ctree_is_viewable (ctree, node))) focus_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row)); @@ -5135,8 +5563,7 @@ gtk_ctree_sort (GtkCTree *ctree, clist->undo_anchor = clist->focus_row; } - if (thaw) - gtk_clist_thaw (clist); + gtk_clist_thaw (clist); } /************************************************************************/ @@ -5150,13 +5577,14 @@ fake_unselect_all (GtkCList *clist, if (row >= 0 && (focus_node = g_list_nth (clist->row_list, row))) { - if (GTK_CTREE_ROW (focus_node)->row.state == GTK_STATE_NORMAL) + if (GTK_CTREE_ROW (focus_node)->row.state == GTK_STATE_NORMAL && + GTK_CTREE_ROW (focus_node)->row.selectable) { GTK_CTREE_ROW (focus_node)->row.state = GTK_STATE_SELECTED; - if (!GTK_CLIST_FROZEN (clist) && + if (CLIST_UNFROZEN (clist) && gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE) - GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, + GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, GTK_CLIST_ROW (focus_node)); } } @@ -5192,22 +5620,19 @@ resync_selection (GtkCList *clist, GdkEvent *event) gint i; gint e; gint row; - gboolean thaw = FALSE; gboolean unselect; - g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CTREE (clist)); - if (clist->anchor < 0) + if (clist->selection_mode != GTK_SELECTION_MULTIPLE) + return; + + if (clist->anchor < 0 || clist->drag_pos < 0) return; ctree = GTK_CTREE (clist); - if (!GTK_CLIST_FROZEN (clist)) - { - GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN); - thaw = TRUE; - } + clist->freeze_count++; i = MIN (clist->anchor, clist->drag_pos); e = MAX (clist->anchor, clist->drag_pos); @@ -5227,13 +5652,13 @@ resync_selection (GtkCList *clist, GdkEvent *event) unselect = TRUE; - if (gtk_ctree_is_visible (ctree, node)) + if (gtk_ctree_is_viewable (ctree, node)) { row = g_list_position (clist->row_list, (GList *)node); if (row >= i && row <= e) unselect = FALSE; } - if (unselect) + if (unselect && GTK_CTREE_ROW (node)->row.selectable) { GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED; gtk_ctree_unselect (ctree, node); @@ -5243,34 +5668,64 @@ resync_selection (GtkCList *clist, GdkEvent *event) } } - - for (node = GTK_CTREE_NODE (g_list_nth (clist->row_list, i)); i <= e; - i++, node = GTK_CTREE_NODE_NEXT (node)) - if (g_list_find (clist->selection, node)) - { - if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL) + if (clist->anchor < clist->drag_pos) + { + for (node = GTK_CTREE_NODE (g_list_nth (clist->row_list, i)); i <= e; + i++, node = GTK_CTREE_NODE_NEXT (node)) + if (GTK_CTREE_ROW (node)->row.selectable) { - GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED; - gtk_ctree_unselect (ctree, node); - clist->undo_selection = g_list_prepend (clist->undo_selection, - node); + if (g_list_find (clist->selection, node)) + { + if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL) + { + GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED; + gtk_ctree_unselect (ctree, node); + clist->undo_selection = + g_list_prepend (clist->undo_selection, node); + } + } + else if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED) + { + GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL; + clist->undo_unselection = + g_list_prepend (clist->undo_unselection, node); + } } - } - else if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED) - { - GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL; - clist->undo_unselection = g_list_prepend (clist->undo_unselection, - node); - } + } + else + { + for (node = GTK_CTREE_NODE (g_list_nth (clist->row_list, e)); i <= e; + e--, node = GTK_CTREE_NODE_PREV (node)) + if (GTK_CTREE_ROW (node)->row.selectable) + { + if (g_list_find (clist->selection, node)) + { + if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL) + { + GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED; + gtk_ctree_unselect (ctree, node); + clist->undo_selection = + g_list_prepend (clist->undo_selection, node); + } + } + else if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED) + { + GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL; + clist->undo_unselection = + g_list_prepend (clist->undo_unselection, node); + } + } + } + clist->undo_unselection = g_list_reverse (clist->undo_unselection); for (list = clist->undo_unselection; list; list = list->next) gtk_ctree_select (ctree, list->data); clist->anchor = -1; clist->drag_pos = -1; - if (thaw) - GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN); + if (!CLIST_UNFROZEN (clist)) + clist->freeze_count--; } static void @@ -5279,10 +5734,9 @@ real_undo_selection (GtkCList *clist) GtkCTree *ctree; GList *work; - g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CTREE (clist)); - if (clist->selection_mode != GTK_SELECTION_EXTENDED) + if (clist->selection_mode != GTK_SELECTION_MULTIPLE) return; if (!(clist->undo_selection || clist->undo_unselection)) @@ -5294,16 +5748,17 @@ real_undo_selection (GtkCList *clist) ctree = GTK_CTREE (clist); for (work = clist->undo_selection; work; work = work->next) - gtk_ctree_select (ctree, GTK_CTREE_NODE (work->data)); + if (GTK_CTREE_ROW (work->data)->row.selectable) + gtk_ctree_select (ctree, GTK_CTREE_NODE (work->data)); for (work = clist->undo_unselection; work; work = work->next) - gtk_ctree_unselect (ctree, GTK_CTREE_NODE (work->data)); + if (GTK_CTREE_ROW (work->data)->row.selectable) + gtk_ctree_unselect (ctree, GTK_CTREE_NODE (work->data)); if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor) { - gtk_widget_draw_focus (GTK_WIDGET (clist)); clist->focus_row = clist->undo_anchor; - gtk_widget_draw_focus (GTK_WIDGET (clist)); + gtk_widget_queue_draw (GTK_WIDGET (clist)); } else clist->focus_row = clist->undo_anchor; @@ -5322,3 +5777,378 @@ real_undo_selection (GtkCList *clist) gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0); } + +void +gtk_ctree_set_drag_compare_func (GtkCTree *ctree, + GtkCTreeCompareDragFunc cmp_func) +{ + g_return_if_fail (GTK_IS_CTREE (ctree)); + + ctree->drag_compare = cmp_func; +} + +static gboolean +check_drag (GtkCTree *ctree, + GtkCTreeNode *drag_source, + GtkCTreeNode *drag_target, + GtkCListDragPos insert_pos) +{ + g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE); + + if (drag_source && drag_source != drag_target && + (!GTK_CTREE_ROW (drag_source)->children || + !gtk_ctree_is_ancestor (ctree, drag_source, drag_target))) + { + switch (insert_pos) + { + case GTK_CLIST_DRAG_NONE: + return FALSE; + case GTK_CLIST_DRAG_AFTER: + if (GTK_CTREE_ROW (drag_target)->sibling != drag_source) + return (!ctree->drag_compare || + ctree->drag_compare (ctree, + drag_source, + GTK_CTREE_ROW (drag_target)->parent, + GTK_CTREE_ROW (drag_target)->sibling)); + break; + case GTK_CLIST_DRAG_BEFORE: + if (GTK_CTREE_ROW (drag_source)->sibling != drag_target) + return (!ctree->drag_compare || + ctree->drag_compare (ctree, + drag_source, + GTK_CTREE_ROW (drag_target)->parent, + drag_target)); + break; + case GTK_CLIST_DRAG_INTO: + if (!GTK_CTREE_ROW (drag_target)->is_leaf && + GTK_CTREE_ROW (drag_target)->children != drag_source) + return (!ctree->drag_compare || + ctree->drag_compare (ctree, + drag_source, + drag_target, + GTK_CTREE_ROW (drag_target)->children)); + break; + } + } + return FALSE; +} + + + +/************************************/ +static void +drag_dest_info_destroy (gpointer data) +{ + GtkCListDestInfo *info = data; + + g_free (info); +} + +static void +drag_dest_cell (GtkCList *clist, + gint x, + gint y, + GtkCListDestInfo *dest_info) +{ + GtkWidget *widget; + + widget = GTK_WIDGET (clist); + + dest_info->insert_pos = GTK_CLIST_DRAG_NONE; + + y -= (GTK_CONTAINER (widget)->border_width + + widget->style->ythickness + clist->column_title_area.height); + dest_info->cell.row = ROW_FROM_YPIXEL (clist, y); + + if (dest_info->cell.row >= clist->rows) + { + dest_info->cell.row = clist->rows - 1; + y = ROW_TOP_YPIXEL (clist, dest_info->cell.row) + clist->row_height; + } + if (dest_info->cell.row < -1) + dest_info->cell.row = -1; + + x -= GTK_CONTAINER (widget)->border_width + widget->style->xthickness; + + dest_info->cell.column = COLUMN_FROM_XPIXEL (clist, x); + + if (dest_info->cell.row >= 0) + { + gint y_delta; + gint h = 0; + + y_delta = y - ROW_TOP_YPIXEL (clist, dest_info->cell.row); + + if (GTK_CLIST_DRAW_DRAG_RECT(clist) && + !GTK_CTREE_ROW (g_list_nth (clist->row_list, + dest_info->cell.row))->is_leaf) + { + dest_info->insert_pos = GTK_CLIST_DRAG_INTO; + h = clist->row_height / 4; + } + else if (GTK_CLIST_DRAW_DRAG_LINE(clist)) + { + dest_info->insert_pos = GTK_CLIST_DRAG_BEFORE; + h = clist->row_height / 2; + } + + if (GTK_CLIST_DRAW_DRAG_LINE(clist)) + { + if (y_delta < h) + dest_info->insert_pos = GTK_CLIST_DRAG_BEFORE; + else if (clist->row_height - y_delta < h) + dest_info->insert_pos = GTK_CLIST_DRAG_AFTER; + } + } +} + +static void +gtk_ctree_drag_begin (GtkWidget *widget, + GdkDragContext *context) +{ + GtkCList *clist; + GtkCTree *ctree; + gboolean use_icons; + + g_return_if_fail (GTK_IS_CTREE (widget)); + g_return_if_fail (context != NULL); + + clist = GTK_CLIST (widget); + ctree = GTK_CTREE (widget); + + use_icons = GTK_CLIST_USE_DRAG_ICONS (clist); + GTK_CLIST_UNSET_FLAG (clist, CLIST_USE_DRAG_ICONS); + GTK_WIDGET_CLASS (parent_class)->drag_begin (widget, context); + + if (use_icons) + { + GtkCTreeNode *node; + + GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS); + node = GTK_CTREE_NODE (g_list_nth (clist->row_list, + clist->click_cell.row)); + if (node) + { + if (GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap) + { + gtk_drag_set_icon_pixmap + (context, + gtk_widget_get_colormap (widget), + GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap, + GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask, + -2, -2); + return; + } + } + gtk_drag_set_icon_default (context); + } +} + +static gint +gtk_ctree_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + GtkCList *clist; + GtkCTree *ctree; + GtkCListDestInfo new_info; + GtkCListDestInfo *dest_info; + + g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE); + + clist = GTK_CLIST (widget); + ctree = GTK_CTREE (widget); + + dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest"); + + if (!dest_info) + { + dest_info = g_new (GtkCListDestInfo, 1); + + dest_info->cell.row = -1; + dest_info->cell.column = -1; + dest_info->insert_pos = GTK_CLIST_DRAG_NONE; + + g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info, + drag_dest_info_destroy); + } + + drag_dest_cell (clist, x, y, &new_info); + + if (GTK_CLIST_REORDERABLE (clist)) + { + GList *list; + GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE); + + list = context->targets; + while (list) + { + if (atom == GPOINTER_TO_INT (list->data)) + break; + list = list->next; + } + + if (list) + { + GtkCTreeNode *drag_source; + GtkCTreeNode *drag_target; + + drag_source = GTK_CTREE_NODE (g_list_nth (clist->row_list, + clist->click_cell.row)); + drag_target = GTK_CTREE_NODE (g_list_nth (clist->row_list, + new_info.cell.row)); + + if (gtk_drag_get_source_widget (context) != widget || + !check_drag (ctree, drag_source, drag_target, + new_info.insert_pos)) + { + if (dest_info->cell.row < 0) + { + gdk_drag_status (context, GDK_ACTION_DEFAULT, time); + return FALSE; + } + return TRUE; + } + + if (new_info.cell.row != dest_info->cell.row || + (new_info.cell.row == dest_info->cell.row && + dest_info->insert_pos != new_info.insert_pos)) + { + if (dest_info->cell.row >= 0) + GTK_CLIST_GET_CLASS (clist)->draw_drag_highlight + (clist, + g_list_nth (clist->row_list, dest_info->cell.row)->data, + dest_info->cell.row, dest_info->insert_pos); + + dest_info->insert_pos = new_info.insert_pos; + dest_info->cell.row = new_info.cell.row; + dest_info->cell.column = new_info.cell.column; + + GTK_CLIST_GET_CLASS (clist)->draw_drag_highlight + (clist, + g_list_nth (clist->row_list, dest_info->cell.row)->data, + dest_info->cell.row, dest_info->insert_pos); + + clist->drag_highlight_row = dest_info->cell.row; + clist->drag_highlight_pos = dest_info->insert_pos; + + gdk_drag_status (context, context->suggested_action, time); + } + return TRUE; + } + } + + dest_info->insert_pos = new_info.insert_pos; + dest_info->cell.row = new_info.cell.row; + dest_info->cell.column = new_info.cell.column; + return TRUE; +} + +static void +gtk_ctree_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint32 time) +{ + GtkCTree *ctree; + GtkCList *clist; + + g_return_if_fail (GTK_IS_CTREE (widget)); + g_return_if_fail (context != NULL); + g_return_if_fail (selection_data != NULL); + + ctree = GTK_CTREE (widget); + clist = GTK_CLIST (widget); + + if (GTK_CLIST_REORDERABLE (clist) && + gtk_drag_get_source_widget (context) == widget && + selection_data->target == + gdk_atom_intern ("gtk-clist-drag-reorder", FALSE) && + selection_data->format == GTK_TYPE_POINTER && + selection_data->length == sizeof (GtkCListCellInfo)) + { + GtkCListCellInfo *source_info; + + source_info = (GtkCListCellInfo *)(selection_data->data); + if (source_info) + { + GtkCListDestInfo dest_info; + GtkCTreeNode *source_node; + GtkCTreeNode *dest_node; + + drag_dest_cell (clist, x, y, &dest_info); + + source_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, + source_info->row)); + dest_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, + dest_info.cell.row)); + + if (!source_node || !dest_node) + return; + + switch (dest_info.insert_pos) + { + case GTK_CLIST_DRAG_NONE: + break; + case GTK_CLIST_DRAG_INTO: + if (check_drag (ctree, source_node, dest_node, + dest_info.insert_pos)) + gtk_ctree_move (ctree, source_node, dest_node, + GTK_CTREE_ROW (dest_node)->children); + g_dataset_remove_data (context, "gtk-clist-drag-dest"); + break; + case GTK_CLIST_DRAG_BEFORE: + if (check_drag (ctree, source_node, dest_node, + dest_info.insert_pos)) + gtk_ctree_move (ctree, source_node, + GTK_CTREE_ROW (dest_node)->parent, dest_node); + g_dataset_remove_data (context, "gtk-clist-drag-dest"); + break; + case GTK_CLIST_DRAG_AFTER: + if (check_drag (ctree, source_node, dest_node, + dest_info.insert_pos)) + gtk_ctree_move (ctree, source_node, + GTK_CTREE_ROW (dest_node)->parent, + GTK_CTREE_ROW (dest_node)->sibling); + g_dataset_remove_data (context, "gtk-clist-drag-dest"); + break; + } + } + } +} + +/* dummy boxed type definition, used so that the GtkCTreeNode signal + * arguments have a reasonable type. + */ +gpointer +ctree_node_copy (gpointer boxed) +{ + return boxed; +} + +void +ctree_node_free (gpointer boxed) +{ + /* nothing */ +} + +GType +gtk_ctree_node_get_type (void) +{ + static GType our_type = 0; + + if (our_type == 0) + our_type = g_boxed_type_register_static ("GtkCTreeNode", + (GBoxedCopyFunc)ctree_node_copy, + (GBoxedFreeFunc)ctree_node_free); + + return our_type; +}