+2008-08-05 [colin] 3.5.0cvs49
+
+ * src/prefs_account.c
+ * src/prefs_filtering_action.c
+ * src/prefs_matcher.c
+ * src/gtk/Makefile.am
+ * src/gtk/claws-marshal.list
+ * src/gtk/colorlabel.c
+ * src/gtk/colorsel.c
+ * src/gtk/foldersort.c
+ * src/gtk/gtkaspell.c
+ * src/gtk/gtkcmclist.c
+ * src/gtk/gtkcmclist.h
+ * src/gtk/gtkcmctree.c
+ * src/gtk/gtkcmctree.h
+ * src/gtk/gtkcmoptionmenu.c
+ * src/gtk/gtkcmoptionmenu.h
+ * src/gtk/gtksctree.c
+ * src/gtk/gtksctree.h
+ * src/gtk/gtkutils.c
+ * src/gtk/gtkutils.h
+ * src/gtk/gtkvscrollbutton.c
+ * src/gtk/menu.c
+ * src/gtk/menu.h
+ * src/gtk/quicksearch.c
+ * src/plugins/dillo_viewer/dillo_viewer.c
+ * src/plugins/pgpcore/select-keys.c
+ Try to finish yesterday's commit
+
2008-08-04 [colin] 3.5.0cvs48
* src/addressadd.c
( cvs diff -u -r 1.274.2.261 -r 1.274.2.262 src/mainwindow.c; ) > 3.5.0cvs46.patchset
( cvs diff -u -r 1.382.2.462 -r 1.382.2.463 src/compose.c; cvs diff -u -r 1.50.2.48 -r 1.50.2.49 src/compose.h; cvs diff -u -r 1.19.2.27 -r 1.19.2.28 src/toolbar.h; cvs diff -u -r 1.96.2.203 -r 1.96.2.204 src/textview.c; cvs diff -u -r 1.25.2.58 -r 1.25.2.59 src/stock_pixmap.c; cvs diff -u -r 1.5.2.21 -r 1.5.2.22 src/statusbar.c; cvs diff -u -r 1.3.8.8 -r 1.3.8.9 src/noticeview.h; cvs diff -u -r 1.20.2.25 -r 1.20.2.26 src/mimeview.h; cvs diff -u -r 1.274.2.262 -r 1.274.2.263 src/mainwindow.c; cvs diff -u -r 1.1.2.22 -r 1.1.2.23 src/image_viewer.c; cvs diff -u -r 1.9.2.57 -r 1.9.2.58 src/gtk/gtkaspell.c; cvs diff -u -r 1.5.2.13 -r 1.5.2.14 src/gtk/gtkvscrollbutton.c; cvs diff -u -r 1.12.2.26 -r 1.12.2.27 src/plugins/dillo_viewer/dillo_viewer.c; ) > 3.5.0cvs47.patchset
( cvs diff -u -r 1.9.2.23 -r 1.9.2.24 src/addressadd.c; cvs diff -u -r 1.60.2.122 -r 1.60.2.123 src/addressbook.c; cvs diff -u -r 1.1.2.11 -r 1.1.2.12 src/addressbook_foldersel.c; cvs diff -u -r 1.5.2.10 -r 1.5.2.11 src/addressitem.h; cvs diff -u -r 1.5.10.24 -r 1.5.10.25 src/addrgather.c; cvs diff -u -r 1.2.4.20 -r 1.2.4.21 src/browseldap.c; cvs diff -u -r 1.382.2.462 -r 1.382.2.463 src/compose.c; cvs diff -u -r 1.50.2.48 -r 1.50.2.49 src/compose.h; cvs diff -u -r 1.14.2.51 -r 1.14.2.52 src/editaddress.c; cvs diff -u -r 1.1.2.6 -r 1.1.2.7 src/editaddress_other_attributes_ldap.c; cvs diff -u -r 1.11.2.19 -r 1.11.2.20 src/editgroup.c; cvs diff -u -r 1.10.2.13 -r 1.10.2.14 src/editldap_basedn.c; cvs diff -u -r 1.207.2.204 -r 1.207.2.205 src/folderview.c; cvs diff -u -r 1.20.2.23 -r 1.20.2.24 src/folderview.h; cvs diff -u -r 1.14.2.20 -r 1.14.2.21 src/grouplistdialog.c; cvs diff -u -r 1.1.2.22 -r 1.1.2.23 src/image_viewer.c; cvs diff -u -r 1.1.2.60 -r 1.1.2.61 src/imap_gtk.c; cvs diff -u -r 1.14.2.18 -r 1.14.2.19 src/importldif.c; cvs diff -u -r 1.115.2.200 -r 1.115.2.201 src/main.c; cvs diff -u -r 1.274.2.262 -r 1.274.2.263 src/mainwindow.c; cvs diff -u -r 1.3.12.30 -r 1.3.12.31 src/message_search.c; cvs diff -u -r 1.2.2.33 -r 1.2.2.34 src/mh_gtk.c; cvs diff -u -r 1.83.2.138 -r 1.83.2.139 src/mimeview.c; cvs diff -u -r 1.20.2.25 -r 1.20.2.26 src/mimeview.h; cvs diff -u -r 1.2.2.28 -r 1.2.2.29 src/news_gtk.c; cvs diff -u -r 1.3.8.8 -r 1.3.8.9 src/noticeview.h; cvs diff -u -r 1.105.2.139 -r 1.105.2.140 src/prefs_account.c; cvs diff -u -r 1.1.4.53 -r 1.1.4.54 src/prefs_filtering_action.c; cvs diff -u -r 1.43.2.73 -r 1.43.2.74 src/prefs_matcher.c; cvs diff -u -r 1.1.2.37 -r 1.1.2.38 src/prefs_msg_colors.c; cvs diff -u -r 1.1.2.56 -r 1.1.2.57 src/prefs_summaries.c; cvs diff -u -r 1.5.2.21 -r 1.5.2.22 src/statusbar.c; cvs diff -u -r 1.25.2.58 -r 1.25.2.59 src/stock_pixmap.c; cvs diff -u -r 1.15.2.54 -r 1.15.2.55 src/summary_search.c; cvs diff -u -r 1.395.2.379 -r 1.395.2.380 src/summaryview.c; cvs diff -u -r 1.68.2.48 -r 1.68.2.49 src/summaryview.h; cvs diff -u -r 1.96.2.203 -r 1.96.2.204 src/textview.c; cvs diff -u -r 1.19.2.27 -r 1.19.2.28 src/toolbar.h; cvs diff -u -r 1.20.2.16 -r 1.20.2.17 src/gtk/Makefile.am; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/gtk/claws-marshal.list; cvs diff -u -r 1.1.4.11 -r 1.1.4.12 src/gtk/colorsel.c; cvs diff -u -r 1.1.2.16 -r 1.1.2.17 src/gtk/foldersort.c; cvs diff -u -r 1.9.2.57 -r 1.9.2.58 src/gtk/gtkaspell.c; diff -u /dev/null src/gtk/gtkcmclist.c; diff -u /dev/null src/gtk/gtkcmclist.h; diff -u /dev/null src/gtk/gtkcmctree.c; diff -u /dev/null src/gtk/gtkcmctree.h; cvs diff -u -r 1.1.4.46 -r 1.1.4.47 src/gtk/gtksctree.c; cvs diff -u -r 1.1.4.13 -r 1.1.4.14 src/gtk/gtksctree.h; cvs diff -u -r 1.5.2.78 -r 1.5.2.79 src/gtk/gtkutils.c; cvs diff -u -r 1.4.2.42 -r 1.4.2.43 src/gtk/gtkutils.h; cvs diff -u -r 1.5.2.13 -r 1.5.2.14 src/gtk/gtkvscrollbutton.c; cvs diff -u -r 1.5.2.34 -r 1.5.2.35 src/gtk/menu.c; cvs diff -u -r 1.4.2.19 -r 1.4.2.20 src/gtk/menu.h; cvs diff -u -r 1.1.2.83 -r 1.1.2.84 src/gtk/quicksearch.c; cvs diff -u -r 1.12.2.26 -r 1.12.2.27 src/plugins/dillo_viewer/dillo_viewer.c; cvs diff -u -r 1.1.2.20 -r 1.1.2.21 src/plugins/pgpcore/select-keys.c; ) > 3.5.0cvs48.patchset
+( cvs diff -u -r 1.105.2.140 -r 1.105.2.141 src/prefs_account.c; cvs diff -u -r 1.1.4.54 -r 1.1.4.55 src/prefs_filtering_action.c; cvs diff -u -r 1.43.2.74 -r 1.43.2.75 src/prefs_matcher.c; cvs diff -u -r 1.20.2.16 -r 1.20.2.17 src/gtk/Makefile.am; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/gtk/claws-marshal.list; cvs diff -u -r 1.2.2.21 -r 1.2.2.22 src/gtk/colorlabel.c; cvs diff -u -r 1.1.4.11 -r 1.1.4.12 src/gtk/colorsel.c; cvs diff -u -r 1.1.2.16 -r 1.1.2.17 src/gtk/foldersort.c; cvs diff -u -r 1.9.2.57 -r 1.9.2.58 src/gtk/gtkaspell.c; diff -u /dev/null src/gtk/gtkcmclist.c; diff -u /dev/null src/gtk/gtkcmclist.h; diff -u /dev/null src/gtk/gtkcmctree.c; diff -u /dev/null src/gtk/gtkcmctree.h; diff -u /dev/null src/gtk/gtkcmoptionmenu.c; diff -u /dev/null src/gtk/gtkcmoptionmenu.h; cvs diff -u -r 1.1.4.46 -r 1.1.4.47 src/gtk/gtksctree.c; cvs diff -u -r 1.1.4.13 -r 1.1.4.14 src/gtk/gtksctree.h; cvs diff -u -r 1.5.2.78 -r 1.5.2.79 src/gtk/gtkutils.c; cvs diff -u -r 1.4.2.42 -r 1.4.2.43 src/gtk/gtkutils.h; cvs diff -u -r 1.5.2.13 -r 1.5.2.14 src/gtk/gtkvscrollbutton.c; cvs diff -u -r 1.5.2.34 -r 1.5.2.35 src/gtk/menu.c; cvs diff -u -r 1.4.2.19 -r 1.4.2.20 src/gtk/menu.h; cvs diff -u -r 1.1.2.83 -r 1.1.2.84 src/gtk/quicksearch.c; cvs diff -u -r 1.12.2.26 -r 1.12.2.27 src/plugins/dillo_viewer/dillo_viewer.c; cvs diff -u -r 1.1.2.20 -r 1.1.2.21 src/plugins/pgpcore/select-keys.c; ) > 3.5.0cvs49.patchset
MICRO_VERSION=0
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=48
+EXTRA_VERSION=49
EXTRA_RELEASE=
EXTRA_GTK2_VERSION=
fi
CFLAGS="$CFLAGS -Wall"
+<<<<<<< configure.ac
+
+if test $USE_MAINTAINER_MODE = yes; then
+ CFLAGS="$CFLAGS -DGTK_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED"
+fi
+
+=======
if test $USE_MAINTAINER_MODE = yes; then
CFLAGS="$CFLAGS -DGTK_DISABLE_DEPRECATED"
fi
+>>>>>>> 1.654.2.3521
pthread_name=
case "$target" in
*-darwin*)
filesel.c \
foldersort.c \
gtkaspell.c \
- gtksctree.c \
+ gtkcmctree.c \
+ gtkcmclist.c \
+ gtkcmoptionmenu.c \
gtkshruler.c \
gtksctree.c \
gtksourceprintjob.c \
filesel.h \
foldersort.h \
gtkaspell.h \
+ gtkcmctree.h \
+ gtkcmclist.h \
+ gtkcmoptionmenu.h \
gtksctree.h \
gtkshruler.h \
- gtksctree.h \
gtksourceprintjob.h \
gtkutils.h \
gtkvscrollbutton.h \
NONE:POINTER
NONE:INT,POINTER
+NONE:OBJECT,OBJECT
+NONE:INT,INT,BOXED
+NONE:INT,INT
+NONE:INT
+NONE:VOID
+NONE:VOID,VOID
+NONE:ENUM,FLOAT,BOOLEAN
+NONE:ENUM,FLOAT
+NONE:POINTER,INT
+NONE:POINTER,POINTER,POINTER
+NONE:ENUM
TRUE, 1, 1, widget->allocation.width - 2,
widget->allocation.height - 2);
- gdk_gc_unref(gc);
+ g_object_unref(gc);
return FALSE;
}
*
*/
+#undef GTK_DISABLE_DEPRECATED /* FIXME set_color */
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
int i;
for (i = 0; i < dialog->rows; i++) {
- folder = gtk_clist_get_row_data(GTK_CLIST(dialog->folderlist), i);
+ folder = gtk_cmclist_get_row_data(GTK_CMCLIST(dialog->folderlist), i);
folder_set_sort(folder, dialog->rows - i);
}
{
g_return_if_fail(dialog->selected > 0);
- gtk_clist_swap_rows(GTK_CLIST(dialog->folderlist), dialog->selected, dialog->selected - 1);
+ gtk_cmclist_swap_rows(GTK_CMCLIST(dialog->folderlist), dialog->selected, dialog->selected - 1);
}
static void movedown_clicked(GtkWidget *widget, FolderSortDialog *dialog)
{
g_return_if_fail(dialog->selected < (dialog->rows - 1));
- gtk_clist_swap_rows(GTK_CLIST(dialog->folderlist), dialog->selected, dialog->selected + 1);
+ gtk_cmclist_swap_rows(GTK_CMCLIST(dialog->folderlist), dialog->selected, dialog->selected + 1);
}
-static void row_selected(GtkCList *clist, gint row, gint column, GdkEventButton *event, FolderSortDialog *dialog)
+static void row_selected(GtkCMCList *clist, gint row, gint column, GdkEventButton *event, FolderSortDialog *dialog)
{
set_selected(dialog, row);
}
-static void row_unselected(GtkCList *clist, gint row, gint column, GdkEventButton *event, FolderSortDialog *dialog)
+static void row_unselected(GtkCMCList *clist, gint row, gint column, GdkEventButton *event, FolderSortDialog *dialog)
{
set_selected(dialog, -1);
}
-static void row_moved(GtkCList *clist, gint srcpos, gint destpos, FolderSortDialog *dialog)
+static void row_moved(GtkCMCList *clist, gint srcpos, gint destpos, FolderSortDialog *dialog)
{
if (dialog->selected == -1)
return;
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
- folderlist = gtk_clist_new(1);
+ folderlist = gtk_cmclist_new(1);
gtk_widget_show(folderlist);
gtk_container_add(GTK_CONTAINER(scrolledwindow1), folderlist);
- gtk_clist_set_column_width(GTK_CLIST(folderlist), 0, 80);
- gtk_clist_column_titles_show(GTK_CLIST(folderlist));
+ gtk_cmclist_set_column_width(GTK_CMCLIST(folderlist), 0, 80);
+ gtk_cmclist_column_titles_show(GTK_CMCLIST(folderlist));
label2 = gtk_label_new(_("Folders"));
gtk_widget_show(label2);
- gtk_clist_set_column_widget(GTK_CLIST(folderlist), 0, label2);
+ gtk_cmclist_set_column_widget(GTK_CMCLIST(folderlist), 0, label2);
gtk_label_set_justify(GTK_LABEL(label2), GTK_JUSTIFY_LEFT);
gtk_misc_set_alignment(GTK_MISC(label2), 0, 0.5);
gtk_widget_show(window);
gtk_widget_set_sensitive(moveup_btn, FALSE);
gtk_widget_set_sensitive(movedown_btn, FALSE);
- gtk_clist_set_reorderable(GTK_CLIST(folderlist), TRUE);
+ gtk_cmclist_set_reorderable(GTK_CMCLIST(folderlist), TRUE);
g_signal_connect(G_OBJECT(moveup_btn), "clicked",
G_CALLBACK(moveup_clicked), dialog);
gchar *text[1];
text[0] = folder->name;
- row = gtk_clist_append(GTK_CLIST(folderlist), text);
- gtk_clist_set_row_data(GTK_CLIST(folderlist), row, folder);
+ row = gtk_cmclist_append(GTK_CMCLIST(folderlist), text);
+ gtk_cmclist_set_row_data(GTK_CMCLIST(folderlist), row, folder);
dialog->rows++;
}
gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
gtk_window_set_title(GTK_WINDOW(dialog),_("Replace unknown word"));
gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
- gtk_widget_set_uposition(dialog, xx, yy);
+ gtk_window_move(GTK_WINDOW(dialog), xx, yy);
g_signal_connect_swapped(G_OBJECT(dialog), "destroy",
G_CALLBACK(gtk_widget_destroy),
wx = r.width;
wy = r.height;
- *x = rect.x + xx +
- gdk_char_width(gtk_style_get_font(GTK_WIDGET(text)->style), ' ');
+ *x = rect.x + xx + 8;
*y = rect.y + rect.height + yy;
if (*x + wx > sx)
*x = sx - wx;
if (*y + wy > sy)
- *y = *y - wy -
- gdk_string_height(gtk_style_get_font(
- GTK_WIDGET(text)->style),
- gtkaspell->theword);
+ *y = *y - wy - 10;
}
/* change the current dictionary of gtkaspell
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, Josh MacDonald,
+ * Copyright (C) 1997-1998 Jay Painter <jpaint@serv.net><jpaint@gimp.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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 <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include "claws-marshal.h"
+#include "gtkcmclist.h"
+#include <gdk/gdkkeysyms.h>
+
+/* length of button_actions array */
+#define MAX_BUTTON 5
+
+/* the width of the column resize windows */
+#define DRAG_WIDTH 6
+
+/* minimum allowed width of a column */
+#define COLUMN_MIN_WIDTH 5
+
+/* this defigns the base grid spacing */
+#define CELL_SPACING 1
+
+/* added the horizontal space at the beginning and end of a row*/
+#define COLUMN_INSET 3
+
+/* used for auto-scrolling */
+#define SCROLL_TIME 100
+
+/* gives the top pixel of the given row in context of
+ * the clist's voffset */
+#define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
+ (((row) + 1) * CELL_SPACING) + \
+ (clist)->voffset)
+
+/* returns the row index from a y pixel location in the
+ * context of the clist's voffset */
+#define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
+ ((clist)->row_height + CELL_SPACING))
+
+/* gives the left pixel of the given column in context of
+ * the clist's hoffset */
+#define COLUMN_LEFT_XPIXEL(clist, colnum) ((clist)->column[(colnum)].area.x + \
+ (clist)->hoffset)
+
+/* returns the column index from a x pixel location in the
+ * context of the clist's hoffset */
+static inline gint
+COLUMN_FROM_XPIXEL (GtkCMCList * 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;
+}
+
+/* returns the top pixel of the given row in the context of
+ * the list height */
+#define ROW_TOP(clist, row) (((clist)->row_height + CELL_SPACING) * (row))
+
+/* returns the left pixel of the given column in the context of
+ * the list width */
+#define COLUMN_LEFT(clist, colnum) ((clist)->column[(colnum)].area.x)
+
+/* returns the total height of the list */
+#define LIST_HEIGHT(clist) (((clist)->row_height * ((clist)->rows)) + \
+ (CELL_SPACING * ((clist)->rows + 1)))
+
+
+/* returns the total width of the list */
+static inline gint
+LIST_WIDTH (GtkCMCList * clist)
+{
+ gint last_column;
+
+ for (last_column = clist->columns - 1;
+ last_column >= 0 && !clist->column[last_column].visible; last_column--);
+
+ if (last_column >= 0)
+ return (clist->column[last_column].area.x +
+ clist->column[last_column].area.width +
+ COLUMN_INSET + CELL_SPACING);
+ return 0;
+}
+
+/* returns the GList item for the nth row */
+#define ROW_ELEMENT(clist, row) (((row) == (clist)->rows - 1) ? \
+ (clist)->row_list_end : \
+ g_list_nth ((clist)->row_list, (row)))
+
+
+/* redraw the list if it's not frozen */
+#define CLIST_UNFROZEN(clist) (((GtkCMCList*) (clist))->freeze_count == 0)
+#define CLIST_REFRESH(clist) G_STMT_START { \
+ if (CLIST_UNFROZEN (clist)) \
+ GTK_CMCLIST_GET_CLASS (clist)->refresh ((GtkCMCList*) (clist)); \
+} G_STMT_END
+
+
+/* Signals */
+enum {
+ SELECT_ROW,
+ UNSELECT_ROW,
+ ROW_MOVE,
+ CLICK_COLUMN,
+ RESIZE_COLUMN,
+ TOGGLE_FOCUS_ROW,
+ SELECT_ALL,
+ UNSELECT_ALL,
+ UNDO_SELECTION,
+ START_SELECTION,
+ END_SELECTION,
+ TOGGLE_ADD_MODE,
+ EXTEND_SELECTION,
+ SCROLL_VERTICAL,
+ SCROLL_HORIZONTAL,
+ ABORT_COLUMN_RESIZE,
+ LAST_SIGNAL
+};
+
+enum {
+ SYNC_REMOVE,
+ SYNC_INSERT
+};
+
+enum {
+ ARG_0,
+ ARG_N_COLUMNS,
+ ARG_SHADOW_TYPE,
+ ARG_SELECTION_MODE,
+ ARG_ROW_HEIGHT,
+ ARG_TITLES_ACTIVE,
+ ARG_REORDERABLE,
+ ARG_USE_DRAG_ICONS,
+ ARG_SORT_TYPE
+};
+
+/* GtkCMCList Methods */
+static void gtk_cmclist_class_init (GtkCMCListClass *klass);
+static void gtk_cmclist_init (GtkCMCList *clist);
+static GObject* gtk_cmclist_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params);
+
+/* GtkObject Methods */
+static void gtk_cmclist_destroy (GtkObject *object);
+static void gtk_cmclist_finalize (GObject *object);
+static void gtk_cmclist_set_arg (GObject *object,
+ guint arg_id,
+ const GValue *value,
+ GParamSpec *spec);
+static void gtk_cmclist_get_arg (GObject *object,
+ guint arg_id,
+ GValue *value,
+ GParamSpec *spec);
+
+/* GtkWidget Methods */
+static void gtk_cmclist_set_scroll_adjustments (GtkCMCList *clist,
+ GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment);
+static void gtk_cmclist_realize (GtkWidget *widget);
+static void gtk_cmclist_unrealize (GtkWidget *widget);
+static void gtk_cmclist_map (GtkWidget *widget);
+static void gtk_cmclist_unmap (GtkWidget *widget);
+static gint gtk_cmclist_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_cmclist_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_cmclist_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_cmclist_motion (GtkWidget *widget,
+ GdkEventMotion *event);
+static void gtk_cmclist_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_cmclist_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_cmclist_draw_focus (GtkWidget *widget);
+static gint gtk_cmclist_focus_in (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint gtk_cmclist_focus_out (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint gtk_cmclist_focus (GtkWidget *widget,
+ GtkDirectionType direction);
+static void gtk_cmclist_set_focus_child (GtkContainer *container,
+ GtkWidget *child);
+static void gtk_cmclist_style_set (GtkWidget *widget,
+ GtkStyle *previous_style);
+static void gtk_cmclist_drag_begin (GtkWidget *widget,
+ GdkDragContext *context);
+static gint gtk_cmclist_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time);
+static void gtk_cmclist_drag_leave (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time);
+static void gtk_cmclist_drag_end (GtkWidget *widget,
+ GdkDragContext *context);
+static gboolean gtk_cmclist_drag_drop (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time);
+static void gtk_cmclist_drag_data_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time);
+static void gtk_cmclist_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time);
+
+/* GtkContainer Methods */
+static void gtk_cmclist_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
+
+/* Selection */
+static void toggle_row (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event);
+static void real_select_row (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event);
+static void real_unselect_row (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event);
+static void update_extended_selection (GtkCMCList *clist,
+ gint row);
+static GList *selection_find (GtkCMCList *clist,
+ gint row_number,
+ GList *row_list_element);
+static void real_select_all (GtkCMCList *clist);
+static void real_unselect_all (GtkCMCList *clist);
+static void move_vertical (GtkCMCList *clist,
+ gint row,
+ gfloat align);
+static void move_horizontal (GtkCMCList *clist,
+ gint diff);
+static void real_undo_selection (GtkCMCList *clist);
+static void fake_unselect_all (GtkCMCList *clist,
+ gint row);
+static void fake_toggle_row (GtkCMCList *clist,
+ gint row);
+static void resync_selection (GtkCMCList *clist,
+ GdkEvent *event);
+static void sync_selection (GtkCMCList *clist,
+ gint row,
+ gint mode);
+static void set_anchor (GtkCMCList *clist,
+ gboolean add_mode,
+ gint anchor,
+ gint undo_anchor);
+static void start_selection (GtkCMCList *clist);
+static void end_selection (GtkCMCList *clist);
+static void toggle_add_mode (GtkCMCList *clist);
+static void toggle_focus_row (GtkCMCList *clist);
+static void extend_selection (GtkCMCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position,
+ gboolean auto_start_selection);
+static gint get_selection_info (GtkCMCList *clist,
+ gint x,
+ gint y,
+ gint *row,
+ gint *column);
+
+/* Scrolling */
+static void move_focus_row (GtkCMCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position);
+static void scroll_horizontal (GtkCMCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position);
+static void scroll_vertical (GtkCMCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position);
+static void move_horizontal (GtkCMCList *clist,
+ gint diff);
+static void move_vertical (GtkCMCList *clist,
+ gint row,
+ gfloat align);
+static gint horizontal_timeout (GtkCMCList *clist);
+static gint vertical_timeout (GtkCMCList *clist);
+static void remove_grab (GtkCMCList *clist);
+
+
+/* Resize Columns */
+static void draw_xor_line (GtkCMCList *clist);
+static gint new_column_width (GtkCMCList *clist,
+ gint column,
+ gint *x);
+static void column_auto_resize (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ gint old_width);
+static void real_resize_column (GtkCMCList *clist,
+ gint column,
+ gint width);
+static void abort_column_resize (GtkCMCList *clist);
+static void cell_size_request (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ GtkRequisition *requisition);
+
+/* Buttons */
+static void column_button_create (GtkCMCList *clist,
+ gint column);
+static void column_button_clicked (GtkWidget *widget,
+ gpointer data);
+
+/* Adjustments */
+static void adjust_adjustments (GtkCMCList *clist,
+ gboolean block_resize);
+static void vadjustment_changed (GtkAdjustment *adjustment,
+ gpointer data);
+static void vadjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data);
+static void hadjustment_changed (GtkAdjustment *adjustment,
+ gpointer data);
+static void hadjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data);
+
+/* Drawing */
+static void get_cell_style (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint state,
+ gint column,
+ GtkStyle **style,
+ GdkGC **fg_gc,
+ GdkGC **bg_gc);
+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 draw_row (GtkCMCList *clist,
+ GdkRectangle *area,
+ gint row,
+ GtkCMCListRow *clist_row);
+static void draw_rows (GtkCMCList *clist,
+ GdkRectangle *area);
+static void clist_refresh (GtkCMCList *clist);
+static void draw_drag_highlight (GtkCMCList *clist,
+ GtkCMCListRow *dest_row,
+ gint dest_row_number,
+ GtkCMCListDragPos drag_pos);
+
+/* Size Allocation / Requisition */
+static void size_allocate_title_buttons (GtkCMCList *clist);
+static void size_allocate_columns (GtkCMCList *clist,
+ gboolean block_resize);
+static gint list_requisition_width (GtkCMCList *clist);
+
+/* Memory Allocation/Distruction Routines */
+static GtkCMCListColumn *columns_new (GtkCMCList *clist);
+static void column_title_new (GtkCMCList *clist,
+ gint column,
+ const gchar *title);
+static void columns_delete (GtkCMCList *clist);
+static GtkCMCListRow *row_new (GtkCMCList *clist);
+static void row_delete (GtkCMCList *clist,
+ GtkCMCListRow *clist_row);
+static void set_cell_contents (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ GtkCMCellType type,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask);
+static gint real_insert_row (GtkCMCList *clist,
+ gint row,
+ gchar *text[]);
+static void real_remove_row (GtkCMCList *clist,
+ gint row);
+static void real_clear (GtkCMCList *clist);
+
+/* Sorting */
+static gint default_compare (GtkCMCList *clist,
+ gconstpointer row1,
+ gconstpointer row2);
+static void real_sort_list (GtkCMCList *clist);
+static GList *gtk_cmclist_merge (GtkCMCList *clist,
+ GList *a,
+ GList *b);
+static GList *gtk_cmclist_mergesort (GtkCMCList *clist,
+ GList *list,
+ gint num);
+/* Misc */
+static gboolean title_focus_in (GtkCMCList *clist,
+ gint dir);
+static gboolean title_focus_move (GtkCMCList *clist,
+ gint dir);
+
+static void real_row_move (GtkCMCList *clist,
+ gint source_row,
+ gint dest_row);
+static gint column_title_passive_func (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data);
+static void drag_dest_cell (GtkCMCList *clist,
+ gint x,
+ gint y,
+ GtkCMCListDestInfo *dest_info);
+
+
+
+static GtkContainerClass *parent_class = NULL;
+static guint clist_signals[LAST_SIGNAL] = {0};
+
+static const GtkTargetEntry clist_target_table = { "gtk-clist-drag-reorder", 0, 0};
+
+GType
+gtk_cmclist_get_type (void)
+{
+ static GType clist_type = 0;
+
+ if (!clist_type)
+ {
+ static const GTypeInfo clist_info =
+ {
+ sizeof (GtkCMCListClass),
+
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+
+ (GClassInitFunc) gtk_cmclist_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+
+ sizeof (GtkCMCList),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gtk_cmclist_init,
+ };
+ clist_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkCMCList", &clist_info, (GTypeFlags)0);
+ }
+
+ return clist_type;
+}
+
+static void
+gtk_cmclist_class_init (GtkCMCListClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkObjectClass *gtk_object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+ GtkBindingSet *binding_set;
+
+ object_class->constructor = gtk_cmclist_constructor;
+
+ gtk_object_class = (GtkObjectClass *) klass;
+ widget_class = (GtkWidgetClass *) klass;
+ container_class = (GtkContainerClass *) klass;
+
+ parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
+
+ object_class->finalize = gtk_cmclist_finalize;
+ gtk_object_class->destroy = gtk_cmclist_destroy;
+ object_class->set_property = gtk_cmclist_set_arg;
+ object_class->get_property = gtk_cmclist_get_arg;
+
+
+ widget_class->realize = gtk_cmclist_realize;
+ widget_class->unrealize = gtk_cmclist_unrealize;
+ widget_class->map = gtk_cmclist_map;
+ widget_class->unmap = gtk_cmclist_unmap;
+ widget_class->button_press_event = gtk_cmclist_button_press;
+ widget_class->button_release_event = gtk_cmclist_button_release;
+ widget_class->motion_notify_event = gtk_cmclist_motion;
+ widget_class->expose_event = gtk_cmclist_expose;
+ widget_class->size_request = gtk_cmclist_size_request;
+ widget_class->size_allocate = gtk_cmclist_size_allocate;
+ widget_class->focus_in_event = gtk_cmclist_focus_in;
+ widget_class->focus_out_event = gtk_cmclist_focus_out;
+ widget_class->style_set = gtk_cmclist_style_set;
+ widget_class->drag_begin = gtk_cmclist_drag_begin;
+ widget_class->drag_end = gtk_cmclist_drag_end;
+ widget_class->drag_motion = gtk_cmclist_drag_motion;
+ widget_class->drag_leave = gtk_cmclist_drag_leave;
+ widget_class->drag_drop = gtk_cmclist_drag_drop;
+ widget_class->drag_data_get = gtk_cmclist_drag_data_get;
+ widget_class->drag_data_received = gtk_cmclist_drag_data_received;
+ widget_class->focus = gtk_cmclist_focus;
+
+ /* container_class->add = NULL; use the default GtkContainerClass warning */
+ /* container_class->remove=NULL; use the default GtkContainerClass warning */
+
+ container_class->forall = gtk_cmclist_forall;
+ container_class->set_focus_child = gtk_cmclist_set_focus_child;
+
+ klass->set_scroll_adjustments = gtk_cmclist_set_scroll_adjustments;
+ klass->refresh = clist_refresh;
+ klass->select_row = real_select_row;
+ klass->unselect_row = real_unselect_row;
+ klass->row_move = real_row_move;
+ klass->undo_selection = real_undo_selection;
+ klass->resync_selection = resync_selection;
+ klass->selection_find = selection_find;
+ klass->click_column = NULL;
+ klass->resize_column = real_resize_column;
+ klass->draw_row = draw_row;
+ klass->draw_drag_highlight = draw_drag_highlight;
+ klass->insert_row = real_insert_row;
+ klass->remove_row = real_remove_row;
+ klass->clear = real_clear;
+ klass->sort_list = real_sort_list;
+ klass->select_all = real_select_all;
+ klass->unselect_all = real_unselect_all;
+ klass->fake_unselect_all = fake_unselect_all;
+ klass->scroll_horizontal = scroll_horizontal;
+ klass->scroll_vertical = scroll_vertical;
+ klass->extend_selection = extend_selection;
+ klass->toggle_focus_row = toggle_focus_row;
+ klass->toggle_add_mode = toggle_add_mode;
+ klass->start_selection = start_selection;
+ klass->end_selection = end_selection;
+ klass->abort_column_resize = abort_column_resize;
+ klass->set_cell_contents = set_cell_contents;
+ klass->cell_size_request = cell_size_request;
+
+ g_object_class_install_property (object_class,
+ ARG_N_COLUMNS,
+ g_param_spec_uint ("n-columns",
+ "N-Columns",
+ "N-Columns",
+ 1,
+ G_MAXINT,
+ 1,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ ARG_SHADOW_TYPE,
+ g_param_spec_enum ("shadow-type",
+ "shadow-type",
+ "shadow-type",
+ GTK_TYPE_SHADOW_TYPE, 0,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ ARG_SELECTION_MODE,
+ g_param_spec_enum ("selection-mode",
+ "selection-mode",
+ "selection-mode",
+ GTK_TYPE_SELECTION_MODE, 0,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ ARG_ROW_HEIGHT,
+ g_param_spec_uint ("row-height",
+ "row-height",
+ "row-height",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ ARG_REORDERABLE,
+ g_param_spec_boolean ("reorderable",
+ "reorderable",
+ "reorderable",
+ TRUE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ ARG_TITLES_ACTIVE,
+ g_param_spec_boolean ("titles-active",
+ "titles-active",
+ "titles-active",
+ TRUE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ ARG_USE_DRAG_ICONS,
+ g_param_spec_boolean ("use-drag-icons",
+ "use-drag-icons",
+ "use-drag-icons",
+ TRUE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ ARG_SORT_TYPE,
+ g_param_spec_enum ("sort-type",
+ "sort-type",
+ "sort-type",
+ GTK_TYPE_SORT_TYPE, 0,
+ G_PARAM_READWRITE));
+ widget_class->set_scroll_adjustments_signal =
+ g_signal_new ("set_scroll_adjustments",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkCMCListClass, set_scroll_adjustments),
+ NULL, NULL,
+ claws_marshal_VOID__OBJECT_OBJECT,
+ G_TYPE_NONE, 2,
+ GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
+
+ clist_signals[SELECT_ROW] =
+ g_signal_new ("select_row",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkCMCListClass, select_row),
+ NULL, NULL,
+ claws_marshal_VOID__INT_INT_BOXED,
+ G_TYPE_NONE, 3,
+ G_TYPE_INT,
+ G_TYPE_INT,
+ GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+ clist_signals[UNSELECT_ROW] =
+ g_signal_new ("unselect_row",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkCMCListClass, unselect_row),
+ NULL, NULL,
+ claws_marshal_VOID__INT_INT_BOXED,
+ G_TYPE_NONE, 3,
+ G_TYPE_INT,
+ G_TYPE_INT,
+ GDK_TYPE_EVENT);
+ clist_signals[ROW_MOVE] =
+ g_signal_new ("row_move",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkCMCListClass, row_move),
+ NULL, NULL,
+ claws_marshal_VOID__INT_INT,
+ G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+ clist_signals[CLICK_COLUMN] =
+ g_signal_new ("click_column",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkCMCListClass, click_column),
+ NULL, NULL,
+ claws_marshal_VOID__INT,
+ G_TYPE_NONE, 1, G_TYPE_INT);
+ clist_signals[RESIZE_COLUMN] =
+ g_signal_new ("resize_column",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkCMCListClass, resize_column),
+ NULL, NULL,
+ claws_marshal_VOID__INT_INT,
+ G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+
+ clist_signals[TOGGLE_FOCUS_ROW] =
+ g_signal_new ("toggle_focus_row",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkCMCListClass, toggle_focus_row),
+ NULL, NULL,
+ claws_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ clist_signals[SELECT_ALL] =
+ g_signal_new ("select_all",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkCMCListClass, select_all),
+ NULL, NULL,
+ claws_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ clist_signals[UNSELECT_ALL] =
+ g_signal_new ("unselect_all",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkCMCListClass, unselect_all),
+ NULL, NULL,
+ claws_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ clist_signals[UNDO_SELECTION] =
+ g_signal_new ("undo_selection",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkCMCListClass, undo_selection),
+ NULL, NULL,
+ claws_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ clist_signals[START_SELECTION] =
+ g_signal_new ("start_selection",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkCMCListClass, start_selection),
+ NULL, NULL,
+ claws_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ clist_signals[END_SELECTION] =
+ g_signal_new ("end_selection",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkCMCListClass, end_selection),
+ NULL, NULL,
+ claws_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ clist_signals[TOGGLE_ADD_MODE] =
+ g_signal_new ("toggle_add_mode",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkCMCListClass, toggle_add_mode),
+ NULL, NULL,
+ claws_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ clist_signals[EXTEND_SELECTION] =
+ g_signal_new ("extend_selection",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkCMCListClass, extend_selection),
+ NULL, NULL,
+ claws_marshal_VOID__ENUM_FLOAT_BOOLEAN,
+ G_TYPE_NONE, 3, GTK_TYPE_SCROLL_TYPE, G_TYPE_FLOAT, G_TYPE_BOOLEAN);
+ clist_signals[SCROLL_VERTICAL] =
+ g_signal_new ("scroll_vertical",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkCMCListClass, scroll_vertical),
+ NULL, NULL,
+ claws_marshal_VOID__ENUM_FLOAT,
+ G_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, G_TYPE_FLOAT);
+ clist_signals[SCROLL_HORIZONTAL] =
+ g_signal_new ("scroll_horizontal",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkCMCListClass, scroll_horizontal),
+ NULL, NULL,
+ claws_marshal_VOID__ENUM_FLOAT,
+ G_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, G_TYPE_FLOAT);
+ clist_signals[ABORT_COLUMN_RESIZE] =
+ g_signal_new ("abort_column_resize",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkCMCListClass, abort_column_resize),
+ NULL, NULL,
+ claws_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ binding_set = gtk_binding_set_by_class (klass);
+ gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
+ "scroll_vertical", 2,
+ G_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+ G_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
+ "scroll_vertical", 2,
+ G_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+ G_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
+ "scroll_vertical", 2,
+ G_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+ G_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
+ "scroll_vertical", 2,
+ G_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+ G_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
+ "scroll_vertical", 2,
+ G_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
+ G_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, 0,
+ "scroll_vertical", 2,
+ G_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
+ G_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
+ "scroll_vertical", 2,
+ G_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
+ G_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, 0,
+ "scroll_vertical", 2,
+ G_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
+ G_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
+ "scroll_vertical", 2,
+ G_TYPE_ENUM, GTK_SCROLL_JUMP,
+ G_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, GDK_CONTROL_MASK,
+ "scroll_vertical", 2,
+ G_TYPE_ENUM, GTK_SCROLL_JUMP,
+ G_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
+ "scroll_vertical", 2,
+ G_TYPE_ENUM, GTK_SCROLL_JUMP,
+ G_TYPE_FLOAT, 1.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_End, GDK_CONTROL_MASK,
+ "scroll_vertical", 2,
+ G_TYPE_ENUM, GTK_SCROLL_JUMP,
+ G_TYPE_FLOAT, 1.0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Up, GDK_SHIFT_MASK,
+ "extend_selection", 3,
+ G_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+ G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, GDK_SHIFT_MASK,
+ "extend_selection", 3,
+ G_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+ G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_Down, GDK_SHIFT_MASK,
+ "extend_selection", 3,
+ G_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+ G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, GDK_SHIFT_MASK,
+ "extend_selection", 3,
+ G_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+ G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_SHIFT_MASK,
+ "extend_selection", 3,
+ G_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
+ G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, GDK_SHIFT_MASK,
+ "extend_selection", 3,
+ G_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
+ G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_SHIFT_MASK,
+ "extend_selection", 3,
+ G_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
+ G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, GDK_SHIFT_MASK,
+ "extend_selection", 3,
+ G_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
+ G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_Home,
+ GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "extend_selection", 3,
+ G_TYPE_ENUM, GTK_SCROLL_JUMP,
+ G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Home,
+ GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "extend_selection", 3,
+ G_TYPE_ENUM, GTK_SCROLL_JUMP,
+ G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_End,
+ GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "extend_selection", 3,
+ G_TYPE_ENUM, GTK_SCROLL_JUMP,
+ G_TYPE_FLOAT, 1.0, G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_End,
+ GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "extend_selection", 3,
+ G_TYPE_ENUM, GTK_SCROLL_JUMP,
+ G_TYPE_FLOAT, 1.0, G_TYPE_BOOLEAN, TRUE);
+
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
+ "scroll_horizontal", 2,
+ G_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+ G_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
+ "scroll_horizontal", 2,
+ G_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+ G_TYPE_FLOAT, 0.0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
+ "scroll_horizontal", 2,
+ G_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+ G_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
+ "scroll_horizontal", 2,
+ G_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+ G_TYPE_FLOAT, 0.0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
+ "scroll_horizontal", 2,
+ G_TYPE_ENUM, GTK_SCROLL_JUMP,
+ G_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
+ "scroll_horizontal", 2,
+ G_TYPE_ENUM, GTK_SCROLL_JUMP,
+ G_TYPE_FLOAT, 0.0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
+ "scroll_horizontal", 2,
+ G_TYPE_ENUM, GTK_SCROLL_JUMP,
+ G_TYPE_FLOAT, 1.0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
+ "scroll_horizontal", 2,
+ G_TYPE_ENUM, GTK_SCROLL_JUMP,
+ G_TYPE_FLOAT, 1.0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
+ "undo_selection", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
+ "abort_column_resize", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
+ "toggle_focus_row", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
+ "toggle_focus_row", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
+ "toggle_add_mode", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_CONTROL_MASK,
+ "toggle_add_mode", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK,
+ "select_all", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Divide, GDK_CONTROL_MASK,
+ "select_all", 0);
+ gtk_binding_entry_add_signal (binding_set, '\\', GDK_CONTROL_MASK,
+ "unselect_all", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
+ GDK_RELEASE_MASK | GDK_SHIFT_MASK,
+ "end_selection", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
+ GDK_RELEASE_MASK | GDK_SHIFT_MASK,
+ "end_selection", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
+ GDK_RELEASE_MASK | GDK_SHIFT_MASK |
+ GDK_CONTROL_MASK,
+ "end_selection", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
+ GDK_RELEASE_MASK | GDK_SHIFT_MASK |
+ GDK_CONTROL_MASK,
+ "end_selection", 0);
+}
+
+static void
+gtk_cmclist_set_arg (GObject *object,
+ guint arg_id,
+ const GValue *value,
+ GParamSpec *spec)
+{
+ GtkCMCList *clist;
+
+ clist = GTK_CMCLIST (object);
+
+ switch (arg_id)
+ {
+ case ARG_N_COLUMNS: /* only set at construction time */
+ clist->columns = MAX (1, g_value_get_uint (value));
+ break;
+ case ARG_SHADOW_TYPE:
+ gtk_cmclist_set_shadow_type (clist, g_value_get_enum (value));
+ break;
+ case ARG_SELECTION_MODE:
+ gtk_cmclist_set_selection_mode (clist, g_value_get_enum (value));
+ break;
+ case ARG_ROW_HEIGHT:
+ gtk_cmclist_set_row_height (clist, g_value_get_uint (value));
+ break;
+ case ARG_REORDERABLE:
+ gtk_cmclist_set_reorderable (clist, g_value_get_boolean (value));
+ break;
+ case ARG_TITLES_ACTIVE:
+ if (g_value_get_boolean (value))
+ gtk_cmclist_column_titles_active (clist);
+ else
+ gtk_cmclist_column_titles_passive (clist);
+ break;
+ case ARG_USE_DRAG_ICONS:
+ gtk_cmclist_set_use_drag_icons (clist, g_value_get_boolean (value));
+ break;
+ case ARG_SORT_TYPE:
+ gtk_cmclist_set_sort_type (clist, g_value_get_enum (value));
+ break;
+ }
+}
+
+static void
+gtk_cmclist_get_arg (GObject *object,
+ guint arg_id,
+ GValue *value,
+ GParamSpec *spec)
+{
+ GtkCMCList *clist;
+
+ clist = GTK_CMCLIST (object);
+
+ switch (arg_id)
+ {
+ guint i;
+
+ case ARG_N_COLUMNS:
+ g_value_set_uint(value, clist->columns);
+ break;
+ case ARG_SHADOW_TYPE:
+ g_value_set_enum(value, clist->shadow_type);
+ break;
+ case ARG_SELECTION_MODE:
+ g_value_set_enum(value, clist->selection_mode);
+ break;
+ case ARG_ROW_HEIGHT:
+ g_value_set_uint(value, GTK_CMCLIST_ROW_HEIGHT_SET(clist) ? clist->row_height : 0);
+ break;
+ case ARG_REORDERABLE:
+ g_value_set_boolean(value, GTK_CMCLIST_REORDERABLE (clist));
+ break;
+ case ARG_TITLES_ACTIVE:
+ g_value_set_boolean(value, TRUE);
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].button &&
+ !GTK_WIDGET_SENSITIVE (clist->column[i].button))
+ {
+ g_value_set_boolean(value, FALSE);
+ break;
+ }
+ break;
+ case ARG_USE_DRAG_ICONS:
+ g_value_set_boolean(value, GTK_CMCLIST_USE_DRAG_ICONS (clist));
+ break;
+ case ARG_SORT_TYPE:
+ g_value_set_enum(value, clist->sort_type);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, spec);
+ break;
+ }
+}
+
+static void
+gtk_cmclist_init (GtkCMCList *clist)
+{
+ clist->flags = 0;
+
+ GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
+ GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_DRAW_DRAG_LINE);
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_USE_DRAG_ICONS);
+
+ clist->freeze_count = 0;
+
+ clist->rows = 0;
+ clist->row_height = 0;
+ clist->row_list = NULL;
+ clist->row_list_end = NULL;
+
+ clist->columns = 0;
+
+ clist->title_window = NULL;
+ clist->column_title_area.x = 0;
+ clist->column_title_area.y = 0;
+ clist->column_title_area.width = 1;
+ clist->column_title_area.height = 1;
+
+ clist->clist_window = NULL;
+ clist->clist_window_width = 1;
+ clist->clist_window_height = 1;
+
+ clist->hoffset = 0;
+ clist->voffset = 0;
+
+ clist->shadow_type = GTK_SHADOW_IN;
+ clist->vadjustment = NULL;
+ clist->hadjustment = NULL;
+
+ clist->button_actions[0] = GTK_CMBUTTON_SELECTS | GTK_CMBUTTON_DRAGS;
+ clist->button_actions[1] = GTK_CMBUTTON_IGNORED;
+ clist->button_actions[2] = GTK_CMBUTTON_IGNORED;
+ clist->button_actions[3] = GTK_CMBUTTON_IGNORED;
+ clist->button_actions[4] = GTK_CMBUTTON_IGNORED;
+
+ clist->cursor_drag = NULL;
+ clist->xor_gc = NULL;
+ clist->fg_gc = NULL;
+ clist->bg_gc = NULL;
+ clist->x_drag = 0;
+
+ clist->selection_mode = GTK_SELECTION_SINGLE;
+ clist->selection = NULL;
+ clist->selection_end = NULL;
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+
+ clist->focus_row = -1;
+ clist->focus_header_column = -1;
+ clist->undo_anchor = -1;
+
+ clist->anchor = -1;
+ clist->anchor_state = GTK_STATE_SELECTED;
+ clist->drag_pos = -1;
+ clist->htimer = 0;
+ clist->vtimer = 0;
+
+ clist->click_cell.row = -1;
+ clist->click_cell.column = -1;
+
+ clist->compare = default_compare;
+ clist->sort_type = GTK_SORT_ASCENDING;
+ clist->sort_column = 0;
+
+ clist->drag_highlight_row = -1;
+}
+
+/* Constructor */
+static GObject*
+gtk_cmclist_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object = G_OBJECT_CLASS (parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties);
+ GtkCMCList *clist = GTK_CMCLIST (object);
+
+ /* allocate memory for columns */
+ clist->column = columns_new (clist);
+
+ /* there needs to be at least one column button
+ * because there is alot of code that will break if it
+ * isn't there
+ */
+ column_button_create (clist, 0);
+
+ return object;
+}
+
+/* GTKCLIST PUBLIC INTERFACE
+ * gtk_cmclist_new
+ * gtk_cmclist_new_with_titles
+ * gtk_cmclist_set_hadjustment
+ * gtk_cmclist_set_vadjustment
+ * gtk_cmclist_get_hadjustment
+ * gtk_cmclist_get_vadjustment
+ * gtk_cmclist_set_shadow_type
+ * gtk_cmclist_set_selection_mode
+ * gtk_cmclist_freeze
+ * gtk_cmclist_thaw
+ */
+GtkWidget*
+gtk_cmclist_new (gint columns)
+{
+ return gtk_cmclist_new_with_titles (columns, NULL);
+}
+
+GtkWidget*
+gtk_cmclist_new_with_titles (gint columns,
+ gchar *titles[])
+{
+ GtkCMCList *clist;
+
+ clist = g_object_new (GTK_TYPE_CMCLIST,
+ "n_columns", columns,
+ NULL);
+ if (titles)
+ {
+ guint i;
+
+ for (i = 0; i < clist->columns; i++)
+ gtk_cmclist_set_column_title (clist, i, titles[i]);
+ gtk_cmclist_column_titles_show (clist);
+ }
+ else
+ gtk_cmclist_column_titles_hide (clist);
+
+ return GTK_WIDGET (clist);
+}
+
+void
+gtk_cmclist_set_hadjustment (GtkCMCList *clist,
+ GtkAdjustment *adjustment)
+{
+ GtkAdjustment *old_adjustment;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+ if (adjustment)
+ g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+
+ if (clist->hadjustment == adjustment)
+ return;
+
+ old_adjustment = clist->hadjustment;
+
+ if (clist->hadjustment)
+ {
+ g_signal_handlers_disconnect_matched(GTK_OBJECT (clist->hadjustment), G_SIGNAL_MATCH_DATA,
+ 0, 0, 0, 0, clist);
+
+ g_object_unref (GTK_OBJECT (clist->hadjustment));
+ }
+
+ clist->hadjustment = adjustment;
+
+ if (clist->hadjustment)
+ {
+ g_object_ref_sink (clist->hadjustment);
+
+ g_signal_connect (G_OBJECT (clist->hadjustment), "changed",
+ G_CALLBACK( hadjustment_changed),
+ (gpointer) clist);
+ g_signal_connect (G_OBJECT (clist->hadjustment), "value_changed",
+ G_CALLBACK( hadjustment_value_changed),
+ (gpointer) clist);
+ }
+
+ if (!clist->hadjustment || !old_adjustment)
+ gtk_widget_queue_resize (GTK_WIDGET (clist));
+}
+
+GtkAdjustment *
+gtk_cmclist_get_hadjustment (GtkCMCList *clist)
+{
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+ return clist->hadjustment;
+}
+
+void
+gtk_cmclist_set_vadjustment (GtkCMCList *clist,
+ GtkAdjustment *adjustment)
+{
+ GtkAdjustment *old_adjustment;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+ if (adjustment)
+ g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+
+ if (clist->vadjustment == adjustment)
+ return;
+
+ old_adjustment = clist->vadjustment;
+
+ if (clist->vadjustment)
+ {
+ g_signal_handlers_disconnect_matched(GTK_OBJECT (clist->vadjustment), G_SIGNAL_MATCH_DATA,
+ 0, 0, 0, 0, clist);
+ g_object_unref (GTK_OBJECT (clist->vadjustment));
+ }
+
+ clist->vadjustment = adjustment;
+
+ if (clist->vadjustment)
+ {
+ g_object_ref_sink (clist->vadjustment);
+
+ g_signal_connect (GTK_OBJECT (clist->vadjustment), "changed",
+ G_CALLBACK(vadjustment_changed),
+ (gpointer) clist);
+ g_signal_connect (GTK_OBJECT (clist->vadjustment), "value_changed",
+ G_CALLBACK(vadjustment_value_changed),
+ (gpointer) clist);
+ }
+
+ if (!clist->vadjustment || !old_adjustment)
+ gtk_widget_queue_resize (GTK_WIDGET (clist));
+}
+
+GtkAdjustment *
+gtk_cmclist_get_vadjustment (GtkCMCList *clist)
+{
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+ return clist->vadjustment;
+}
+
+static void
+gtk_cmclist_set_scroll_adjustments (GtkCMCList *clist,
+ GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment)
+{
+ if (clist->hadjustment != hadjustment)
+ gtk_cmclist_set_hadjustment (clist, hadjustment);
+ if (clist->vadjustment != vadjustment)
+ gtk_cmclist_set_vadjustment (clist, vadjustment);
+}
+
+void
+gtk_cmclist_set_shadow_type (GtkCMCList *clist,
+ GtkShadowType type)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ clist->shadow_type = type;
+
+ if (GTK_WIDGET_VISIBLE (clist))
+ gtk_widget_queue_resize (GTK_WIDGET (clist));
+}
+
+void
+gtk_cmclist_set_selection_mode (GtkCMCList *clist,
+ GtkSelectionMode mode)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+ g_return_if_fail (mode != GTK_SELECTION_NONE);
+
+ if (mode == clist->selection_mode)
+ return;
+
+ clist->selection_mode = mode;
+ clist->anchor = -1;
+ clist->anchor_state = GTK_STATE_SELECTED;
+ clist->drag_pos = -1;
+ clist->undo_anchor = clist->focus_row;
+
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+
+ switch (mode)
+ {
+ case GTK_SELECTION_MULTIPLE:
+ return;
+ case GTK_SELECTION_BROWSE:
+ case GTK_SELECTION_SINGLE:
+ gtk_cmclist_unselect_all (clist);
+ break;
+ default:
+ /* Someone set it by hand */
+ g_assert_not_reached ();
+ }
+}
+
+void
+gtk_cmclist_freeze (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ clist->freeze_count++;
+}
+
+void
+gtk_cmclist_thaw (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist->freeze_count)
+ {
+ clist->freeze_count--;
+ CLIST_REFRESH (clist);
+ }
+}
+
+/* PUBLIC COLUMN FUNCTIONS
+ * gtk_cmclist_column_titles_show
+ * gtk_cmclist_column_titles_hide
+ * gtk_cmclist_column_title_active
+ * gtk_cmclist_column_title_passive
+ * gtk_cmclist_column_titles_active
+ * gtk_cmclist_column_titles_passive
+ * gtk_cmclist_set_column_title
+ * gtk_cmclist_get_column_title
+ * gtk_cmclist_set_column_widget
+ * gtk_cmclist_set_column_justification
+ * gtk_cmclist_set_column_visibility
+ * gtk_cmclist_set_column_resizeable
+ * gtk_cmclist_set_column_auto_resize
+ * gtk_cmclist_optimal_column_width
+ * gtk_cmclist_set_column_width
+ * gtk_cmclist_set_column_min_width
+ * gtk_cmclist_set_column_max_width
+ */
+void
+gtk_cmclist_column_titles_show (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (!GTK_CMCLIST_SHOW_TITLES(clist))
+ {
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_SHOW_TITLES);
+ if (clist->title_window)
+ gdk_window_show (clist->title_window);
+ gtk_widget_queue_resize (GTK_WIDGET (clist));
+ }
+}
+
+void
+gtk_cmclist_column_titles_hide (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (GTK_CMCLIST_SHOW_TITLES(clist))
+ {
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_SHOW_TITLES);
+ if (clist->title_window)
+ gdk_window_hide (clist->title_window);
+ gtk_widget_queue_resize (GTK_WIDGET (clist));
+ }
+}
+
+void
+gtk_cmclist_column_title_active (GtkCMCList *clist,
+ gint column)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+ if (!clist->column[column].button || !clist->column[column].button_passive)
+ return;
+
+ clist->column[column].button_passive = FALSE;
+
+ g_signal_handlers_disconnect_matched(GTK_OBJECT (clist->column[column].button), G_SIGNAL_MATCH_FUNC,
+ 0, 0, 0, column_title_passive_func, 0);
+
+ GTK_WIDGET_SET_FLAGS (clist->column[column].button, GTK_CAN_FOCUS);
+ if (GTK_WIDGET_VISIBLE (clist))
+ gtk_widget_queue_draw (clist->column[column].button);
+}
+
+void
+gtk_cmclist_column_title_passive (GtkCMCList *clist,
+ gint column)
+{
+ GtkButton *button;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+ if (!clist->column[column].button || clist->column[column].button_passive)
+ return;
+
+ button = GTK_BUTTON (clist->column[column].button);
+
+ clist->column[column].button_passive = TRUE;
+
+ if (button->button_down)
+ gtk_button_released (button);
+ if (button->in_button)
+ gtk_button_leave (button);
+
+ g_signal_connect (G_OBJECT (clist->column[column].button), "event",
+ G_CALLBACK(column_title_passive_func), NULL);
+
+ GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_CAN_FOCUS);
+ if (GTK_WIDGET_VISIBLE (clist))
+ gtk_widget_queue_draw (clist->column[column].button);
+}
+
+void
+gtk_cmclist_column_titles_active (GtkCMCList *clist)
+{
+ gint i;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ for (i = 0; i < clist->columns; i++)
+ gtk_cmclist_column_title_active (clist, i);
+}
+
+void
+gtk_cmclist_column_titles_passive (GtkCMCList *clist)
+{
+ gint i;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ for (i = 0; i < clist->columns; i++)
+ gtk_cmclist_column_title_passive (clist, i);
+}
+
+void
+gtk_cmclist_set_column_title (GtkCMCList *clist,
+ gint column,
+ const gchar *title)
+{
+ gint new_button = 0;
+ GtkWidget *old_widget;
+ GtkWidget *alignment = NULL;
+ GtkWidget *label;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+
+ /* if the column button doesn't currently exist,
+ * it has to be created first */
+ if (!clist->column[column].button)
+ {
+ column_button_create (clist, column);
+ new_button = 1;
+ }
+
+ column_title_new (clist, column, title);
+
+ /* remove and destroy the old widget */
+ old_widget = GTK_BIN (clist->column[column].button)->child;
+ if (old_widget)
+ gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
+
+ /* create new alignment based no column justification */
+ switch (clist->column[column].justification)
+ {
+ case GTK_JUSTIFY_LEFT:
+ alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
+ break;
+
+ case GTK_JUSTIFY_RIGHT:
+ alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
+ break;
+
+ case GTK_JUSTIFY_CENTER:
+ alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
+ break;
+
+ case GTK_JUSTIFY_FILL:
+ alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
+ break;
+ }
+
+ gtk_widget_push_composite_child ();
+ label = gtk_label_new (clist->column[column].title);
+ gtk_widget_pop_composite_child ();
+ gtk_container_add (GTK_CONTAINER (alignment), label);
+ gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
+ gtk_widget_show (label);
+ gtk_widget_show (alignment);
+
+ /* if this button didn't previously exist, then the
+ * column button positions have to be re-computed */
+ if (GTK_WIDGET_VISIBLE (clist) && new_button)
+ size_allocate_title_buttons (clist);
+}
+
+gchar *
+gtk_cmclist_get_column_title (GtkCMCList *clist,
+ gint column)
+{
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+ if (column < 0 || column >= clist->columns)
+ return NULL;
+
+ return clist->column[column].title;
+}
+
+void
+gtk_cmclist_set_column_widget (GtkCMCList *clist,
+ gint column,
+ GtkWidget *widget)
+{
+ gint new_button = 0;
+ GtkWidget *old_widget;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+
+ /* if the column button doesn't currently exist,
+ * it has to be created first */
+ if (!clist->column[column].button)
+ {
+ column_button_create (clist, column);
+ new_button = 1;
+ }
+
+ column_title_new (clist, column, NULL);
+
+ /* remove and destroy the old widget */
+ old_widget = GTK_BIN (clist->column[column].button)->child;
+ if (old_widget)
+ gtk_container_remove (GTK_CONTAINER (clist->column[column].button),
+ old_widget);
+
+ /* add and show the widget */
+ if (widget)
+ {
+ gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
+ gtk_widget_show (widget);
+ }
+
+ /* if this button didn't previously exist, then the
+ * column button positions have to be re-computed */
+ if (GTK_WIDGET_VISIBLE (clist) && new_button)
+ size_allocate_title_buttons (clist);
+}
+
+GtkWidget *
+gtk_cmclist_get_column_widget (GtkCMCList *clist,
+ gint column)
+{
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+ if (column < 0 || column >= clist->columns)
+ return NULL;
+
+ if (clist->column[column].button)
+ return GTK_BIN (clist->column[column].button)->child;
+
+ return NULL;
+}
+
+void
+gtk_cmclist_set_column_justification (GtkCMCList *clist,
+ gint column,
+ GtkJustification justification)
+{
+ GtkWidget *alignment;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+
+ clist->column[column].justification = justification;
+
+ /* change the alinment of the button title if it's not a
+ * custom widget */
+ if (clist->column[column].title)
+ {
+ alignment = GTK_BIN (clist->column[column].button)->child;
+
+ switch (clist->column[column].justification)
+ {
+ case GTK_JUSTIFY_LEFT:
+ gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
+ break;
+
+ case GTK_JUSTIFY_RIGHT:
+ gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
+ break;
+
+ case GTK_JUSTIFY_CENTER:
+ gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
+ break;
+
+ case GTK_JUSTIFY_FILL:
+ gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (CLIST_UNFROZEN (clist))
+ draw_rows (clist, NULL);
+}
+
+void
+gtk_cmclist_set_column_visibility (GtkCMCList *clist,
+ gint column,
+ gboolean visible)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+ if (clist->column[column].visible == visible)
+ return;
+
+ /* don't hide last visible column */
+ if (!visible)
+ {
+ gint i;
+ gint vis_columns = 0;
+
+ for (i = 0, vis_columns = 0; i < clist->columns && vis_columns < 2; i++)
+ if (clist->column[i].visible)
+ vis_columns++;
+
+ if (vis_columns < 2)
+ return;
+ }
+
+ clist->column[column].visible = visible;
+
+ if (clist->column[column].button)
+ {
+ if (visible)
+ gtk_widget_show (clist->column[column].button);
+ else
+ gtk_widget_hide (clist->column[column].button);
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET(clist));
+}
+
+void
+gtk_cmclist_set_column_resizeable (GtkCMCList *clist,
+ gint column,
+ gboolean resizeable)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+ if (clist->column[column].resizeable == resizeable)
+ return;
+
+ clist->column[column].resizeable = resizeable;
+ if (resizeable)
+ clist->column[column].auto_resize = FALSE;
+
+ if (GTK_WIDGET_VISIBLE (clist))
+ size_allocate_title_buttons (clist);
+}
+
+void
+gtk_cmclist_set_column_auto_resize (GtkCMCList *clist,
+ gint column,
+ gboolean auto_resize)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+ if (clist->column[column].auto_resize == auto_resize)
+ return;
+
+ clist->column[column].auto_resize = auto_resize;
+ if (auto_resize)
+ {
+ clist->column[column].resizeable = FALSE;
+ if (!GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ {
+ gint width;
+
+ width = gtk_cmclist_optimal_column_width (clist, column);
+ gtk_cmclist_set_column_width (clist, column, width);
+ }
+ }
+
+ if (GTK_WIDGET_VISIBLE (clist))
+ size_allocate_title_buttons (clist);
+}
+
+gint
+gtk_cmclist_columns_autosize (GtkCMCList *clist)
+{
+ gint i;
+ gint width;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+
+ gtk_cmclist_freeze (clist);
+ width = 0;
+ for (i = 0; i < clist->columns; i++)
+ {
+ gtk_cmclist_set_column_width (clist, i,
+ gtk_cmclist_optimal_column_width (clist, i));
+
+ width += clist->column[i].width;
+ }
+
+ gtk_cmclist_thaw (clist);
+ return width;
+}
+
+gint
+gtk_cmclist_optimal_column_width (GtkCMCList *clist,
+ gint column)
+{
+ GtkRequisition requisition;
+ GList *list;
+ gint width;
+
+ g_return_val_if_fail (GTK_CMCLIST (clist), 0);
+
+ if (column < 0 || column >= clist->columns)
+ return 0;
+
+ if (GTK_CMCLIST_SHOW_TITLES(clist) && clist->column[column].button)
+ width = (clist->column[column].button->requisition.width)
+#if 0
+ (CELL_SPACING + (2 * COLUMN_INSET)))
+#endif
+ ;
+ else
+ width = 0;
+
+ for (list = clist->row_list; list; list = list->next)
+ {
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+ (clist, GTK_CMCLIST_ROW (list), column, &requisition);
+ width = MAX (width, requisition.width);
+ }
+
+ return width;
+}
+
+void
+gtk_cmclist_set_column_width (GtkCMCList *clist,
+ gint column,
+ gint width)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[RESIZE_COLUMN], 0,
+ column, width);
+}
+
+void
+gtk_cmclist_set_column_min_width (GtkCMCList *clist,
+ gint column,
+ gint min_width)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+ if (clist->column[column].min_width == min_width)
+ return;
+
+ if (clist->column[column].max_width >= 0 &&
+ clist->column[column].max_width < min_width)
+ clist->column[column].min_width = clist->column[column].max_width;
+ else
+ clist->column[column].min_width = min_width;
+
+ if (clist->column[column].area.width < clist->column[column].min_width)
+ gtk_cmclist_set_column_width (clist, column,clist->column[column].min_width);
+}
+
+void
+gtk_cmclist_set_column_max_width (GtkCMCList *clist,
+ gint column,
+ gint max_width)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+ if (clist->column[column].max_width == max_width)
+ return;
+
+ if (clist->column[column].min_width >= 0 && max_width >= 0 &&
+ clist->column[column].min_width > max_width)
+ clist->column[column].max_width = clist->column[column].min_width;
+ else
+ clist->column[column].max_width = max_width;
+
+ if (clist->column[column].area.width > clist->column[column].max_width)
+ gtk_cmclist_set_column_width (clist, column,clist->column[column].max_width);
+}
+
+/* PRIVATE COLUMN FUNCTIONS
+ * column_auto_resize
+ * real_resize_column
+ * abort_column_resize
+ * size_allocate_title_buttons
+ * size_allocate_columns
+ * list_requisition_width
+ * new_column_width
+ * column_button_create
+ * column_button_clicked
+ * column_title_passive_func
+ */
+static void
+column_auto_resize (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ gint old_width)
+{
+ /* resize column if needed for auto_resize */
+ GtkRequisition requisition;
+
+ if (!clist->column[column].auto_resize ||
+ GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ return;
+
+ if (clist_row)
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+ column, &requisition);
+ else
+ requisition.width = 0;
+
+ if (requisition.width > clist->column[column].width)
+ gtk_cmclist_set_column_width (clist, column, requisition.width);
+ else if (requisition.width < old_width &&
+ old_width == clist->column[column].width)
+ {
+ GList *list;
+ gint new_width = 0;
+
+ /* run a "gtk_cmclist_optimal_column_width" but break, if
+ * the column doesn't shrink */
+ if (GTK_CMCLIST_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_CMCLIST_GET_CLASS (clist)->cell_size_request
+ (clist, GTK_CMCLIST_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_cmclist_set_column_width
+ (clist, column, MAX (new_width, clist->column[column].min_width));
+ }
+}
+
+static void
+real_resize_column (GtkCMCList *clist,
+ gint column,
+ gint width)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+
+ if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
+ width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
+ if (clist->column[column].max_width >= 0 &&
+ width > clist->column[column].max_width)
+ width = clist->column[column].max_width;
+
+ clist->column[column].width = width;
+ clist->column[column].width_set = TRUE;
+
+ /* FIXME: this is quite expensive to do if the widget hasn't
+ * been size_allocated yet, and pointless. Should
+ * a flag be kept
+ */
+ size_allocate_columns (clist, TRUE);
+ size_allocate_title_buttons (clist);
+
+ CLIST_REFRESH (clist);
+}
+
+static void
+abort_column_resize (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (!GTK_CMCLIST_IN_DRAG(clist))
+ return;
+
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_IN_DRAG);
+ gtk_grab_remove (GTK_WIDGET (clist));
+ gdk_display_pointer_ungrab (gtk_widget_get_display (GTK_WIDGET (clist)),
+ GDK_CURRENT_TIME);
+ clist->drag_pos = -1;
+
+ if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
+ draw_xor_line (clist);
+
+ if (GTK_CMCLIST_ADD_MODE(clist))
+ {
+ gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0);
+ gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
+ }
+}
+
+static void
+size_allocate_title_buttons (GtkCMCList *clist)
+{
+ GtkAllocation button_allocation;
+ gint last_column;
+ gint last_button = 0;
+ gint i;
+
+ if (!GTK_WIDGET_REALIZED (clist))
+ return;
+
+ button_allocation.x = clist->hoffset;
+ button_allocation.y = 0;
+ button_allocation.width = 0;
+ button_allocation.height = clist->column_title_area.height;
+
+ /* find last visible column */
+ for (last_column = clist->columns - 1; last_column >= 0; last_column--)
+ if (clist->column[last_column].visible)
+ break;
+
+ for (i = 0; i < last_column; i++)
+ {
+ if (!clist->column[i].visible)
+ {
+ last_button = i + 1;
+ gdk_window_hide (clist->column[i].window);
+ continue;
+ }
+
+ button_allocation.width += (clist->column[i].area.width +
+ CELL_SPACING + 2 * COLUMN_INSET);
+
+ if (!clist->column[i + 1].button)
+ {
+ gdk_window_hide (clist->column[i].window);
+ continue;
+ }
+
+ gtk_widget_size_allocate (clist->column[last_button].button,
+ &button_allocation);
+ button_allocation.x += button_allocation.width;
+ button_allocation.width = 0;
+
+ if (clist->column[last_button].resizeable)
+ {
+ gdk_window_show (clist->column[last_button].window);
+ gdk_window_move_resize (clist->column[last_button].window,
+ button_allocation.x - (DRAG_WIDTH / 2),
+ 0, DRAG_WIDTH,
+ clist->column_title_area.height);
+ }
+ else
+ gdk_window_hide (clist->column[last_button].window);
+
+ last_button = i + 1;
+ }
+
+ button_allocation.width += (clist->column[last_column].area.width +
+ 2 * (CELL_SPACING + COLUMN_INSET));
+ gtk_widget_size_allocate (clist->column[last_button].button,
+ &button_allocation);
+
+ if (clist->column[last_button].resizeable)
+ {
+ button_allocation.x += button_allocation.width;
+
+ gdk_window_show (clist->column[last_button].window);
+ gdk_window_move_resize (clist->column[last_button].window,
+ button_allocation.x - (DRAG_WIDTH / 2),
+ 0, DRAG_WIDTH, clist->column_title_area.height);
+ }
+ else
+ gdk_window_hide (clist->column[last_button].window);
+}
+
+static void
+size_allocate_columns (GtkCMCList *clist,
+ gboolean block_resize)
+{
+ gint xoffset = CELL_SPACING + COLUMN_INSET;
+ gint last_column;
+ gint i;
+
+ /* find last visible column and calculate correct column width */
+ for (last_column = clist->columns - 1;
+ last_column >= 0 && !clist->column[last_column].visible; last_column--);
+
+ if (last_column < 0)
+ return;
+
+ for (i = 0; i <= last_column; i++)
+ {
+ if (!clist->column[i].visible)
+ continue;
+ clist->column[i].area.x = xoffset;
+ if (clist->column[i].width_set)
+ {
+ if (!block_resize && GTK_CMCLIST_SHOW_TITLES(clist) &&
+ clist->column[i].auto_resize && clist->column[i].button)
+ {
+ gint width;
+
+ width = (clist->column[i].button->requisition.width -
+ (CELL_SPACING + (2 * COLUMN_INSET)));
+
+ if (width > clist->column[i].width)
+ gtk_cmclist_set_column_width (clist, i, width);
+ }
+
+ clist->column[i].area.width = clist->column[i].width;
+ xoffset += clist->column[i].width + CELL_SPACING + (2* COLUMN_INSET);
+ }
+ else if (GTK_CMCLIST_SHOW_TITLES(clist) && clist->column[i].button)
+ {
+ clist->column[i].area.width =
+ clist->column[i].button->requisition.width -
+ (CELL_SPACING + (2 * COLUMN_INSET));
+ xoffset += clist->column[i].button->requisition.width;
+ }
+ }
+
+ clist->column[last_column].area.width = clist->column[last_column].area.width
+ + MAX (0, clist->clist_window_width + COLUMN_INSET - xoffset);
+}
+
+static gint
+list_requisition_width (GtkCMCList *clist)
+{
+ gint width = CELL_SPACING;
+ gint i;
+
+ for (i = clist->columns - 1; i >= 0; i--)
+ {
+ if (!clist->column[i].visible)
+ continue;
+
+ if (clist->column[i].width_set)
+ width += clist->column[i].width + CELL_SPACING + (2 * COLUMN_INSET);
+ else if (GTK_CMCLIST_SHOW_TITLES(clist) && clist->column[i].button)
+ width += clist->column[i].button->requisition.width;
+ }
+
+ return width;
+}
+
+/* this function returns the new width of the column being resized given
+ * the column and x position of the cursor; the x cursor position is passed
+ * in as a pointer and automagicly corrected if it's beyond min/max limits */
+static gint
+new_column_width (GtkCMCList *clist,
+ gint column,
+ gint *x)
+{
+ gint xthickness = GTK_WIDGET (clist)->style->xthickness;
+ gint width;
+ gint cx;
+ gint dx;
+ gint last_column;
+
+ /* first translate the x position from widget->window
+ * to clist->clist_window */
+ cx = *x - xthickness;
+
+ for (last_column = clist->columns - 1;
+ last_column >= 0 && !clist->column[last_column].visible; last_column--);
+
+ /* calculate new column width making sure it doesn't end up
+ * less than the minimum width */
+ dx = (COLUMN_LEFT_XPIXEL (clist, column) + COLUMN_INSET +
+ (column < last_column) * CELL_SPACING);
+ width = cx - dx;
+
+ if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
+ {
+ width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
+ cx = dx + width;
+ *x = cx + xthickness;
+ }
+ else if (clist->column[column].max_width >= COLUMN_MIN_WIDTH &&
+ width > clist->column[column].max_width)
+ {
+ width = clist->column[column].max_width;
+ cx = dx + clist->column[column].max_width;
+ *x = cx + xthickness;
+ }
+
+ if (cx < 0 || cx > clist->clist_window_width)
+ *x = -1;
+
+ return width;
+}
+
+static void
+column_button_create (GtkCMCList *clist,
+ gint column)
+{
+ GtkWidget *button;
+
+ gtk_widget_push_composite_child ();
+ button = clist->column[column].button = gtk_button_new ();
+ gtk_container_set_border_width(GTK_CONTAINER(button), 0);
+ gtk_widget_pop_composite_child ();
+
+ if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
+ gtk_widget_set_parent_window (clist->column[column].button,
+ clist->title_window);
+ gtk_widget_set_parent (button, GTK_WIDGET (clist));
+
+ g_signal_connect (GTK_OBJECT (button), "clicked",
+ G_CALLBACK(column_button_clicked),
+ (gpointer) clist);
+ gtk_widget_show (button);
+}
+
+static void
+column_button_clicked (GtkWidget *widget,
+ gpointer data)
+{
+ gint i;
+ GtkCMCList *clist;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CMCLIST (data));
+
+ clist = GTK_CMCLIST (data);
+
+ /* find the column who's button was pressed */
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].button == widget)
+ break;
+
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], 0, i);
+}
+
+static gint
+column_title_passive_func (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data)
+{
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ switch (event->type)
+ {
+ case GDK_MOTION_NOTIFY:
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ case GDK_ENTER_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+
+/* PUBLIC CELL FUNCTIONS
+ * gtk_cmclist_get_cell_type
+ * gtk_cmclist_set_text
+ * gtk_cmclist_get_text
+ * gtk_cmclist_set_pixmap
+ * gtk_cmclist_get_pixmap
+ * gtk_cmclist_set_pixtext
+ * gtk_cmclist_get_pixtext
+ * gtk_cmclist_set_shift
+ */
+GtkCMCellType
+gtk_cmclist_get_cell_type (GtkCMCList *clist,
+ gint row,
+ gint column)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), -1);
+
+ if (row < 0 || row >= clist->rows)
+ return -1;
+ if (column < 0 || column >= clist->columns)
+ return -1;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ return clist_row->cell[column].type;
+}
+
+void
+gtk_cmclist_set_text (GtkCMCList *clist,
+ gint row,
+ gint column,
+ const gchar *text)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row >= clist->rows)
+ return;
+ if (column < 0 || column >= clist->columns)
+ return;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ /* if text is null, then the cell is empty */
+ GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+ (clist, clist_row, column, GTK_CMCELL_TEXT, text, 0, NULL, NULL);
+
+ /* redraw the list if it's not frozen */
+ if (CLIST_UNFROZEN (clist))
+ {
+ if (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+ }
+}
+
+gint
+gtk_cmclist_get_text (GtkCMCList *clist,
+ gint row,
+ gint column,
+ gchar **text)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+
+ if (row < 0 || row >= clist->rows)
+ return 0;
+ if (column < 0 || column >= clist->columns)
+ return 0;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (clist_row->cell[column].type != GTK_CMCELL_TEXT)
+ return 0;
+
+ if (text)
+ *text = GTK_CMCELL_TEXT (clist_row->cell[column])->text;
+
+ return 1;
+}
+
+void
+gtk_cmclist_set_pixmap (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row >= clist->rows)
+ return;
+ if (column < 0 || column >= clist->columns)
+ return;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ g_object_ref (pixmap);
+
+ if (mask) g_object_ref (mask);
+
+ GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+ (clist, clist_row, column, GTK_CMCELL_PIXMAP, NULL, 0, pixmap, mask);
+
+ /* redraw the list if it's not frozen */
+ if (CLIST_UNFROZEN (clist))
+ {
+ if (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+ }
+}
+
+gint
+gtk_cmclist_get_pixmap (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkPixmap **pixmap,
+ GdkBitmap **mask)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+
+ if (row < 0 || row >= clist->rows)
+ return 0;
+ if (column < 0 || column >= clist->columns)
+ return 0;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (clist_row->cell[column].type != GTK_CMCELL_PIXMAP)
+ return 0;
+
+ if (pixmap)
+ {
+ *pixmap = GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap;
+ /* mask can be NULL */
+ *mask = GTK_CMCELL_PIXMAP (clist_row->cell[column])->mask;
+ }
+
+ return 1;
+}
+
+void
+gtk_cmclist_set_pixtext (GtkCMCList *clist,
+ gint row,
+ gint column,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row >= clist->rows)
+ return;
+ if (column < 0 || column >= clist->columns)
+ return;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ g_object_ref (pixmap);
+ if (mask) g_object_ref (mask);
+ GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+ (clist, clist_row, column, GTK_CMCELL_PIXTEXT, text, spacing, pixmap, mask);
+
+ /* redraw the list if it's not frozen */
+ if (CLIST_UNFROZEN (clist))
+ {
+ if (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+ }
+}
+
+gint
+gtk_cmclist_get_pixtext (GtkCMCList *clist,
+ gint row,
+ gint column,
+ gchar **text,
+ guint8 *spacing,
+ GdkPixmap **pixmap,
+ GdkBitmap **mask)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+
+ if (row < 0 || row >= clist->rows)
+ return 0;
+ if (column < 0 || column >= clist->columns)
+ return 0;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (clist_row->cell[column].type != GTK_CMCELL_PIXTEXT)
+ return 0;
+
+ if (text)
+ *text = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text;
+ if (spacing)
+ *spacing = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->spacing;
+ if (pixmap)
+ *pixmap = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap;
+
+ /* mask can be NULL */
+ if (mask)
+ *mask = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask;
+
+ return 1;
+}
+
+void
+gtk_cmclist_set_shift (GtkCMCList *clist,
+ gint row,
+ gint column,
+ gint vertical,
+ gint horizontal)
+{
+ GtkRequisition requisition = { 0 };
+ GtkCMCListRow *clist_row;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row >= clist->rows)
+ return;
+ if (column < 0 || column >= clist->columns)
+ return;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (clist->column[column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+ column, &requisition);
+
+ clist_row->cell[column].vertical = vertical;
+ clist_row->cell[column].horizontal = horizontal;
+
+ column_auto_resize (clist, clist_row, column, requisition.width);
+
+ if (CLIST_UNFROZEN (clist) && gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+}
+
+/* PRIVATE CELL FUNCTIONS
+ * set_cell_contents
+ * cell_size_request
+ */
+static void
+set_cell_contents (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ GtkCMCellType type,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask)
+{
+ GtkRequisition requisition;
+ gchar *old_text = NULL;
+ GdkPixmap *old_pixmap = NULL;
+ GdkBitmap *old_mask = NULL;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+ g_return_if_fail (clist_row != NULL);
+
+ if (clist->column[column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+ column, &requisition);
+
+ switch (clist_row->cell[column].type)
+ {
+ case GTK_CMCELL_EMPTY:
+ break;
+ case GTK_CMCELL_TEXT:
+ old_text = GTK_CMCELL_TEXT (clist_row->cell[column])->text;
+ break;
+ case GTK_CMCELL_PIXMAP:
+ old_pixmap = GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap;
+ old_mask = GTK_CMCELL_PIXMAP (clist_row->cell[column])->mask;
+ break;
+ case GTK_CMCELL_PIXTEXT:
+ old_text = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text;
+ old_pixmap = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap;
+ old_mask = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask;
+ break;
+ case GTK_CMCELL_WIDGET:
+ /* unimplemented */
+ break;
+ default:
+ break;
+ }
+
+ clist_row->cell[column].type = GTK_CMCELL_EMPTY;
+
+ /* Note that pixmap and mask were already ref'ed by the caller
+ */
+ switch (type)
+ {
+ case GTK_CMCELL_TEXT:
+ if (text)
+ {
+ clist_row->cell[column].type = GTK_CMCELL_TEXT;
+ GTK_CMCELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
+ }
+ break;
+ case GTK_CMCELL_PIXMAP:
+ if (pixmap)
+ {
+ clist_row->cell[column].type = GTK_CMCELL_PIXMAP;
+ GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
+ /* We set the mask even if it is NULL */
+ GTK_CMCELL_PIXMAP (clist_row->cell[column])->mask = mask;
+ }
+ break;
+ case GTK_CMCELL_PIXTEXT:
+ if (text && pixmap)
+ {
+ clist_row->cell[column].type = GTK_CMCELL_PIXTEXT;
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask = mask;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (clist->column[column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ column_auto_resize (clist, clist_row, column, requisition.width);
+
+ g_free (old_text);
+ if (old_pixmap)
+ g_object_unref (old_pixmap);
+ if (old_mask)
+ g_object_unref (old_mask);
+}
+
+PangoLayout *
+_gtk_cmclist_create_cell_layout (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column)
+{
+ PangoLayout *layout;
+ GtkStyle *style;
+ GtkCMCell *cell;
+ gchar *text;
+
+ get_cell_style (clist, clist_row, GTK_STATE_NORMAL, column, &style,
+ NULL, NULL);
+
+
+ cell = &clist_row->cell[column];
+ switch (cell->type)
+ {
+ case GTK_CMCELL_TEXT:
+ case GTK_CMCELL_PIXTEXT:
+ text = ((cell->type == GTK_CMCELL_PIXTEXT) ?
+ GTK_CMCELL_PIXTEXT (*cell)->text :
+ GTK_CMCELL_TEXT (*cell)->text);
+
+ if (!text)
+ return NULL;
+
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET (clist),
+ ((cell->type == GTK_CMCELL_PIXTEXT) ?
+ GTK_CMCELL_PIXTEXT (*cell)->text :
+ GTK_CMCELL_TEXT (*cell)->text));
+ pango_layout_set_font_description (layout, style->font_desc);
+
+ return layout;
+
+ default:
+ return NULL;
+ }
+}
+
+static void
+cell_size_request (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ GtkRequisition *requisition)
+{
+ gint width;
+ gint height;
+ PangoLayout *layout;
+ PangoRectangle logical_rect;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+ g_return_if_fail (requisition != NULL);
+
+ layout = _gtk_cmclist_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;
+ }
+
+ if (layout && clist_row->cell[column].type == GTK_CMCELL_PIXTEXT)
+ requisition->width += GTK_CMCELL_PIXTEXT (clist_row->cell[column])->spacing;
+
+ switch (clist_row->cell[column].type)
+ {
+ case GTK_CMCELL_PIXTEXT:
+ gdk_drawable_get_size (GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap,
+ &width, &height);
+ requisition->width += width;
+ requisition->height = MAX (requisition->height, height);
+ break;
+ case GTK_CMCELL_PIXMAP:
+ gdk_drawable_get_size (GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap,
+ &width, &height);
+ requisition->width += width;
+ requisition->height = MAX (requisition->height, height);
+ break;
+
+ default:
+ break;
+ }
+
+ requisition->width += clist_row->cell[column].horizontal;
+ requisition->height += clist_row->cell[column].vertical;
+}
+
+/* PUBLIC INSERT/REMOVE ROW FUNCTIONS
+ * gtk_cmclist_prepend
+ * gtk_cmclist_append
+ * gtk_cmclist_insert
+ * gtk_cmclist_remove
+ * gtk_cmclist_clear
+ */
+gint
+gtk_cmclist_prepend (GtkCMCList *clist,
+ gchar *text[])
+{
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), -1);
+ g_return_val_if_fail (text != NULL, -1);
+
+ return GTK_CMCLIST_GET_CLASS (clist)->insert_row (clist, 0, text);
+}
+
+gint
+gtk_cmclist_append (GtkCMCList *clist,
+ gchar *text[])
+{
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), -1);
+ g_return_val_if_fail (text != NULL, -1);
+
+ return GTK_CMCLIST_GET_CLASS (clist)->insert_row (clist, clist->rows, text);
+}
+
+gint
+gtk_cmclist_insert (GtkCMCList *clist,
+ gint row,
+ gchar *text[])
+{
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), -1);
+ g_return_val_if_fail (text != NULL, -1);
+
+ if (row < 0 || row > clist->rows)
+ row = clist->rows;
+
+ return GTK_CMCLIST_GET_CLASS (clist)->insert_row (clist, row, text);
+}
+
+void
+gtk_cmclist_remove (GtkCMCList *clist,
+ gint row)
+{
+ GTK_CMCLIST_GET_CLASS (clist)->remove_row (clist, row);
+}
+
+void
+gtk_cmclist_clear (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ GTK_CMCLIST_GET_CLASS (clist)->clear (clist);
+}
+
+/* PRIVATE INSERT/REMOVE ROW FUNCTIONS
+ * real_insert_row
+ * real_remove_row
+ * real_clear
+ * real_row_move
+ */
+static gint
+real_insert_row (GtkCMCList *clist,
+ gint row,
+ gchar *text[])
+{
+ gint i;
+ GtkCMCListRow *clist_row;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), -1);
+ g_return_val_if_fail (text != NULL, -1);
+
+ /* return if out of bounds */
+ if (row < 0 || row > clist->rows)
+ return -1;
+
+ /* create the row */
+ clist_row = row_new (clist);
+
+ /* set the text in the row's columns */
+ for (i = 0; i < clist->columns; i++)
+ if (text[i])
+ GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+ (clist, clist_row, i, GTK_CMCELL_TEXT, text[i], 0, NULL ,NULL);
+
+ if (!clist->rows)
+ {
+ clist->row_list = g_list_append (clist->row_list, clist_row);
+ clist->row_list_end = clist->row_list;
+ }
+ else
+ {
+ if (GTK_CMCLIST_AUTO_SORT(clist)) /* override insertion pos */
+ {
+ GList *work;
+
+ row = 0;
+ work = clist->row_list;
+
+ if (clist->sort_type == GTK_SORT_ASCENDING)
+ {
+ while (row < clist->rows &&
+ clist->compare (clist, clist_row,
+ GTK_CMCLIST_ROW (work)) > 0)
+ {
+ row++;
+ work = work->next;
+ }
+ }
+ else
+ {
+ while (row < clist->rows &&
+ clist->compare (clist, clist_row,
+ GTK_CMCLIST_ROW (work)) < 0)
+ {
+ row++;
+ work = work->next;
+ }
+ }
+ }
+
+ /* reset the row end pointer if we're inserting at the end of the list */
+ if (row == clist->rows)
+ clist->row_list_end = (g_list_append (clist->row_list_end,
+ clist_row))->next;
+ else
+ clist->row_list = g_list_insert (clist->row_list, clist_row, row);
+
+ }
+ clist->rows++;
+
+ if (row < ROW_FROM_YPIXEL (clist, 0))
+ clist->voffset -= (clist->row_height + CELL_SPACING);
+
+ /* syncronize the selection list */
+ sync_selection (clist, row, SYNC_INSERT);
+
+ if (clist->rows == 1)
+ {
+ clist->focus_row = 0;
+ if (clist->selection_mode == GTK_SELECTION_BROWSE)
+ gtk_cmclist_select_row (clist, 0, -1);
+ }
+
+ /* redraw the list if it isn't frozen */
+ if (CLIST_UNFROZEN (clist))
+ {
+ adjust_adjustments (clist, FALSE);
+
+ if (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ draw_rows (clist, NULL);
+ }
+
+ return row;
+}
+
+static void
+real_remove_row (GtkCMCList *clist,
+ gint row)
+{
+ gint was_visible;
+ GList *list;
+ GtkCMCListRow *clist_row;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ /* return if out of bounds */
+ if (row < 0 || row > (clist->rows - 1))
+ return;
+
+ was_visible = (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
+
+ /* get the row we're going to delete */
+ list = ROW_ELEMENT (clist, row);
+ g_assert (list != NULL);
+ clist_row = list->data;
+
+ /* if we're removing a selected row, we have to make sure
+ * it's properly unselected, and then sync up the clist->selected
+ * list to reflect the deincrimented indexies of rows after the
+ * removal */
+ if (clist_row->state == GTK_STATE_SELECTED)
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+ row, -1, NULL);
+
+ sync_selection (clist, row, SYNC_REMOVE);
+
+ /* reset the row end pointer if we're removing at the end of the list */
+ clist->rows--;
+ if (clist->row_list == list)
+ clist->row_list = g_list_next (list);
+ if (clist->row_list_end == list)
+ clist->row_list_end = g_list_previous (list);
+ list = g_list_remove (list, clist_row);
+
+ if (row < ROW_FROM_YPIXEL (clist, 0))
+ clist->voffset += clist->row_height + CELL_SPACING;
+
+ if (clist->selection_mode == GTK_SELECTION_BROWSE && !clist->selection &&
+ clist->focus_row >= 0)
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+ clist->focus_row, -1, NULL);
+
+ /* toast the row */
+ row_delete (clist, clist_row);
+
+ /* redraw the row if it isn't frozen */
+ if (CLIST_UNFROZEN (clist))
+ {
+ adjust_adjustments (clist, FALSE);
+
+ if (was_visible)
+ draw_rows (clist, NULL);
+ }
+}
+
+static void
+real_clear (GtkCMCList *clist)
+{
+ GList *list;
+ GList *free_list;
+ gint i;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ /* free up the selection list */
+ g_list_free (clist->selection);
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+
+ clist->selection = NULL;
+ clist->selection_end = NULL;
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+ clist->voffset = 0;
+ clist->focus_row = -1;
+ clist->anchor = -1;
+ clist->undo_anchor = -1;
+ clist->anchor_state = GTK_STATE_SELECTED;
+ clist->drag_pos = -1;
+
+ /* remove all the rows */
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+ free_list = clist->row_list;
+ clist->row_list = NULL;
+ clist->row_list_end = NULL;
+ clist->rows = 0;
+ for (list = free_list; list; list = list->next)
+ row_delete (clist, GTK_CMCLIST_ROW (list));
+ g_list_free (free_list);
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].auto_resize)
+ {
+ if (GTK_CMCLIST_SHOW_TITLES(clist) && clist->column[i].button)
+ gtk_cmclist_set_column_width
+ (clist, i, (clist->column[i].button->requisition.width -
+ (CELL_SPACING + (2 * COLUMN_INSET))));
+ else
+ gtk_cmclist_set_column_width (clist, i, 0);
+ }
+ /* zero-out the scrollbars */
+ if (clist->vadjustment)
+ {
+ gtk_adjustment_set_value (clist->vadjustment, 0.0);
+ CLIST_REFRESH (clist);
+ }
+ else
+ gtk_widget_queue_resize (GTK_WIDGET (clist));
+}
+
+static void
+real_row_move (GtkCMCList *clist,
+ gint source_row,
+ gint dest_row)
+{
+ GtkCMCListRow *clist_row;
+ GList *list;
+ gint first, last;
+ gint d;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (GTK_CMCLIST_AUTO_SORT(clist))
+ return;
+
+ if (source_row < 0 || source_row >= clist->rows ||
+ dest_row < 0 || dest_row >= clist->rows ||
+ source_row == dest_row)
+ return;
+
+ gtk_cmclist_freeze (clist);
+
+ /* unlink source row */
+ clist_row = ROW_ELEMENT (clist, source_row)->data;
+ if (source_row == clist->rows - 1)
+ clist->row_list_end = clist->row_list_end->prev;
+ clist->row_list = g_list_remove (clist->row_list, clist_row);
+ clist->rows--;
+
+ /* relink source row */
+ clist->row_list = g_list_insert (clist->row_list, clist_row, dest_row);
+ if (dest_row == clist->rows)
+ clist->row_list_end = clist->row_list_end->next;
+ clist->rows++;
+
+ /* sync selection */
+ if (source_row > dest_row)
+ {
+ first = dest_row;
+ last = source_row;
+ d = 1;
+ }
+ else
+ {
+ first = source_row;
+ last = dest_row;
+ d = -1;
+ }
+
+ for (list = clist->selection; list; list = list->next)
+ {
+ if (list->data == GINT_TO_POINTER (source_row))
+ list->data = GINT_TO_POINTER (dest_row);
+ else if (first <= GPOINTER_TO_INT (list->data) &&
+ last >= GPOINTER_TO_INT (list->data))
+ list->data = GINT_TO_POINTER (GPOINTER_TO_INT (list->data) + d);
+ }
+
+ if (clist->focus_row == source_row)
+ clist->focus_row = dest_row;
+ else if (clist->focus_row > first)
+ clist->focus_row += d;
+
+ gtk_cmclist_thaw (clist);
+}
+
+/* PUBLIC ROW FUNCTIONS
+ * gtk_cmclist_moveto
+ * gtk_cmclist_set_row_height
+ * gtk_cmclist_set_row_data
+ * gtk_cmclist_set_row_data_full
+ * gtk_cmclist_get_row_data
+ * gtk_cmclist_find_row_from_data
+ * gtk_cmclist_swap_rows
+ * gtk_cmclist_row_move
+ * gtk_cmclist_row_is_visible
+ * gtk_cmclist_set_foreground
+ * gtk_cmclist_set_background
+ */
+void
+gtk_cmclist_moveto (GtkCMCList *clist,
+ gint row,
+ gint column,
+ gfloat row_align,
+ gfloat col_align)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < -1 || row >= clist->rows)
+ return;
+ if (column < -1 || column >= clist->columns)
+ return;
+
+ row_align = CLAMP (row_align, 0, 1);
+ col_align = CLAMP (col_align, 0, 1);
+
+ /* adjust horizontal scrollbar */
+ if (clist->hadjustment && column >= 0)
+ {
+ gint x;
+
+ x = (COLUMN_LEFT (clist, column) - CELL_SPACING - COLUMN_INSET -
+ (col_align * (clist->clist_window_width - 2 * COLUMN_INSET -
+ CELL_SPACING - clist->column[column].area.width)));
+ if (x < 0)
+ gtk_adjustment_set_value (clist->hadjustment, 0.0);
+ else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
+ gtk_adjustment_set_value
+ (clist->hadjustment, LIST_WIDTH (clist) - clist->clist_window_width);
+ else
+ gtk_adjustment_set_value (clist->hadjustment, x);
+ }
+
+ /* adjust vertical scrollbar */
+ if (clist->vadjustment && row >= 0)
+ move_vertical (clist, row, row_align);
+}
+
+void
+gtk_cmclist_set_row_height (GtkCMCList *clist,
+ guint height)
+{
+ GtkWidget *widget;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ widget = GTK_WIDGET (clist);
+
+ if (height > 0)
+ {
+ clist->row_height = height;
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_ROW_HEIGHT_SET);
+ }
+ else
+ {
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_ROW_HEIGHT_SET);
+ clist->row_height = 0;
+ }
+
+ if (widget->style->font_desc)
+ {
+ PangoContext *context = gtk_widget_get_pango_context (widget);
+ PangoFontMetrics *metrics;
+
+ metrics = pango_context_get_metrics (context,
+ widget->style->font_desc,
+ pango_context_get_language (context));
+
+ if (!GTK_CMCLIST_ROW_HEIGHT_SET(clist))
+ {
+ clist->row_height = (pango_font_metrics_get_ascent (metrics) +
+ pango_font_metrics_get_descent (metrics));
+ clist->row_height = PANGO_PIXELS (clist->row_height);
+ }
+
+ pango_font_metrics_unref (metrics);
+ }
+
+ CLIST_REFRESH (clist);
+}
+
+void
+gtk_cmclist_set_row_data (GtkCMCList *clist,
+ gint row,
+ gpointer data)
+{
+ gtk_cmclist_set_row_data_full (clist, row, data, NULL);
+}
+
+void
+gtk_cmclist_set_row_data_full (GtkCMCList *clist,
+ gint row,
+ gpointer data,
+ GtkDestroyNotify destroy)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row > (clist->rows - 1))
+ return;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (clist_row->destroy)
+ clist_row->destroy (clist_row->data);
+
+ clist_row->data = data;
+ clist_row->destroy = destroy;
+}
+
+gpointer
+gtk_cmclist_get_row_data (GtkCMCList *clist,
+ gint row)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+ if (row < 0 || row > (clist->rows - 1))
+ return NULL;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+ return clist_row->data;
+}
+
+gint
+gtk_cmclist_find_row_from_data (GtkCMCList *clist,
+ gpointer data)
+{
+ GList *list;
+ gint n;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), -1);
+
+ for (n = 0, list = clist->row_list; list; n++, list = list->next)
+ if (GTK_CMCLIST_ROW (list)->data == data)
+ return n;
+
+ return -1;
+}
+
+void
+gtk_cmclist_swap_rows (GtkCMCList *clist,
+ gint row1,
+ gint row2)
+{
+ gint first, last;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+ g_return_if_fail (row1 != row2);
+
+ if (GTK_CMCLIST_AUTO_SORT(clist))
+ return;
+
+ gtk_cmclist_freeze (clist);
+
+ first = MIN (row1, row2);
+ last = MAX (row1, row2);
+
+ gtk_cmclist_row_move (clist, last, first);
+ gtk_cmclist_row_move (clist, first + 1, last);
+
+ gtk_cmclist_thaw (clist);
+}
+
+void
+gtk_cmclist_row_move (GtkCMCList *clist,
+ gint source_row,
+ gint dest_row)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (GTK_CMCLIST_AUTO_SORT(clist))
+ return;
+
+ if (source_row < 0 || source_row >= clist->rows ||
+ dest_row < 0 || dest_row >= clist->rows ||
+ source_row == dest_row)
+ return;
+
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[ROW_MOVE], 0,
+ source_row, dest_row);
+}
+
+GtkVisibility
+gtk_cmclist_row_is_visible (GtkCMCList *clist,
+ gint row)
+{
+ gint top;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+
+ if (row < 0 || row >= clist->rows)
+ return GTK_VISIBILITY_NONE;
+
+ if (clist->row_height == 0)
+ return GTK_VISIBILITY_NONE;
+
+ if (row < ROW_FROM_YPIXEL (clist, 0))
+ return GTK_VISIBILITY_NONE;
+
+ if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
+ return GTK_VISIBILITY_NONE;
+
+ top = ROW_TOP_YPIXEL (clist, row);
+
+ if ((top < 0)
+ || ((top + clist->row_height) >= clist->clist_window_height))
+ return GTK_VISIBILITY_PARTIAL;
+
+ return GTK_VISIBILITY_FULL;
+}
+
+void
+gtk_cmclist_set_foreground (GtkCMCList *clist,
+ gint row,
+ const GdkColor *color)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row >= clist->rows)
+ return;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (color)
+ {
+ clist_row->foreground = *color;
+ clist_row->fg_set = TRUE;
+ if (GTK_WIDGET_REALIZED (clist))
+ gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (clist)),
+ &clist_row->foreground, TRUE, TRUE);
+ }
+ else
+ clist_row->fg_set = FALSE;
+
+ if (CLIST_UNFROZEN (clist) && gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+}
+
+void
+gtk_cmclist_set_background (GtkCMCList *clist,
+ gint row,
+ const GdkColor *color)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row >= clist->rows)
+ return;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (color)
+ {
+ clist_row->background = *color;
+ clist_row->bg_set = TRUE;
+ if (GTK_WIDGET_REALIZED (clist))
+ gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (clist)),
+ &clist_row->background, TRUE, TRUE);
+ }
+ else
+ clist_row->bg_set = FALSE;
+
+ if (CLIST_UNFROZEN (clist)
+ && (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+}
+
+/* PUBLIC ROW/CELL STYLE FUNCTIONS
+ * gtk_cmclist_set_cell_style
+ * gtk_cmclist_get_cell_style
+ * gtk_cmclist_set_row_style
+ * gtk_cmclist_get_row_style
+ */
+void
+gtk_cmclist_set_cell_style (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GtkStyle *style)
+{
+ GtkRequisition requisition = { 0 };
+ GtkCMCListRow *clist_row;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row >= clist->rows)
+ return;
+ if (column < 0 || column >= clist->columns)
+ return;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (clist_row->cell[column].style == style)
+ return;
+
+ if (clist->column[column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+ column, &requisition);
+
+ if (clist_row->cell[column].style)
+ {
+ if (GTK_WIDGET_REALIZED (clist))
+ gtk_style_detach (clist_row->cell[column].style);
+ g_object_unref (clist_row->cell[column].style);
+ }
+
+ clist_row->cell[column].style = style;
+
+ if (clist_row->cell[column].style)
+ {
+ g_object_ref (clist_row->cell[column].style);
+
+ if (GTK_WIDGET_REALIZED (clist))
+ clist_row->cell[column].style =
+ gtk_style_attach (clist_row->cell[column].style,
+ clist->clist_window);
+ }
+
+ column_auto_resize (clist, clist_row, column, requisition.width);
+
+ /* redraw the list if it's not frozen */
+ if (CLIST_UNFROZEN (clist))
+ {
+ if (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+ }
+}
+
+GtkStyle *
+gtk_cmclist_get_cell_style (GtkCMCList *clist,
+ gint row,
+ gint column)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+ if (row < 0 || row >= clist->rows || column < 0 || column >= clist->columns)
+ return NULL;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ return clist_row->cell[column].style;
+}
+
+void
+gtk_cmclist_set_row_style (GtkCMCList *clist,
+ gint row,
+ GtkStyle *style)
+{
+ GtkRequisition requisition;
+ GtkCMCListRow *clist_row;
+ gint *old_width;
+ gint i;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row >= clist->rows)
+ return;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (clist_row->style == style)
+ return;
+
+ old_width = g_new (gint, clist->columns);
+
+ if (!GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ {
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].auto_resize)
+ {
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+ i, &requisition);
+ old_width[i] = requisition.width;
+ }
+ }
+
+ if (clist_row->style)
+ {
+ if (GTK_WIDGET_REALIZED (clist))
+ gtk_style_detach (clist_row->style);
+ g_object_unref (clist_row->style);
+ }
+
+ clist_row->style = style;
+
+ if (clist_row->style)
+ {
+ g_object_ref (clist_row->style);
+
+ if (GTK_WIDGET_REALIZED (clist))
+ clist_row->style = gtk_style_attach (clist_row->style,
+ clist->clist_window);
+ }
+
+ if (GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ for (i = 0; i < clist->columns; i++)
+ column_auto_resize (clist, clist_row, i, old_width[i]);
+
+ g_free (old_width);
+
+ /* redraw the list if it's not frozen */
+ if (CLIST_UNFROZEN (clist))
+ {
+ if (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+ }
+}
+
+GtkStyle *
+gtk_cmclist_get_row_style (GtkCMCList *clist,
+ gint row)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+ if (row < 0 || row >= clist->rows)
+ return NULL;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ return clist_row->style;
+}
+
+/* PUBLIC SELECTION FUNCTIONS
+ * gtk_cmclist_set_selectable
+ * gtk_cmclist_get_selectable
+ * gtk_cmclist_select_row
+ * gtk_cmclist_unselect_row
+ * gtk_cmclist_select_all
+ * gtk_cmclist_unselect_all
+ * gtk_cmclist_undo_selection
+ */
+void
+gtk_cmclist_set_selectable (GtkCMCList *clist,
+ gint row,
+ gboolean selectable)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row >= clist->rows)
+ return;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (selectable == clist_row->selectable)
+ return;
+
+ clist_row->selectable = selectable;
+
+ if (!selectable && clist_row->state == GTK_STATE_SELECTED)
+ {
+ if (clist->anchor >= 0 &&
+ clist->selection_mode == GTK_SELECTION_MULTIPLE)
+ {
+ clist->drag_button = 0;
+ remove_grab (clist);
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+ }
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+ row, -1, NULL);
+ }
+}
+
+gboolean
+gtk_cmclist_get_selectable (GtkCMCList *clist,
+ gint row)
+{
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), FALSE);
+
+ if (row < 0 || row >= clist->rows)
+ return FALSE;
+
+ return GTK_CMCLIST_ROW (ROW_ELEMENT (clist, row))->selectable;
+}
+
+void
+gtk_cmclist_select_row (GtkCMCList *clist,
+ gint row,
+ gint column)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row >= clist->rows)
+ return;
+ if (column < -1 || column >= clist->columns)
+ return;
+
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+ row, column, NULL);
+}
+
+void
+gtk_cmclist_unselect_row (GtkCMCList *clist,
+ gint row,
+ gint column)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row >= clist->rows)
+ return;
+ if (column < -1 || column >= clist->columns)
+ return;
+
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+ row, column, NULL);
+}
+
+void
+gtk_cmclist_select_all (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ GTK_CMCLIST_GET_CLASS (clist)->select_all (clist);
+}
+
+void
+gtk_cmclist_unselect_all (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ GTK_CMCLIST_GET_CLASS (clist)->unselect_all (clist);
+}
+
+void
+gtk_cmclist_undo_selection (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist->selection_mode == GTK_SELECTION_MULTIPLE &&
+ (clist->undo_selection || clist->undo_unselection))
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[UNDO_SELECTION], 0);
+}
+
+/* PRIVATE SELECTION FUNCTIONS
+ * selection_find
+ * toggle_row
+ * fake_toggle_row
+ * toggle_focus_row
+ * toggle_add_mode
+ * real_select_row
+ * real_unselect_row
+ * real_select_all
+ * real_unselect_all
+ * fake_unselect_all
+ * real_undo_selection
+ * set_anchor
+ * resync_selection
+ * update_extended_selection
+ * start_selection
+ * end_selection
+ * extend_selection
+ * sync_selection
+ */
+static GList *
+selection_find (GtkCMCList *clist,
+ gint row_number,
+ GList *row_list_element)
+{
+ return g_list_find (clist->selection, GINT_TO_POINTER (row_number));
+}
+
+static void
+toggle_row (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event)
+{
+ GtkCMCListRow *clist_row;
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_MULTIPLE:
+ case GTK_SELECTION_SINGLE:
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (!clist_row)
+ return;
+
+ if (clist_row->state == GTK_STATE_SELECTED)
+ {
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+ row, column, event);
+ return;
+ }
+ case GTK_SELECTION_BROWSE:
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+ row, column, event);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+fake_toggle_row (GtkCMCList *clist,
+ gint row)
+{
+ GList *work;
+
+ work = ROW_ELEMENT (clist, row);
+
+ if (!work || !GTK_CMCLIST_ROW (work)->selectable)
+ return;
+
+ if (GTK_CMCLIST_ROW (work)->state == GTK_STATE_NORMAL)
+ clist->anchor_state = GTK_CMCLIST_ROW (work)->state = GTK_STATE_SELECTED;
+ else
+ clist->anchor_state = GTK_CMCLIST_ROW (work)->state = GTK_STATE_NORMAL;
+
+ if (CLIST_UNFROZEN (clist) &&
+ gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row,
+ GTK_CMCLIST_ROW (work));
+}
+
+static gboolean
+clist_has_grab (GtkCMCList *clist)
+{
+ return (GTK_WIDGET_HAS_GRAB (clist) &&
+ gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))));
+}
+
+static void
+toggle_focus_row (GtkCMCList *clist)
+{
+ g_return_if_fail (clist != 0);
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist_has_grab (clist) ||
+ clist->focus_row < 0 || clist->focus_row >= clist->rows)
+ return;
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_SINGLE:
+ toggle_row (clist, clist->focus_row, 0, NULL);
+ break;
+ case GTK_SELECTION_MULTIPLE:
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+
+ clist->anchor = clist->focus_row;
+ clist->drag_pos = clist->focus_row;
+ clist->undo_anchor = clist->focus_row;
+
+ if (GTK_CMCLIST_ADD_MODE(clist))
+ fake_toggle_row (clist, clist->focus_row);
+ else
+ GTK_CMCLIST_GET_CLASS (clist)->fake_unselect_all (clist,clist->focus_row);
+
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+toggle_add_mode (GtkCMCList *clist)
+{
+ g_return_if_fail (clist != 0);
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist_has_grab (clist) ||
+ clist->selection_mode != GTK_SELECTION_MULTIPLE)
+ return;
+
+ gtk_cmclist_draw_focus (GTK_WIDGET (clist));
+ if (!GTK_CMCLIST_ADD_MODE(clist))
+ {
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_ADD_MODE);
+ gdk_gc_set_line_attributes (clist->xor_gc, 1,
+ GDK_LINE_ON_OFF_DASH, 0, 0);
+ gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
+ }
+ else
+ {
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_ADD_MODE);
+ gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
+ clist->anchor_state = GTK_STATE_SELECTED;
+ }
+ gtk_cmclist_draw_focus (GTK_WIDGET (clist));
+}
+
+static void
+real_select_row (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event)
+{
+ GtkCMCListRow *clist_row;
+ GList *list;
+ gint sel_row;
+ gboolean row_selected;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row > (clist->rows - 1))
+ return;
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_SINGLE:
+ case GTK_SELECTION_BROWSE:
+
+ row_selected = FALSE;
+ list = clist->selection;
+
+ while (list)
+ {
+ sel_row = GPOINTER_TO_INT (list->data);
+ list = list->next;
+
+ if (row == sel_row)
+ row_selected = TRUE;
+ else
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+ sel_row, column, event);
+ }
+
+ if (row_selected)
+ return;
+
+ default:
+ break;
+ }
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (clist_row->state != GTK_STATE_NORMAL || !clist_row->selectable)
+ return;
+
+ clist_row->state = GTK_STATE_SELECTED;
+ if (!clist->selection)
+ {
+ clist->selection = g_list_append (clist->selection,
+ GINT_TO_POINTER (row));
+ clist->selection_end = clist->selection;
+ }
+ else
+ clist->selection_end =
+ g_list_append (clist->selection_end, GINT_TO_POINTER (row))->next;
+
+ if (CLIST_UNFROZEN (clist)
+ && (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+}
+
+static void
+real_unselect_row (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event)
+{
+ GtkCMCListRow *clist_row;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (row < 0 || row > (clist->rows - 1))
+ return;
+
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (clist_row->state == GTK_STATE_SELECTED)
+ {
+ clist_row->state = GTK_STATE_NORMAL;
+
+ if (clist->selection_end &&
+ clist->selection_end->data == GINT_TO_POINTER (row))
+ clist->selection_end = clist->selection_end->prev;
+
+ clist->selection = g_list_remove (clist->selection,
+ GINT_TO_POINTER (row));
+
+ if (CLIST_UNFROZEN (clist)
+ && (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+ }
+}
+
+static void
+real_select_all (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist_has_grab (clist))
+ return;
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_SINGLE:
+ case GTK_SELECTION_BROWSE:
+ return;
+
+ case GTK_SELECTION_MULTIPLE:
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+
+ if (clist->rows &&
+ ((GtkCMCListRow *) (clist->row_list->data))->state !=
+ GTK_STATE_SELECTED)
+ fake_toggle_row (clist, 0);
+
+ clist->anchor_state = GTK_STATE_SELECTED;
+ clist->anchor = 0;
+ clist->drag_pos = 0;
+ clist->undo_anchor = clist->focus_row;
+ update_extended_selection (clist, clist->rows);
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+ return;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+real_unselect_all (GtkCMCList *clist)
+{
+ GList *list;
+ gint i;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist_has_grab (clist))
+ return;
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_BROWSE:
+ if (clist->focus_row >= 0)
+ {
+ g_signal_emit (GTK_OBJECT (clist),
+ clist_signals[SELECT_ROW], 0,
+ clist->focus_row, -1, NULL);
+ return;
+ }
+ break;
+ case GTK_SELECTION_MULTIPLE:
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+
+ clist->anchor = -1;
+ clist->drag_pos = -1;
+ clist->undo_anchor = clist->focus_row;
+ break;
+ default:
+ break;
+ }
+
+ list = clist->selection;
+ while (list)
+ {
+ i = GPOINTER_TO_INT (list->data);
+ list = list->next;
+ g_signal_emit (GTK_OBJECT (clist),
+ clist_signals[UNSELECT_ROW], 0, i, -1, NULL);
+ }
+}
+
+static void
+fake_unselect_all (GtkCMCList *clist,
+ gint row)
+{
+ GList *list;
+ GList *work;
+ gint i;
+
+ if (row >= 0 && (work = ROW_ELEMENT (clist, row)))
+ {
+ if (GTK_CMCLIST_ROW (work)->state == GTK_STATE_NORMAL &&
+ GTK_CMCLIST_ROW (work)->selectable)
+ {
+ GTK_CMCLIST_ROW (work)->state = GTK_STATE_SELECTED;
+
+ if (CLIST_UNFROZEN (clist) &&
+ gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row,
+ GTK_CMCLIST_ROW (work));
+ }
+ }
+
+ clist->undo_selection = clist->selection;
+ clist->selection = NULL;
+ clist->selection_end = NULL;
+
+ for (list = clist->undo_selection; list; list = list->next)
+ {
+ if ((i = GPOINTER_TO_INT (list->data)) == row ||
+ !(work = g_list_nth (clist->row_list, i)))
+ continue;
+
+ GTK_CMCLIST_ROW (work)->state = GTK_STATE_NORMAL;
+ if (CLIST_UNFROZEN (clist) &&
+ gtk_cmclist_row_is_visible (clist, i) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, i,
+ GTK_CMCLIST_ROW (work));
+ }
+}
+
+static void
+real_undo_selection (GtkCMCList *clist)
+{
+ GList *work;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist_has_grab (clist) ||
+ clist->selection_mode != GTK_SELECTION_MULTIPLE)
+ return;
+
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+ if (!(clist->undo_selection || clist->undo_unselection))
+ {
+ gtk_cmclist_unselect_all (clist);
+ return;
+ }
+
+ for (work = clist->undo_selection; work; work = work->next)
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+ GPOINTER_TO_INT (work->data), -1, NULL);
+
+ for (work = clist->undo_unselection; work; work = work->next)
+ {
+ /* g_print ("unselect %d\n",GPOINTER_TO_INT (work->data)); */
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+ GPOINTER_TO_INT (work->data), -1, NULL);
+ }
+
+ if (GTK_WIDGET_HAS_FOCUS(clist) && clist->focus_row != clist->undo_anchor)
+ {
+ gtk_cmclist_draw_focus (GTK_WIDGET (clist));
+ clist->focus_row = clist->undo_anchor;
+ gtk_cmclist_draw_focus (GTK_WIDGET (clist));
+ }
+ else
+ clist->focus_row = clist->undo_anchor;
+
+ clist->undo_anchor = -1;
+
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+
+ if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
+ clist->clist_window_height)
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+ else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+}
+
+static void
+set_anchor (GtkCMCList *clist,
+ gboolean add_mode,
+ gint anchor,
+ gint undo_anchor)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist->selection_mode != GTK_SELECTION_MULTIPLE || clist->anchor >= 0)
+ return;
+
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+
+ if (add_mode)
+ fake_toggle_row (clist, anchor);
+ else
+ {
+ GTK_CMCLIST_GET_CLASS (clist)->fake_unselect_all (clist, anchor);
+ clist->anchor_state = GTK_STATE_SELECTED;
+ }
+
+ clist->anchor = anchor;
+ clist->drag_pos = anchor;
+ clist->undo_anchor = undo_anchor;
+}
+
+static void
+resync_selection (GtkCMCList *clist,
+ GdkEvent *event)
+{
+ gint i;
+ gint e;
+ gint row;
+ GList *list;
+ GtkCMCListRow *clist_row;
+
+ if (clist->selection_mode != GTK_SELECTION_MULTIPLE)
+ return;
+
+ if (clist->anchor < 0 || clist->drag_pos < 0)
+ return;
+
+ gtk_cmclist_freeze (clist);
+
+ i = MIN (clist->anchor, clist->drag_pos);
+ e = MAX (clist->anchor, clist->drag_pos);
+
+ if (clist->undo_selection)
+ {
+ list = clist->selection;
+ clist->selection = clist->undo_selection;
+ clist->selection_end = g_list_last (clist->selection);
+ clist->undo_selection = list;
+ list = clist->selection;
+ while (list)
+ {
+ row = GPOINTER_TO_INT (list->data);
+ list = list->next;
+ if (row < i || row > e)
+ {
+ clist_row = g_list_nth (clist->row_list, row)->data;
+ if (clist_row->selectable)
+ {
+ clist_row->state = GTK_STATE_SELECTED;
+ g_signal_emit (GTK_OBJECT (clist),
+ clist_signals[UNSELECT_ROW], 0,
+ row, -1, event);
+ clist->undo_selection = g_list_prepend
+ (clist->undo_selection, GINT_TO_POINTER (row));
+ }
+ }
+ }
+ }
+
+ if (clist->anchor < clist->drag_pos)
+ {
+ for (list = g_list_nth (clist->row_list, i); i <= e;
+ i++, list = list->next)
+ if (GTK_CMCLIST_ROW (list)->selectable)
+ {
+ if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
+ {
+ if (GTK_CMCLIST_ROW (list)->state == GTK_STATE_NORMAL)
+ {
+ GTK_CMCLIST_ROW (list)->state = GTK_STATE_SELECTED;
+ g_signal_emit (GTK_OBJECT (clist),
+ clist_signals[UNSELECT_ROW], 0,
+ i, -1, event);
+ clist->undo_selection =
+ g_list_prepend (clist->undo_selection,
+ GINT_TO_POINTER (i));
+ }
+ }
+ else if (GTK_CMCLIST_ROW (list)->state == GTK_STATE_SELECTED)
+ {
+ GTK_CMCLIST_ROW (list)->state = GTK_STATE_NORMAL;
+ clist->undo_unselection =
+ g_list_prepend (clist->undo_unselection,
+ GINT_TO_POINTER (i));
+ }
+ }
+ }
+ else
+ {
+ for (list = g_list_nth (clist->row_list, e); i <= e;
+ e--, list = list->prev)
+ if (GTK_CMCLIST_ROW (list)->selectable)
+ {
+ if (g_list_find (clist->selection, GINT_TO_POINTER(e)))
+ {
+ if (GTK_CMCLIST_ROW (list)->state == GTK_STATE_NORMAL)
+ {
+ GTK_CMCLIST_ROW (list)->state = GTK_STATE_SELECTED;
+ g_signal_emit (GTK_OBJECT (clist),
+ clist_signals[UNSELECT_ROW], 0,
+ e, -1, event);
+ clist->undo_selection =
+ g_list_prepend (clist->undo_selection,
+ GINT_TO_POINTER (e));
+ }
+ }
+ else if (GTK_CMCLIST_ROW (list)->state == GTK_STATE_SELECTED)
+ {
+ GTK_CMCLIST_ROW (list)->state = GTK_STATE_NORMAL;
+ clist->undo_unselection =
+ g_list_prepend (clist->undo_unselection,
+ GINT_TO_POINTER (e));
+ }
+ }
+ }
+
+ clist->undo_unselection = g_list_reverse (clist->undo_unselection);
+ for (list = clist->undo_unselection; list; list = list->next)
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+ GPOINTER_TO_INT (list->data), -1, event);
+
+ clist->anchor = -1;
+ clist->drag_pos = -1;
+
+ gtk_cmclist_thaw (clist);
+}
+
+static void
+update_extended_selection (GtkCMCList *clist,
+ gint row)
+{
+ gint i;
+ GList *list;
+ GdkRectangle area;
+ gint s1 = -1;
+ gint s2 = -1;
+ gint e1 = -1;
+ gint e2 = -1;
+ gint y1 = clist->clist_window_height;
+ gint y2 = clist->clist_window_height;
+ gint h1 = 0;
+ gint h2 = 0;
+ gint top;
+
+ if (clist->selection_mode != GTK_SELECTION_MULTIPLE || clist->anchor == -1)
+ return;
+
+ if (row < 0)
+ row = 0;
+ if (row >= clist->rows)
+ row = clist->rows - 1;
+
+ /* extending downwards */
+ if (row > clist->drag_pos && clist->anchor <= clist->drag_pos)
+ {
+ s2 = clist->drag_pos + 1;
+ e2 = row;
+ }
+ /* extending upwards */
+ else if (row < clist->drag_pos && clist->anchor >= clist->drag_pos)
+ {
+ s2 = row;
+ e2 = clist->drag_pos - 1;
+ }
+ else if (row < clist->drag_pos && clist->anchor < clist->drag_pos)
+ {
+ e1 = clist->drag_pos;
+ /* row and drag_pos on different sides of anchor :
+ take back the selection between anchor and drag_pos,
+ select between anchor and row */
+ if (row < clist->anchor)
+ {
+ s1 = clist->anchor + 1;
+ s2 = row;
+ e2 = clist->anchor - 1;
+ }
+ /* take back the selection between anchor and drag_pos */
+ else
+ s1 = row + 1;
+ }
+ else if (row > clist->drag_pos && clist->anchor > clist->drag_pos)
+ {
+ s1 = clist->drag_pos;
+ /* row and drag_pos on different sides of anchor :
+ take back the selection between anchor and drag_pos,
+ select between anchor and row */
+ if (row > clist->anchor)
+ {
+ e1 = clist->anchor - 1;
+ s2 = clist->anchor + 1;
+ e2 = row;
+ }
+ /* take back the selection between anchor and drag_pos */
+ else
+ e1 = row - 1;
+ }
+
+ clist->drag_pos = row;
+
+ area.x = 0;
+ area.width = clist->clist_window_width;
+
+ /* restore the elements between s1 and e1 */
+ if (s1 >= 0)
+ {
+ for (i = s1, list = g_list_nth (clist->row_list, i); i <= e1;
+ i++, list = list->next)
+ if (GTK_CMCLIST_ROW (list)->selectable)
+ {
+ if (GTK_CMCLIST_GET_CLASS (clist)->selection_find (clist, i, list))
+ GTK_CMCLIST_ROW (list)->state = GTK_STATE_SELECTED;
+ else
+ GTK_CMCLIST_ROW (list)->state = GTK_STATE_NORMAL;
+ }
+
+ top = ROW_TOP_YPIXEL (clist, clist->focus_row);
+
+ if (top + clist->row_height <= 0)
+ {
+ area.y = 0;
+ area.height = ROW_TOP_YPIXEL (clist, e1) + clist->row_height;
+ draw_rows (clist, &area);
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+ }
+ else if (top >= clist->clist_window_height)
+ {
+ area.y = ROW_TOP_YPIXEL (clist, s1) - 1;
+ area.height = clist->clist_window_height - area.y;
+ draw_rows (clist, &area);
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+ }
+ else if (top < 0)
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+ else if (top + clist->row_height > clist->clist_window_height)
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+
+ y1 = ROW_TOP_YPIXEL (clist, s1) - 1;
+ h1 = (e1 - s1 + 1) * (clist->row_height + CELL_SPACING);
+ }
+
+ /* extend the selection between s2 and e2 */
+ if (s2 >= 0)
+ {
+ for (i = s2, list = g_list_nth (clist->row_list, i); i <= e2;
+ i++, list = list->next)
+ if (GTK_CMCLIST_ROW (list)->selectable &&
+ GTK_CMCLIST_ROW (list)->state != clist->anchor_state)
+ GTK_CMCLIST_ROW (list)->state = clist->anchor_state;
+
+ top = ROW_TOP_YPIXEL (clist, clist->focus_row);
+
+ if (top + clist->row_height <= 0)
+ {
+ area.y = 0;
+ area.height = ROW_TOP_YPIXEL (clist, e2) + clist->row_height;
+ draw_rows (clist, &area);
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+ }
+ else if (top >= clist->clist_window_height)
+ {
+ area.y = ROW_TOP_YPIXEL (clist, s2) - 1;
+ area.height = clist->clist_window_height - area.y;
+ draw_rows (clist, &area);
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+ }
+ else if (top < 0)
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+ else if (top + clist->row_height > clist->clist_window_height)
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+
+ y2 = ROW_TOP_YPIXEL (clist, s2) - 1;
+ h2 = (e2 - s2 + 1) * (clist->row_height + CELL_SPACING);
+ }
+
+ area.y = MAX (0, MIN (y1, y2));
+ if (area.y > clist->clist_window_height)
+ area.y = 0;
+ area.height = MIN (clist->clist_window_height, h1 + h2);
+ if (s1 >= 0 && s2 >= 0)
+ area.height += (clist->row_height + CELL_SPACING);
+ draw_rows (clist, &area);
+}
+
+static void
+start_selection (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist_has_grab (clist))
+ return;
+
+ set_anchor (clist, GTK_CMCLIST_ADD_MODE(clist), clist->focus_row,
+ clist->focus_row);
+}
+
+static void
+end_selection (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))) &&
+ GTK_WIDGET_HAS_FOCUS (clist))
+ return;
+
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+}
+
+static void
+extend_selection (GtkCMCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position,
+ gboolean auto_start_selection)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist_has_grab (clist) ||
+ clist->selection_mode != GTK_SELECTION_MULTIPLE)
+ return;
+
+ if (auto_start_selection)
+ set_anchor (clist, GTK_CMCLIST_ADD_MODE(clist), clist->focus_row,
+ clist->focus_row);
+ else if (clist->anchor == -1)
+ return;
+
+ move_focus_row (clist, scroll_type, position);
+
+ if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
+ clist->clist_window_height)
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+ else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+
+ update_extended_selection (clist, clist->focus_row);
+}
+
+static void
+sync_selection (GtkCMCList *clist,
+ gint row,
+ gint mode)
+{
+ GList *list;
+ gint d;
+
+ if (mode == SYNC_INSERT)
+ d = 1;
+ else
+ d = -1;
+
+ if (clist->focus_row >= row)
+ {
+ if (d > 0 || clist->focus_row > row)
+ clist->focus_row += d;
+ if (clist->focus_row == -1 && clist->rows >= 1)
+ clist->focus_row = 0;
+ else if (d < 0 && clist->focus_row >= clist->rows - 1)
+ clist->focus_row = clist->rows - 2;
+ else if (clist->focus_row >= clist->rows) /* Paranoia */
+ clist->focus_row = clist->rows - 1;
+ }
+
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+
+ clist->anchor = -1;
+ clist->drag_pos = -1;
+ clist->undo_anchor = clist->focus_row;
+
+ list = clist->selection;
+
+ while (list)
+ {
+ if (GPOINTER_TO_INT (list->data) >= row)
+ list->data = ((gchar*) list->data) + d;
+ list = list->next;
+ }
+}
+
+/* GTKOBJECT
+ * gtk_cmclist_destroy
+ * gtk_cmclist_finalize
+ */
+static void
+gtk_cmclist_destroy (GtkObject *object)
+{
+ gint i;
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCLIST (object));
+
+ clist = GTK_CMCLIST (object);
+
+ /* freeze the list */
+ clist->freeze_count++;
+
+ /* get rid of all the rows */
+ gtk_cmclist_clear (clist);
+
+ /* Since we don't have a _remove method, unparent the children
+ * instead of destroying them so the focus will be unset properly.
+ * (For other containers, the _remove method takes care of the
+ * unparent) The destroy will happen when the refcount drops
+ * to zero.
+ */
+
+ /* unref adjustments */
+ if (clist->hadjustment)
+ {
+ g_signal_handlers_disconnect_matched(GTK_OBJECT (clist->hadjustment), G_SIGNAL_MATCH_DATA,
+ 0, 0, 0, 0, clist);
+ g_object_unref (GTK_OBJECT (clist->hadjustment));
+ clist->hadjustment = NULL;
+ }
+ if (clist->vadjustment)
+ {
+ g_signal_handlers_disconnect_matched(GTK_OBJECT (clist->vadjustment), G_SIGNAL_MATCH_DATA,
+ 0, 0, 0, 0, clist);
+ g_object_unref (GTK_OBJECT (clist->vadjustment));
+ clist->vadjustment = NULL;
+ }
+
+ remove_grab (clist);
+
+ /* destroy the column buttons */
+ 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_OBJECT_CLASS (parent_class)->destroy)
+ (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_cmclist_finalize (GObject *object)
+{
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCLIST (object));
+
+ clist = GTK_CMCLIST (object);
+
+ columns_delete (clist);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/* GTKWIDGET
+ * gtk_cmclist_realize
+ * gtk_cmclist_unrealize
+ * gtk_cmclist_map
+ * gtk_cmclist_unmap
+ * gtk_cmclist_expose
+ * gtk_cmclist_style_set
+ * gtk_cmclist_button_press
+ * gtk_cmclist_button_release
+ * gtk_cmclist_motion
+ * gtk_cmclist_size_request
+ * gtk_cmclist_size_allocate
+ */
+static void
+gtk_cmclist_realize (GtkWidget *widget)
+{
+ GtkCMCList *clist;
+ GdkWindowAttr attributes;
+ GdkGCValues values;
+ GtkCMCListRow *clist_row;
+ GList *list;
+ gint attributes_mask;
+ gint border_width;
+ gint i;
+ gint j;
+
+ g_return_if_fail (GTK_IS_CMCLIST (widget));
+
+ clist = GTK_CMCLIST (widget);
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x + border_width;
+ attributes.y = widget->allocation.y + border_width;
+ attributes.width = widget->allocation.width - border_width * 2;
+ attributes.height = widget->allocation.height - border_width * 2;
+ 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);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_KEY_RELEASE_MASK);
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ /* main window */
+ widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, clist);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+
+ /* column-title window */
+
+ attributes.x = clist->column_title_area.x;
+ attributes.y = clist->column_title_area.y;
+ attributes.width = clist->column_title_area.width;
+ attributes.height = clist->column_title_area.height;
+
+ clist->title_window = gdk_window_new (widget->window, &attributes,
+ attributes_mask);
+ gdk_window_set_user_data (clist->title_window, clist);
+
+ gtk_style_set_background (widget->style, clist->title_window,
+ GTK_STATE_NORMAL);
+ gdk_window_show (clist->title_window);
+
+ /* set things up so column buttons are drawn in title window */
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].button)
+ gtk_widget_set_parent_window (clist->column[i].button,
+ clist->title_window);
+
+ /* clist-window */
+ attributes.x = (clist->internal_allocation.x +
+ widget->style->xthickness);
+ attributes.y = (clist->internal_allocation.y +
+ widget->style->ythickness +
+ clist->column_title_area.height);
+ attributes.width = clist->clist_window_width;
+ attributes.height = clist->clist_window_height;
+
+ clist->clist_window = gdk_window_new (widget->window, &attributes,
+ attributes_mask);
+ gdk_window_set_user_data (clist->clist_window, clist);
+
+ gdk_window_set_background (clist->clist_window,
+ &widget->style->base[GTK_STATE_NORMAL]);
+ gdk_window_show (clist->clist_window);
+ gdk_drawable_get_size (clist->clist_window, &clist->clist_window_width,
+ &clist->clist_window_height);
+
+ /* create resize windows */
+ attributes.wclass = GDK_INPUT_ONLY;
+ attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK);
+ attributes_mask = GDK_WA_CURSOR;
+ attributes.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
+ GDK_SB_H_DOUBLE_ARROW);
+ clist->cursor_drag = attributes.cursor;
+
+ attributes.x = LIST_WIDTH (clist) + 1;
+ attributes.y = 0;
+ attributes.width = 0;
+ attributes.height = 0;
+
+ for (i = 0; i < clist->columns; i++)
+ {
+ clist->column[i].window = gdk_window_new (clist->title_window,
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (clist->column[i].window, clist);
+ }
+
+ /* This is slightly less efficient than creating them with the
+ * right size to begin with, but easier
+ */
+ size_allocate_title_buttons (clist);
+
+ /* GCs */
+ clist->fg_gc = gdk_gc_new (widget->window);
+ clist->bg_gc = gdk_gc_new (widget->window);
+
+ /* We'll use this gc to do scrolling as well */
+ gdk_gc_set_exposures (clist->fg_gc, TRUE);
+
+ values.foreground = (widget->style->white.pixel==0 ?
+ widget->style->black:widget->style->white);
+ values.function = GDK_XOR;
+ values.subwindow_mode = GDK_INCLUDE_INFERIORS;
+ clist->xor_gc = gdk_gc_new_with_values (widget->window,
+ &values,
+ GDK_GC_FOREGROUND |
+ GDK_GC_FUNCTION |
+ GDK_GC_SUBWINDOW);
+
+ /* attach optional row/cell styles, allocate foreground/background colors */
+ list = clist->row_list;
+ for (i = 0; i < clist->rows; i++)
+ {
+ clist_row = list->data;
+ list = list->next;
+
+ if (clist_row->style)
+ clist_row->style = gtk_style_attach (clist_row->style,
+ clist->clist_window);
+
+ if (clist_row->fg_set || clist_row->bg_set)
+ {
+ GdkColormap *colormap;
+
+ colormap = gtk_widget_get_colormap (widget);
+ if (clist_row->fg_set)
+ gdk_colormap_alloc_color (colormap, &clist_row->foreground, TRUE, TRUE);
+ if (clist_row->bg_set)
+ gdk_colormap_alloc_color (colormap, &clist_row->background, TRUE, TRUE);
+ }
+
+ for (j = 0; j < clist->columns; j++)
+ if (clist_row->cell[j].style)
+ clist_row->cell[j].style =
+ gtk_style_attach (clist_row->cell[j].style, clist->clist_window);
+ }
+}
+
+static void
+gtk_cmclist_unrealize (GtkWidget *widget)
+{
+ gint i;
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCLIST (widget));
+
+ clist = GTK_CMCLIST (widget);
+
+ /* freeze the list */
+ clist->freeze_count++;
+
+ if (GTK_WIDGET_MAPPED (widget))
+ gtk_cmclist_unmap (widget);
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+
+ /* detach optional row/cell styles */
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ GtkCMCListRow *clist_row;
+ GList *list;
+ gint j;
+
+ list = clist->row_list;
+ for (i = 0; i < clist->rows; i++)
+ {
+ clist_row = list->data;
+ list = list->next;
+
+ if (clist_row->style)
+ gtk_style_detach (clist_row->style);
+ for (j = 0; j < clist->columns; j++)
+ if (clist_row->cell[j].style)
+ gtk_style_detach (clist_row->cell[j].style);
+ }
+ }
+
+ gdk_cursor_unref (clist->cursor_drag);
+ g_object_unref (clist->xor_gc);
+ g_object_unref (clist->fg_gc);
+ g_object_unref (clist->bg_gc);
+
+ for (i = 0; i < clist->columns; i++)
+ {
+ if (clist->column[i].button)
+ gtk_widget_unrealize (clist->column[i].button);
+ if (clist->column[i].window)
+ {
+ gdk_window_set_user_data (clist->column[i].window, NULL);
+ gdk_window_destroy (clist->column[i].window);
+ clist->column[i].window = NULL;
+ }
+ }
+
+ gdk_window_set_user_data (clist->clist_window, NULL);
+ gdk_window_destroy (clist->clist_window);
+ clist->clist_window = NULL;
+
+ gdk_window_set_user_data (clist->title_window, NULL);
+ gdk_window_destroy (clist->title_window);
+ clist->title_window = NULL;
+
+ clist->cursor_drag = NULL;
+ clist->xor_gc = NULL;
+ clist->fg_gc = NULL;
+ clist->bg_gc = NULL;
+
+ if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+ (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
+gtk_cmclist_map (GtkWidget *widget)
+{
+ gint i;
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCLIST (widget));
+
+ clist = GTK_CMCLIST (widget);
+
+ if (!GTK_WIDGET_MAPPED (widget))
+ {
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+
+ /* map column buttons */
+ for (i = 0; i < clist->columns; i++)
+ {
+ if (clist->column[i].button &&
+ GTK_WIDGET_VISIBLE (clist->column[i].button) &&
+ !GTK_WIDGET_MAPPED (clist->column[i].button))
+ gtk_widget_map (clist->column[i].button);
+ }
+
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].window && clist->column[i].button)
+ {
+ gdk_window_raise (clist->column[i].window);
+ gdk_window_show (clist->column[i].window);
+ }
+
+ gdk_window_show (clist->title_window);
+ gdk_window_show (clist->clist_window);
+ gdk_window_show (widget->window);
+
+ /* unfreeze the list */
+ clist->freeze_count = 0;
+ }
+}
+
+static void
+gtk_cmclist_unmap (GtkWidget *widget)
+{
+ gint i;
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCLIST (widget));
+
+ clist = GTK_CMCLIST (widget);
+
+ if (GTK_WIDGET_MAPPED (widget))
+ {
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+
+ if (clist_has_grab (clist))
+ {
+ remove_grab (clist);
+
+ GTK_CMCLIST_GET_CLASS (widget)->resync_selection (clist, NULL);
+
+ clist->click_cell.row = -1;
+ clist->click_cell.column = -1;
+ clist->drag_button = 0;
+
+ if (GTK_CMCLIST_IN_DRAG(clist))
+ {
+ gpointer drag_data;
+
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_IN_DRAG);
+ drag_data = g_object_get_data (G_OBJECT (clist),
+ "gtk-site-data");
+ if (drag_data)
+ g_signal_handlers_unblock_matched(G_OBJECT(clist), G_SIGNAL_MATCH_DATA,
+ 0, 0, 0, 0, drag_data);
+ }
+ }
+
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].window)
+ gdk_window_hide (clist->column[i].window);
+
+ gdk_window_hide (clist->clist_window);
+ gdk_window_hide (clist->title_window);
+ gdk_window_hide (widget->window);
+
+ /* unmap column buttons */
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].button &&
+ GTK_WIDGET_MAPPED (clist->column[i].button))
+ gtk_widget_unmap (clist->column[i].button);
+
+ /* freeze the list */
+ clist->freeze_count++;
+ }
+}
+
+static gint
+gtk_cmclist_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkCMCList *clist;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ clist = GTK_CMCLIST (widget);
+
+ /* draw border */
+ if (event->window == widget->window)
+ gtk_paint_shadow (widget->style, widget->window,
+ GTK_STATE_NORMAL, clist->shadow_type,
+ NULL, NULL, NULL,
+ 0, 0,
+ clist->clist_window_width +
+ (2 * widget->style->xthickness),
+ clist->clist_window_height +
+ (2 * widget->style->ythickness) +
+ clist->column_title_area.height);
+
+ /* exposure events on the list */
+ if (event->window == clist->clist_window)
+ draw_rows (clist, &event->area);
+
+ if (event->window == clist->clist_window &&
+ clist->drag_highlight_row >= 0)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_drag_highlight
+ (clist, g_list_nth (clist->row_list,
+ clist->drag_highlight_row)->data,
+ clist->drag_highlight_row, clist->drag_highlight_pos);
+
+ if (event->window == clist->title_window)
+ {
+ gint i;
+
+ for (i = 0; i < clist->columns; i++)
+ {
+ if (clist->column[i].button)
+ gtk_container_propagate_expose (GTK_CONTAINER (clist),
+ clist->column[i].button,
+ event);
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_cmclist_style_set (GtkWidget *widget,
+ GtkStyle *previous_style)
+{
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCLIST (widget));
+
+ if (GTK_WIDGET_CLASS (parent_class)->style_set)
+ (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
+
+ clist = GTK_CMCLIST (widget);
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gtk_style_set_background (widget->style, widget->window, widget->state);
+ gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_NORMAL);
+ gdk_window_set_background (clist->clist_window, &widget->style->base[GTK_STATE_NORMAL]);
+ }
+
+ /* Fill in data after widget has correct style */
+
+ /* text properties */
+ if (!GTK_CMCLIST_ROW_HEIGHT_SET(clist))
+ /* Reset clist->row_height */
+ gtk_cmclist_set_row_height (clist, 0);
+
+ /* Column widths */
+ if (!GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ {
+ gint width;
+ gint i;
+
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].auto_resize)
+ {
+ width = gtk_cmclist_optimal_column_width (clist, i);
+ if (width != clist->column[i].width)
+ gtk_cmclist_set_column_width (clist, i, width);
+ }
+ }
+}
+
+static gint
+gtk_cmclist_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ gint i;
+ GtkCMCList *clist;
+ gint x;
+ gint y;
+ gint row;
+ gint column;
+ gint button_actions;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ clist = GTK_CMCLIST (widget);
+
+ button_actions = clist->button_actions[event->button - 1];
+
+ if (button_actions == GTK_CMBUTTON_IGNORED)
+ return FALSE;
+
+ /* selections on the list */
+ if (event->window == clist->clist_window)
+ {
+ x = event->x;
+ y = event->y;
+
+ if (get_selection_info (clist, x, y, &row, &column))
+ {
+ gint old_row = clist->focus_row;
+
+ if (clist->focus_row == -1)
+ old_row = row;
+
+ if (event->type == GDK_BUTTON_PRESS)
+ {
+ GdkEventMask mask = ((1 << (4 + event->button)) |
+ GDK_POINTER_MOTION_HINT_MASK |
+ GDK_BUTTON_RELEASE_MASK);
+
+ if (gdk_pointer_grab (clist->clist_window, FALSE, mask,
+ NULL, NULL, event->time))
+ return FALSE;
+ gtk_grab_add (widget);
+
+ clist->click_cell.row = row;
+ clist->click_cell.column = column;
+ clist->drag_button = event->button;
+ }
+ else
+ {
+ clist->click_cell.row = -1;
+ clist->click_cell.column = -1;
+
+ clist->drag_button = 0;
+ remove_grab (clist);
+ }
+
+ if (button_actions & GTK_CMBUTTON_SELECTS)
+ {
+ if (GTK_CMCLIST_ADD_MODE(clist))
+ {
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_ADD_MODE);
+ if (GTK_WIDGET_HAS_FOCUS(widget))
+ {
+ gtk_cmclist_draw_focus (widget);
+ gdk_gc_set_line_attributes (clist->xor_gc, 1,
+ GDK_LINE_SOLID, 0, 0);
+ clist->focus_row = row;
+ gtk_cmclist_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_cmclist_draw_focus (widget);
+ clist->focus_row = row;
+ gtk_cmclist_draw_focus (widget);
+ }
+ else
+ clist->focus_row = row;
+ }
+ }
+
+ if (!GTK_WIDGET_HAS_FOCUS(widget))
+ gtk_widget_grab_focus (widget);
+
+ if (button_actions & GTK_CMBUTTON_SELECTS)
+ {
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_SINGLE:
+ if (event->type != GDK_BUTTON_PRESS)
+ {
+ g_signal_emit (GTK_OBJECT (clist),
+ clist_signals[SELECT_ROW], 0,
+ row, column, event);
+ clist->anchor = -1;
+ }
+ else
+ clist->anchor = row;
+ break;
+ case GTK_SELECTION_BROWSE:
+ g_signal_emit (GTK_OBJECT (clist),
+ clist_signals[SELECT_ROW], 0,
+ row, column, event);
+ break;
+ case GTK_SELECTION_MULTIPLE:
+ if (event->type != GDK_BUTTON_PRESS)
+ {
+ if (clist->anchor != -1)
+ {
+ update_extended_selection (clist, clist->focus_row);
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection
+ (clist, (GdkEvent *) event);
+ }
+ g_signal_emit (GTK_OBJECT (clist),
+ clist_signals[SELECT_ROW], 0,
+ row, column, event);
+ break;
+ }
+
+ if (event->state & GDK_CONTROL_MASK)
+ {
+ if (event->state & GDK_SHIFT_MASK)
+ {
+ if (clist->anchor < 0)
+ {
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+ clist->anchor = old_row;
+ clist->drag_pos = old_row;
+ clist->undo_anchor = old_row;
+ }
+ update_extended_selection (clist, clist->focus_row);
+ }
+ else
+ {
+ if (clist->anchor == -1)
+ set_anchor (clist, TRUE, row, old_row);
+ else
+ update_extended_selection (clist,
+ clist->focus_row);
+ }
+ break;
+ }
+
+ if (event->state & GDK_SHIFT_MASK)
+ {
+ set_anchor (clist, FALSE, old_row, old_row);
+ update_extended_selection (clist, clist->focus_row);
+ break;
+ }
+
+ if (clist->anchor == -1)
+ set_anchor (clist, FALSE, row, old_row);
+ else
+ update_extended_selection (clist, clist->focus_row);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return TRUE;
+ }
+
+ /* press on resize windows */
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].resizeable && clist->column[i].window &&
+ event->window == clist->column[i].window)
+ {
+ gpointer drag_data;
+
+ if (gdk_pointer_grab (clist->column[i].window, FALSE,
+ GDK_POINTER_MOTION_HINT_MASK |
+ GDK_BUTTON1_MOTION_MASK |
+ GDK_BUTTON_RELEASE_MASK,
+ NULL, NULL, event->time))
+ return FALSE;
+
+ gtk_grab_add (widget);
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_IN_DRAG);
+
+ /* block attached dnd signal handler */
+ drag_data = g_object_get_data (G_OBJECT (clist), "gtk-site-data");
+ if (drag_data)
+ g_signal_handlers_block_matched(G_OBJECT(clist), G_SIGNAL_MATCH_DATA,
+ 0, 0, 0, 0, drag_data);
+
+ if (!GTK_WIDGET_HAS_FOCUS(widget))
+ gtk_widget_grab_focus (widget);
+
+ clist->drag_pos = i;
+ clist->x_drag = (COLUMN_LEFT_XPIXEL(clist, i) + COLUMN_INSET +
+ clist->column[i].area.width + CELL_SPACING);
+
+ if (GTK_CMCLIST_ADD_MODE(clist))
+ gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
+ draw_xor_line (clist);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_cmclist_button_release (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkCMCList *clist;
+ gint button_actions;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ clist = GTK_CMCLIST (widget);
+
+ button_actions = clist->button_actions[event->button - 1];
+ if (button_actions == GTK_CMBUTTON_IGNORED)
+ return FALSE;
+
+ /* release on resize windows */
+ if (GTK_CMCLIST_IN_DRAG(clist))
+ {
+ gpointer drag_data;
+ gint width;
+ gint x;
+ gint i;
+
+ i = clist->drag_pos;
+ clist->drag_pos = -1;
+
+ /* unblock attached dnd signal handler */
+ drag_data = g_object_get_data (G_OBJECT (clist), "gtk-site-data");
+ if (drag_data)
+ g_signal_handlers_unblock_matched(G_OBJECT(clist), G_SIGNAL_MATCH_DATA,
+ 0, 0, 0, 0, drag_data);
+
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_IN_DRAG);
+ gtk_widget_get_pointer (widget, &x, NULL);
+ gtk_grab_remove (widget);
+ gdk_display_pointer_ungrab (gtk_widget_get_display (widget), event->time);
+
+ if (clist->x_drag >= 0)
+ draw_xor_line (clist);
+
+ if (GTK_CMCLIST_ADD_MODE(clist))
+ {
+ gdk_gc_set_line_attributes (clist->xor_gc, 1,
+ GDK_LINE_ON_OFF_DASH, 0, 0);
+ gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
+ }
+
+ width = new_column_width (clist, i, &x);
+ gtk_cmclist_set_column_width (clist, i, width);
+
+ return TRUE;
+ }
+
+ if (clist->drag_button == event->button)
+ {
+ gint row;
+ gint column;
+
+ clist->drag_button = 0;
+ clist->click_cell.row = -1;
+ clist->click_cell.column = -1;
+
+ remove_grab (clist);
+
+ if (button_actions & GTK_CMBUTTON_SELECTS)
+ {
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_MULTIPLE:
+ if (!(event->state & GDK_SHIFT_MASK) ||
+ !GTK_WIDGET_CAN_FOCUS (widget) ||
+ event->x < 0 || event->x >= clist->clist_window_width ||
+ event->y < 0 || event->y >= clist->clist_window_height)
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection
+ (clist, (GdkEvent *) event);
+ break;
+ case GTK_SELECTION_SINGLE:
+ if (get_selection_info (clist, event->x, event->y,
+ &row, &column))
+ {
+ if (row >= 0 && row < clist->rows && clist->anchor == row)
+ toggle_row (clist, row, column, (GdkEvent *) event);
+ }
+ clist->anchor = -1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_cmclist_motion (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ GtkCMCList *clist;
+ gint x;
+ gint y;
+ gint row;
+ gint new_width;
+ gint button_actions = 0;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (widget), FALSE);
+
+ clist = GTK_CMCLIST (widget);
+ if (!clist_has_grab (clist))
+ return FALSE;
+
+ if (clist->drag_button > 0)
+ button_actions = clist->button_actions[clist->drag_button - 1];
+
+ if (GTK_CMCLIST_IN_DRAG(clist))
+ {
+ if (event->is_hint || event->window != widget->window)
+ gtk_widget_get_pointer (widget, &x, NULL);
+ else
+ x = event->x;
+
+ new_width = new_column_width (clist, clist->drag_pos, &x);
+ if (x != clist->x_drag)
+ {
+ /* x_drag < 0 indicates that the xor line is already invisible */
+ if (clist->x_drag >= 0)
+ draw_xor_line (clist);
+
+ clist->x_drag = x;
+
+ if (clist->x_drag >= 0)
+ draw_xor_line (clist);
+ }
+
+ if (new_width <= MAX (COLUMN_MIN_WIDTH + 1,
+ clist->column[clist->drag_pos].min_width + 1))
+ {
+ if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) < 0 && x < 0)
+ gtk_cmclist_moveto (clist, -1, clist->drag_pos, 0, 0);
+ return FALSE;
+ }
+ if (clist->column[clist->drag_pos].max_width >= COLUMN_MIN_WIDTH &&
+ new_width >= clist->column[clist->drag_pos].max_width)
+ {
+ if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) + new_width >
+ clist->clist_window_width && x < 0)
+ move_horizontal (clist,
+ COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) +
+ new_width - clist->clist_window_width +
+ COLUMN_INSET + CELL_SPACING);
+ return FALSE;
+ }
+ }
+
+ if (event->is_hint || event->window != clist->clist_window)
+ gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
+ else
+ {
+ x = event->x;
+ y = event->y;
+ }
+
+ if (GTK_CMCLIST_REORDERABLE(clist) && button_actions & GTK_CMBUTTON_DRAGS)
+ {
+ /* delayed drag start */
+ if (event->window == clist->clist_window &&
+ clist->click_cell.row >= 0 && clist->click_cell.column >= 0 &&
+ (y < 0 || y >= clist->clist_window_height ||
+ x < 0 || x >= clist->clist_window_width ||
+ y < ROW_TOP_YPIXEL (clist, clist->click_cell.row) ||
+ y >= (ROW_TOP_YPIXEL (clist, clist->click_cell.row) +
+ clist->row_height) ||
+ x < COLUMN_LEFT_XPIXEL (clist, clist->click_cell.column) ||
+ x >= (COLUMN_LEFT_XPIXEL(clist, clist->click_cell.column) +
+ clist->column[clist->click_cell.column].area.width)))
+ {
+ GtkTargetList *target_list;
+
+ target_list = gtk_target_list_new (&clist_target_table, 1);
+ gtk_drag_begin (widget, target_list, GDK_ACTION_MOVE,
+ clist->drag_button, (GdkEvent *)event);
+
+ }
+ return TRUE;
+ }
+
+ /* horizontal autoscrolling */
+ if (clist->hadjustment && LIST_WIDTH (clist) > clist->clist_window_width &&
+ (x < 0 || x >= clist->clist_window_width))
+ {
+ if (clist->htimer)
+ return FALSE;
+
+ clist->htimer = gdk_threads_add_timeout
+ (SCROLL_TIME, (GSourceFunc) horizontal_timeout, clist);
+
+ if (!((x < 0 && clist->hadjustment->value == 0) ||
+ (x >= clist->clist_window_width &&
+ clist->hadjustment->value ==
+ LIST_WIDTH (clist) - clist->clist_window_width)))
+ {
+ if (x < 0)
+ move_horizontal (clist, -1 + (x/2));
+ else
+ move_horizontal (clist, 1 + (x - clist->clist_window_width) / 2);
+ }
+ }
+
+ if (GTK_CMCLIST_IN_DRAG(clist))
+ return FALSE;
+
+ /* vertical autoscrolling */
+ row = ROW_FROM_YPIXEL (clist, y);
+
+ /* don't scroll on last pixel row if it's a cell spacing */
+ if (y == clist->clist_window_height - 1 &&
+ y == ROW_TOP_YPIXEL (clist, row-1) + clist->row_height)
+ return FALSE;
+
+ if (LIST_HEIGHT (clist) > clist->clist_window_height &&
+ (y < 0 || y >= clist->clist_window_height))
+ {
+ if (clist->vtimer)
+ return FALSE;
+
+ clist->vtimer = gdk_threads_add_timeout (SCROLL_TIME,
+ (GSourceFunc) vertical_timeout, clist);
+
+ if (clist->drag_button &&
+ ((y < 0 && clist->focus_row == 0) ||
+ (y >= clist->clist_window_height &&
+ clist->focus_row == clist->rows - 1)))
+ return FALSE;
+ }
+
+ row = CLAMP (row, 0, clist->rows - 1);
+
+ if (button_actions & GTK_CMBUTTON_SELECTS &
+ !g_object_get_data (G_OBJECT (widget), "gtk-site-data"))
+ {
+ if (row == clist->focus_row)
+ return FALSE;
+
+ gtk_cmclist_draw_focus (widget);
+ clist->focus_row = row;
+ gtk_cmclist_draw_focus (widget);
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_BROWSE:
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+ clist->focus_row, -1, event);
+ break;
+ case GTK_SELECTION_MULTIPLE:
+ update_extended_selection (clist, clist->focus_row);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (ROW_TOP_YPIXEL(clist, row) < 0)
+ move_vertical (clist, row, 0);
+ else if (ROW_TOP_YPIXEL(clist, row) + clist->row_height >
+ clist->clist_window_height)
+ move_vertical (clist, row, 1);
+
+ return FALSE;
+}
+
+static void
+gtk_cmclist_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkCMCList *clist;
+ gint i;
+ gint font_height = 0;
+ g_return_if_fail (GTK_IS_CMCLIST (widget));
+ g_return_if_fail (requisition != NULL);
+
+ clist = GTK_CMCLIST (widget);
+
+ requisition->width = 0;
+ requisition->height = 0;
+
+ /* compute the size of the column title (title) area */
+ clist->column_title_area.height = 0;
+ if (GTK_CMCLIST_SHOW_TITLES(clist)) {
+ font_height = (pango_font_description_get_size((GTK_WIDGET(clist)->style)->font_desc)/PANGO_SCALE)*2+4;
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].button)
+ {
+ GtkRequisition child_requisition;
+
+ gtk_widget_size_request (clist->column[i].button,
+ &child_requisition);
+ clist->column_title_area.height =
+ MAX (clist->column_title_area.height,
+ child_requisition.height - 2);
+ }
+ clist->column_title_area.height = font_height;
+ }
+ requisition->width += (widget->style->xthickness +
+ GTK_CONTAINER (widget)->border_width) * 2;
+ requisition->height += (clist->column_title_area.height +
+ (widget->style->ythickness +
+ GTK_CONTAINER (widget)->border_width) * 2);
+
+ /* if (!clist->hadjustment) */
+ requisition->width += list_requisition_width (clist);
+ /* if (!clist->vadjustment) */
+ requisition->height += LIST_HEIGHT (clist);
+}
+
+static void
+gtk_cmclist_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkCMCList *clist;
+ GtkAllocation clist_allocation;
+ gint border_width;
+
+ g_return_if_fail (GTK_IS_CMCLIST (widget));
+ g_return_if_fail (allocation != NULL);
+
+ clist = GTK_CMCLIST (widget);
+ widget->allocation = *allocation;
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move_resize (widget->window,
+ allocation->x + border_width,
+ allocation->y + border_width,
+ allocation->width - border_width * 2,
+ allocation->height - border_width * 2);
+ }
+
+ /* use internal allocation structure for all the math
+ * because it's easier than always subtracting the container
+ * border width */
+ clist->internal_allocation.x = 0;
+ clist->internal_allocation.y = 0;
+ clist->internal_allocation.width = MAX (1, (gint)allocation->width -
+ border_width * 2);
+ clist->internal_allocation.height = MAX (1, (gint)allocation->height -
+ border_width * 2);
+
+ /* allocate clist window assuming no scrollbars */
+ clist_allocation.x = (clist->internal_allocation.x +
+ widget->style->xthickness);
+ clist_allocation.y = (clist->internal_allocation.y +
+ widget->style->ythickness +
+ clist->column_title_area.height);
+ clist_allocation.width = MAX (1, (gint)clist->internal_allocation.width -
+ (2 * (gint)widget->style->xthickness));
+ clist_allocation.height = MAX (1, (gint)clist->internal_allocation.height -
+ (2 * (gint)widget->style->ythickness) -
+ (gint)clist->column_title_area.height);
+
+ clist->clist_window_width = clist_allocation.width;
+ clist->clist_window_height = clist_allocation.height;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move_resize (clist->clist_window,
+ clist_allocation.x,
+ clist_allocation.y,
+ clist_allocation.width,
+ clist_allocation.height);
+ }
+
+ /* position the window which holds the column title buttons */
+ clist->column_title_area.x = widget->style->xthickness;
+ clist->column_title_area.y = widget->style->ythickness;
+ clist->column_title_area.width = clist_allocation.width;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move_resize (clist->title_window,
+ clist->column_title_area.x,
+ clist->column_title_area.y,
+ clist->column_title_area.width,
+ clist->column_title_area.height);
+ }
+
+ /* column button allocation */
+ size_allocate_columns (clist, FALSE);
+ size_allocate_title_buttons (clist);
+
+ adjust_adjustments (clist, TRUE);
+}
+
+/* GTKCONTAINER
+ * gtk_cmclist_forall
+ */
+static void
+gtk_cmclist_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkCMCList *clist;
+ guint i;
+
+ g_return_if_fail (GTK_IS_CMCLIST (container));
+ g_return_if_fail (callback != NULL);
+
+ if (!include_internals)
+ return;
+
+ clist = GTK_CMCLIST (container);
+
+ /* callback for the column buttons */
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].button)
+ (*callback) (clist->column[i].button, callback_data);
+}
+
+/* PRIVATE DRAWING FUNCTIONS
+ * get_cell_style
+ * draw_cell_pixmap
+ * draw_row
+ * draw_rows
+ * draw_xor_line
+ * clist_refresh
+ */
+static void
+get_cell_style (GtkCMCList *clist,
+ GtkCMCListRow *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;
+
+ 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 (state != GTK_STATE_SELECTED)
+ {
+ if (fg_gc && clist_row->fg_set)
+ *fg_gc = clist->fg_gc;
+ if (bg_gc && clist_row->bg_set)
+ *bg_gc = clist->bg_gc;
+ }
+ }
+}
+
+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)
+{
+ gint xsrc = 0;
+ gint ysrc = 0;
+
+ 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;
+
+ 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;
+
+ gdk_draw_drawable (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
+ gdk_gc_set_clip_origin (fg_gc, 0, 0);
+ if (mask)
+ gdk_gc_set_clip_mask (fg_gc, NULL);
+
+ return x + MAX (width, 0);
+}
+
+static void
+draw_row (GtkCMCList *clist,
+ GdkRectangle *area,
+ gint row,
+ GtkCMCListRow *clist_row)
+{
+ GtkWidget *widget;
+ GdkRectangle *rect;
+ GdkRectangle row_rectangle;
+ GdkRectangle cell_rectangle;
+ GdkRectangle clip_rectangle;
+ GdkRectangle intersect_rectangle;
+ gint last_column;
+ gint state;
+ gint i;
+
+ g_return_if_fail (clist != NULL);
+
+ /* bail now if we arn't drawable yet */
+ if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows)
+ return;
+
+ widget = GTK_WIDGET (clist);
+
+ /* if the function is passed the pointer to the row instead of null,
+ * it avoids this expensive lookup */
+ if (!clist_row)
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ /* rectangle of the entire row */
+ row_rectangle.x = 0;
+ row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
+ row_rectangle.width = clist->clist_window_width;
+ row_rectangle.height = clist->row_height;
+
+ /* rectangle of the cell spacing above the row */
+ cell_rectangle.x = 0;
+ cell_rectangle.y = row_rectangle.y - CELL_SPACING;
+ cell_rectangle.width = row_rectangle.width;
+ cell_rectangle.height = CELL_SPACING;
+
+ /* 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;
+
+ if (clist_row->state == GTK_STATE_NORMAL)
+ {
+ if (clist_row->fg_set)
+ 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);
+ }
+
+ state = clist_row->state;
+
+ /* draw the cell borders and background */
+ if (area)
+ {
+ rect = &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);
+
+ /* 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 (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))
+ return;
+
+ }
+ else
+ {
+ rect = &clip_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);
+
+ /* 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;
+
+ 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);
+ }
+ }
+
+ for (last_column = clist->columns - 1;
+ last_column >= 0 && !clist->column[last_column].visible; last_column--)
+ ;
+
+ /* 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;
+ PangoRectangle logical_rect;
+
+ gint width;
+ gint height;
+ gint pixmap_width;
+ gint offset = 0;
+
+ if (!clist->column[i].visible)
+ continue;
+
+ get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
+
+ clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
+ clip_rectangle.width = clist->column[i].area.width;
+
+ /* calculate clipping region clipping region */
+ clip_rectangle.x -= COLUMN_INSET + CELL_SPACING;
+ clip_rectangle.width += (2 * COLUMN_INSET + CELL_SPACING +
+ (i == last_column) * CELL_SPACING);
+
+ if (area && !gdk_rectangle_intersect (area, &clip_rectangle,
+ &intersect_rectangle))
+ continue;
+
+ gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
+ rect->x, rect->y, rect->width, rect->height);
+
+ clip_rectangle.x += COLUMN_INSET + CELL_SPACING;
+ clip_rectangle.width -= (2 * COLUMN_INSET + CELL_SPACING +
+ (i == last_column) * CELL_SPACING);
+
+
+ /* calculate real width for column justification */
+
+ layout = _gtk_cmclist_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;
+
+ pixmap_width = 0;
+ offset = 0;
+ switch (clist_row->cell[i].type)
+ {
+ case GTK_CMCELL_PIXMAP:
+ gdk_drawable_get_size (GTK_CMCELL_PIXMAP (clist_row->cell[i])->pixmap,
+ &pixmap_width, &height);
+ width += pixmap_width;
+ break;
+ case GTK_CMCELL_PIXTEXT:
+ gdk_drawable_get_size (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+ &pixmap_width, &height);
+ width += pixmap_width + GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
+ 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 + clist_row->cell[i].horizontal +
+ (clip_rectangle.width / 2) - (width / 2));
+ break;
+ };
+
+ /* Draw Text and/or Pixmap */
+ switch (clist_row->cell[i].type)
+ {
+ case GTK_CMCELL_PIXMAP:
+ draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
+ GTK_CMCELL_PIXMAP (clist_row->cell[i])->pixmap,
+ GTK_CMCELL_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_CMCELL_PIXTEXT:
+ offset =
+ draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
+ GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+ GTK_CMCELL_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_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
+
+ /* Fall through */
+ case GTK_CMCELL_TEXT:
+ if (layout)
+ {
+ gint row_center_offset = (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);
+ g_object_unref (G_OBJECT (layout));
+ gdk_gc_set_clip_rectangle (fg_gc, NULL);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* draw focus rectangle */
+ if (clist->focus_row == row &&
+ GTK_WIDGET_CAN_FOCUS (widget) && GTK_WIDGET_HAS_FOCUS(widget))
+ {
+ 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);
+ }
+ }
+}
+
+static void
+draw_rows (GtkCMCList *clist,
+ GdkRectangle *area)
+{
+ GList *list;
+ GtkCMCListRow *clist_row;
+ gint i;
+ gint first_row;
+ gint last_row;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist->row_height == 0 ||
+ !GTK_WIDGET_DRAWABLE (clist))
+ return;
+
+ if (area)
+ {
+ first_row = ROW_FROM_YPIXEL (clist, area->y);
+ last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
+ }
+ else
+ {
+ first_row = ROW_FROM_YPIXEL (clist, 0);
+ last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
+ }
+
+ /* this is a small special case which exposes the bottom cell line
+ * on the last row -- it might go away if I change the wall the cell
+ * spacings are drawn
+ */
+ if (clist->rows == first_row)
+ first_row--;
+
+ list = ROW_ELEMENT (clist, first_row);
+ i = first_row;
+ while (list)
+ {
+ clist_row = list->data;
+ list = list->next;
+
+ if (i > last_row)
+ return;
+
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, area, i, clist_row);
+ i++;
+ }
+
+ if (!area)
+ gdk_window_clear_area (clist->clist_window, 0,
+ ROW_TOP_YPIXEL (clist, i), 0, 0);
+}
+
+static void
+draw_xor_line (GtkCMCList *clist)
+{
+ GtkWidget *widget;
+
+ g_return_if_fail (clist != NULL);
+
+ widget = GTK_WIDGET (clist);
+
+ gdk_draw_line (widget->window, clist->xor_gc,
+ clist->x_drag,
+ widget->style->ythickness,
+ clist->x_drag,
+ clist->column_title_area.height +
+ clist->clist_window_height + 1);
+}
+
+static void
+clist_refresh (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (CLIST_UNFROZEN (clist))
+ {
+ adjust_adjustments (clist, FALSE);
+ draw_rows (clist, NULL);
+ }
+}
+
+/* get cell from coordinates
+ * get_selection_info
+ * gtk_cmclist_get_selection_info
+ */
+static gint
+get_selection_info (GtkCMCList *clist,
+ gint x,
+ gint y,
+ gint *row,
+ gint *column)
+{
+ gint trow, tcol;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+
+ /* bounds checking, return false if the user clicked
+ * on a blank area */
+ trow = ROW_FROM_YPIXEL (clist, y);
+ if (trow >= clist->rows)
+ return 0;
+
+ if (row)
+ *row = trow;
+
+ tcol = COLUMN_FROM_XPIXEL (clist, x);
+ if (tcol >= clist->columns)
+ return 0;
+
+ if (column)
+ *column = tcol;
+
+ return 1;
+}
+
+gint
+gtk_cmclist_get_selection_info (GtkCMCList *clist,
+ gint x,
+ gint y,
+ gint *row,
+ gint *column)
+{
+ g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+ return get_selection_info (clist, x, y, row, column);
+}
+
+/* PRIVATE ADJUSTMENT FUNCTIONS
+ * adjust_adjustments
+ * vadjustment_changed
+ * hadjustment_changed
+ * vadjustment_value_changed
+ * hadjustment_value_changed
+ * check_exposures
+ */
+static void
+adjust_adjustments (GtkCMCList *clist,
+ gboolean block_resize)
+{
+ if (clist->vadjustment)
+ {
+ clist->vadjustment->page_size = clist->clist_window_height;
+ clist->vadjustment->step_increment = clist->row_height;
+ clist->vadjustment->page_increment =
+ MAX (clist->vadjustment->page_size - clist->vadjustment->step_increment,
+ clist->vadjustment->page_size / 2);
+ clist->vadjustment->lower = 0;
+ clist->vadjustment->upper = LIST_HEIGHT (clist);
+
+ if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist) ||
+ (clist->voffset + (gint)clist->vadjustment->value) != 0)
+ {
+ clist->vadjustment->value = MAX (0, (LIST_HEIGHT (clist) -
+ clist->clist_window_height));
+ g_signal_emit_by_name (GTK_OBJECT (clist->vadjustment),
+ "value_changed");
+ }
+ g_signal_emit_by_name (GTK_OBJECT (clist->vadjustment), "changed");
+ }
+
+ if (clist->hadjustment)
+ {
+ clist->hadjustment->page_size = clist->clist_window_width;
+ clist->hadjustment->step_increment = 10;
+ clist->hadjustment->page_increment =
+ MAX (clist->hadjustment->page_size - clist->hadjustment->step_increment,
+ clist->hadjustment->page_size / 2);
+ clist->hadjustment->lower = 0;
+ clist->hadjustment->upper = LIST_WIDTH (clist);
+
+ if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist) ||
+ (clist->hoffset + (gint)clist->hadjustment->value) != 0)
+ {
+ clist->hadjustment->value = MAX (0, (LIST_WIDTH (clist) -
+ clist->clist_window_width));
+ g_signal_emit_by_name (GTK_OBJECT (clist->hadjustment),
+ "value_changed");
+ }
+ g_signal_emit_by_name (GTK_OBJECT (clist->hadjustment), "changed");
+ }
+
+ if (!block_resize && (!clist->vadjustment || !clist->hadjustment))
+ {
+ GtkWidget *widget;
+ GtkRequisition requisition;
+
+ widget = GTK_WIDGET (clist);
+ gtk_widget_size_request (widget, &requisition);
+
+ if ((!clist->hadjustment &&
+ requisition.width != widget->allocation.width) ||
+ (!clist->vadjustment &&
+ requisition.height != widget->allocation.height))
+ gtk_widget_queue_resize (widget);
+ }
+}
+
+static void
+vadjustment_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ GtkCMCList *clist;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+
+ clist = GTK_CMCLIST (data);
+}
+
+static void
+hadjustment_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ GtkCMCList *clist;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+
+ clist = GTK_CMCLIST (data);
+}
+
+static void
+vadjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ GtkCMCList *clist;
+ gint dy, value;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (GTK_IS_CMCLIST (data));
+
+ clist = GTK_CMCLIST (data);
+
+ if (adjustment != clist->vadjustment)
+ return;
+
+ value = -adjustment->value;
+ dy = value - clist->voffset;
+ clist->voffset = value;
+
+ if (GTK_WIDGET_DRAWABLE (clist))
+ {
+ gdk_window_scroll (clist->clist_window, 0, dy);
+ gdk_window_process_updates (clist->clist_window, FALSE);
+ }
+
+ return;
+}
+
+typedef struct
+{
+ GdkWindow *window;
+ gint dx;
+} ScrollData;
+
+/* The window to which widget->window is relative */
+#define ALLOCATION_WINDOW(widget) \
+ (GTK_WIDGET_NO_WINDOW (widget) ? \
+ (widget)->window : \
+ gdk_window_get_parent ((widget)->window))
+
+static void
+adjust_allocation_recurse (GtkWidget *widget,
+ gpointer data)
+{
+ ScrollData *scroll_data = data;
+
+ if (!GTK_WIDGET_REALIZED (widget))
+ {
+ if (GTK_WIDGET_VISIBLE (widget))
+ {
+ GdkRectangle tmp_rectangle = widget->allocation;
+ tmp_rectangle.x += scroll_data->dx;
+
+ gtk_widget_size_allocate (widget, &tmp_rectangle);
+ }
+ }
+ else
+ {
+ if (ALLOCATION_WINDOW (widget) == scroll_data->window)
+ {
+ widget->allocation.x += scroll_data->dx;
+
+ if (GTK_IS_CONTAINER (widget))
+ gtk_container_forall (GTK_CONTAINER (widget),
+ adjust_allocation_recurse,
+ data);
+ }
+ }
+}
+
+static void
+adjust_allocation (GtkWidget *widget,
+ gint dx)
+{
+ ScrollData scroll_data;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ scroll_data.window = ALLOCATION_WINDOW (widget);
+ else
+ scroll_data.window = NULL;
+
+ scroll_data.dx = dx;
+
+ adjust_allocation_recurse (widget, &scroll_data);
+}
+
+static void
+hadjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ GtkCMCList *clist;
+ GtkContainer *container;
+ GdkRectangle area;
+ gint i;
+ gint y = 0;
+ gint value;
+ gint dx;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (GTK_IS_CMCLIST (data));
+
+ clist = GTK_CMCLIST (data);
+ container = GTK_CONTAINER (data);
+
+ if (adjustment != clist->hadjustment)
+ return;
+
+ value = adjustment->value;
+
+ dx = -value - clist->hoffset;
+
+ if (GTK_WIDGET_REALIZED (clist))
+ gdk_window_scroll (clist->title_window, dx, 0);
+
+ /* adjust the column button's allocations */
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].button)
+ adjust_allocation (clist->column[i].button, dx);
+
+ clist->hoffset = -value;
+
+ if (GTK_WIDGET_DRAWABLE (clist))
+ {
+ if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
+ !container->focus_child && GTK_CMCLIST_ADD_MODE(clist))
+ {
+ y = ROW_TOP_YPIXEL (clist, clist->focus_row);
+
+ gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
+ clist->clist_window_width - 1,
+ clist->row_height - 1);
+ }
+
+ gdk_window_scroll (clist->clist_window, dx, 0);
+ gdk_window_process_updates (clist->clist_window, FALSE);
+
+ if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
+ !container->focus_child)
+ {
+ if (GTK_CMCLIST_ADD_MODE(clist))
+ {
+ gint focus_row;
+
+ focus_row = clist->focus_row;
+ clist->focus_row = -1;
+ draw_rows (clist, &area);
+ clist->focus_row = focus_row;
+
+ gdk_draw_rectangle (clist->clist_window, clist->xor_gc,
+ FALSE, 0, y, clist->clist_window_width - 1,
+ clist->row_height - 1);
+ return;
+ }
+ else if (ABS(dx) < clist->clist_window_width - 1)
+ {
+ gint x0;
+ gint x1;
+
+ if (dx > 0)
+ {
+ x0 = clist->clist_window_width - 1;
+ x1 = dx;
+ }
+ else
+ {
+ x0 = 0;
+ x1 = clist->clist_window_width - 1 + dx;
+ }
+
+ y = ROW_TOP_YPIXEL (clist, clist->focus_row);
+ gdk_draw_line (clist->clist_window, clist->xor_gc,
+ x0, y + 1, x0, y + clist->row_height - 2);
+ gdk_draw_line (clist->clist_window, clist->xor_gc,
+ x1, y + 1, x1, y + clist->row_height - 2);
+ }
+ }
+ }
+}
+
+/* PRIVATE
+ * Memory Allocation/Distruction Routines for GtkCMCList stuctures
+ *
+ * functions:
+ * columns_new
+ * column_title_new
+ * columns_delete
+ * row_new
+ * row_delete
+ */
+static GtkCMCListColumn *
+columns_new (GtkCMCList *clist)
+{
+ GtkCMCListColumn *column;
+ gint i;
+
+ column = g_new (GtkCMCListColumn, clist->columns);
+
+ for (i = 0; i < clist->columns; i++)
+ {
+ column[i].area.x = 0;
+ column[i].area.y = 0;
+ column[i].area.width = 0;
+ column[i].area.height = 0;
+ column[i].title = NULL;
+ column[i].button = NULL;
+ column[i].window = NULL;
+ column[i].width = 0;
+ column[i].min_width = -1;
+ column[i].max_width = -1;
+ column[i].visible = TRUE;
+ column[i].width_set = FALSE;
+ column[i].resizeable = TRUE;
+ column[i].auto_resize = FALSE;
+ column[i].button_passive = FALSE;
+ column[i].justification = GTK_JUSTIFY_LEFT;
+ }
+
+ return column;
+}
+
+static void
+column_title_new (GtkCMCList *clist,
+ gint column,
+ const gchar *title)
+{
+ g_free (clist->column[column].title);
+
+ clist->column[column].title = g_strdup (title);
+}
+
+static void
+columns_delete (GtkCMCList *clist)
+{
+ gint i;
+
+ for (i = 0; i < clist->columns; i++)
+ g_free (clist->column[i].title);
+
+ g_free (clist->column);
+}
+
+static GtkCMCListRow *
+row_new (GtkCMCList *clist)
+{
+ int i;
+ GtkCMCListRow *clist_row;
+
+ clist_row = g_slice_new (GtkCMCListRow);
+ clist_row->cell = g_slice_alloc (sizeof (GtkCMCell) * clist->columns);
+
+ for (i = 0; i < clist->columns; i++)
+ {
+ clist_row->cell[i].type = GTK_CMCELL_EMPTY;
+ clist_row->cell[i].vertical = 0;
+ clist_row->cell[i].horizontal = 0;
+ clist_row->cell[i].style = NULL;
+ }
+
+ clist_row->fg_set = FALSE;
+ clist_row->bg_set = FALSE;
+ clist_row->style = NULL;
+ clist_row->selectable = TRUE;
+ clist_row->state = GTK_STATE_NORMAL;
+ clist_row->data = NULL;
+ clist_row->destroy = NULL;
+
+ return clist_row;
+}
+
+static void
+row_delete (GtkCMCList *clist,
+ GtkCMCListRow *clist_row)
+{
+ gint i;
+
+ for (i = 0; i < clist->columns; i++)
+ {
+ GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+ (clist, clist_row, i, GTK_CMCELL_EMPTY, NULL, 0, NULL, NULL);
+ if (clist_row->cell[i].style)
+ {
+ if (GTK_WIDGET_REALIZED (clist))
+ gtk_style_detach (clist_row->cell[i].style);
+ g_object_unref (clist_row->cell[i].style);
+ }
+ }
+
+ if (clist_row->style)
+ {
+ if (GTK_WIDGET_REALIZED (clist))
+ gtk_style_detach (clist_row->style);
+ g_object_unref (clist_row->style);
+ }
+
+ if (clist_row->destroy)
+ clist_row->destroy (clist_row->data);
+
+ g_slice_free1 (sizeof (GtkCMCell) * clist->columns, clist_row->cell);
+ g_slice_free (GtkCMCListRow, clist_row);
+}
+
+/* FOCUS FUNCTIONS
+ * gtk_cmclist_focus_content_area
+ * gtk_cmclist_focus
+ * gtk_cmclist_draw_focus
+ * gtk_cmclist_focus_in
+ * gtk_cmclist_focus_out
+ * title_focus
+ */
+static void
+gtk_cmclist_focus_content_area (GtkCMCList *clist)
+{
+ if (clist->focus_row < 0)
+ {
+ clist->focus_row = 0;
+
+ if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
+ clist->selection_mode == GTK_SELECTION_MULTIPLE) &&
+ !clist->selection)
+ g_signal_emit (GTK_OBJECT (clist),
+ clist_signals[SELECT_ROW], 0,
+ clist->focus_row, -1, NULL);
+ }
+ gtk_widget_grab_focus (GTK_WIDGET (clist));
+}
+
+static gboolean
+gtk_cmclist_focus (GtkWidget *widget,
+ GtkDirectionType direction)
+{
+ GtkCMCList *clist = GTK_CMCLIST (widget);
+ GtkWidget *focus_child;
+ gboolean is_current_focus;
+
+ if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ return FALSE;
+
+ focus_child = GTK_CONTAINER (widget)->focus_child;
+
+ is_current_focus = gtk_widget_is_focus (GTK_WIDGET (clist));
+
+ if (focus_child &&
+ gtk_widget_child_focus (focus_child, direction))
+ return TRUE;
+
+ switch (direction)
+ {
+ case GTK_DIR_LEFT:
+ case GTK_DIR_RIGHT:
+ if (focus_child)
+ {
+ if (title_focus_move (clist, direction))
+ return TRUE;
+ }
+ else if (!is_current_focus)
+ {
+ gtk_cmclist_focus_content_area (clist);
+ return TRUE;
+ }
+ break;
+ case GTK_DIR_DOWN:
+ case GTK_DIR_TAB_FORWARD:
+ if (!focus_child && !is_current_focus)
+ {
+ if (title_focus_in (clist, direction))
+ return TRUE;
+ }
+
+ if (!is_current_focus && clist->rows)
+ {
+ gtk_cmclist_focus_content_area (clist);
+ return TRUE;
+ }
+ break;
+ case GTK_DIR_UP:
+ case GTK_DIR_TAB_BACKWARD:
+ if (!focus_child && is_current_focus)
+ {
+ if (title_focus_in (clist, direction))
+ return TRUE;
+ }
+
+ if (!is_current_focus && !focus_child && clist->rows)
+ {
+ gtk_cmclist_focus_content_area (clist);
+ return TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_cmclist_set_focus_child (GtkContainer *container,
+ GtkWidget *child)
+{
+ GtkCMCList *clist = GTK_CMCLIST (container);
+ gint i;
+
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].button == child)
+ clist->focus_header_column = i;
+
+ parent_class->set_focus_child (container, child);
+}
+
+static void
+gtk_cmclist_draw_focus (GtkWidget *widget)
+{
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCLIST (widget));
+
+ if (!GTK_WIDGET_DRAWABLE (widget) || !GTK_WIDGET_CAN_FOCUS (widget))
+ return;
+
+ clist = GTK_CMCLIST (widget);
+ if (clist->focus_row >= 0)
+ gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
+ 0, ROW_TOP_YPIXEL(clist, clist->focus_row),
+ clist->clist_window_width - 1,
+ clist->row_height - 1);
+}
+
+static gint
+gtk_cmclist_focus_in (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ GtkCMCList *clist = GTK_CMCLIST (widget);
+
+ if (clist->selection_mode == GTK_SELECTION_BROWSE &&
+ clist->selection == NULL && clist->focus_row > -1)
+ {
+ GList *list;
+
+ list = g_list_nth (clist->row_list, clist->focus_row);
+ if (list && GTK_CMCLIST_ROW (list)->selectable)
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+ clist->focus_row, -1, event);
+ else
+ gtk_cmclist_draw_focus (widget);
+ }
+ else
+ gtk_cmclist_draw_focus (widget);
+
+ return FALSE;
+}
+
+static gint
+gtk_cmclist_focus_out (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ GtkCMCList *clist = GTK_CMCLIST (widget);
+
+ gtk_cmclist_draw_focus (widget);
+
+ GTK_CMCLIST_GET_CLASS (widget)->resync_selection (clist, (GdkEvent *) event);
+
+ return FALSE;
+}
+
+static gboolean
+focus_column (GtkCMCList *clist, gint column, gint dir)
+{
+ GtkWidget *child = clist->column[column].button;
+
+ if (gtk_widget_child_focus (child, dir))
+ {
+ return TRUE;
+ }
+ else if (GTK_WIDGET_CAN_FOCUS (child))
+ {
+ gtk_widget_grab_focus (child);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* Focus moved onto the headers. Focus first focusable and visible child.
+ * (FIXME: focus the last focused child if visible)
+ */
+static gboolean
+title_focus_in (GtkCMCList *clist, gint dir)
+{
+ gint i;
+ gint left, right;
+
+ if (!GTK_CMCLIST_SHOW_TITLES (clist))
+ return FALSE;
+
+ /* Check last focused column */
+ if (clist->focus_header_column != -1)
+ {
+ i = clist->focus_header_column;
+
+ left = COLUMN_LEFT_XPIXEL (clist, i);
+ right = left + clist->column[i].area.width;
+
+ if (left >= 0 && right <= clist->clist_window_width)
+ {
+ if (focus_column (clist, i, dir))
+ return TRUE;
+ }
+ }
+
+ /* Check fully visible columns */
+ for (i = 0 ; i < clist->columns ; i++)
+ {
+ left = COLUMN_LEFT_XPIXEL (clist, i);
+ right = left + clist->column[i].area.width;
+
+ if (left >= 0 && right <= clist->clist_window_width)
+ {
+ if (focus_column (clist, i, dir))
+ return TRUE;
+ }
+ }
+
+ /* Check partially visible columns */
+ for (i = 0 ; i < clist->columns ; i++)
+ {
+ left = COLUMN_LEFT_XPIXEL (clist, i);
+ right = left + clist->column[i].area.width;
+
+ if ((left < 0 && right > 0) ||
+ (left < clist->clist_window_width && right > clist->clist_window_width))
+ {
+ if (focus_column (clist, i, dir))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/* Move the focus right or left within the title buttons, scrolling
+ * as necessary to keep the focused child visible.
+ */
+static gboolean
+title_focus_move (GtkCMCList *clist,
+ gint dir)
+{
+ GtkWidget *focus_child;
+ gboolean return_val = FALSE;
+ gint d = 0;
+ gint i = -1;
+ gint j;
+
+ if (!GTK_CMCLIST_SHOW_TITLES(clist))
+ return FALSE;
+
+ focus_child = GTK_CONTAINER (clist)->focus_child;
+ g_assert (focus_child);
+
+ /* Movement direction within headers
+ */
+ switch (dir)
+ {
+ case GTK_DIR_RIGHT:
+ d = 1;
+ break;
+ case GTK_DIR_LEFT:
+ d = -1;
+ break;
+ }
+
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].button == focus_child)
+ break;
+
+ g_assert (i != -1); /* Have a starting column */
+
+ j = i + d;
+ while (!return_val && j >= 0 && j < clist->columns)
+ {
+ if (clist->column[j].button &&
+ GTK_WIDGET_VISIBLE (clist->column[j].button))
+ {
+ if (focus_column (clist, j, dir))
+ {
+ return_val = TRUE;
+ break;
+ }
+ }
+ j += d;
+ }
+
+ /* If we didn't find it, wrap around and keep looking
+ */
+ if (!return_val)
+ {
+ j = d > 0 ? 0 : clist->columns - 1;
+
+ while (!return_val && j != i)
+ {
+ if (clist->column[j].button &&
+ GTK_WIDGET_VISIBLE (clist->column[j].button))
+ {
+ if (focus_column (clist, j, dir))
+ {
+ return_val = TRUE;
+ break;
+ }
+ }
+ j += d;
+ }
+ }
+
+ /* Scroll horizontally so focused column is visible
+ */
+ if (return_val)
+ {
+ if (COLUMN_LEFT_XPIXEL (clist, j) < CELL_SPACING + COLUMN_INSET)
+ gtk_cmclist_moveto (clist, -1, j, 0, 0);
+ else if (COLUMN_LEFT_XPIXEL(clist, j) + clist->column[j].area.width >
+ clist->clist_window_width)
+ {
+ gint last_column;
+
+ for (last_column = clist->columns - 1;
+ last_column >= 0 && !clist->column[last_column].visible; last_column--);
+
+ if (j == last_column)
+ gtk_cmclist_moveto (clist, -1, j, 0, 0);
+ else
+ gtk_cmclist_moveto (clist, -1, j, 0, 1);
+ }
+ }
+ return TRUE; /* Even if we didn't find a new one, we can keep the
+ * focus in the same place.
+ */
+}
+
+/* PRIVATE SCROLLING FUNCTIONS
+ * move_focus_row
+ * scroll_horizontal
+ * scroll_vertical
+ * move_horizontal
+ * move_vertical
+ * horizontal_timeout
+ * vertical_timeout
+ * remove_grab
+ */
+static void
+move_focus_row (GtkCMCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position)
+{
+ GtkWidget *widget;
+
+ g_return_if_fail (clist != 0);
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ widget = GTK_WIDGET (clist);
+
+ switch (scroll_type)
+ {
+ case GTK_SCROLL_STEP_UP:
+ case GTK_SCROLL_STEP_BACKWARD:
+ if (clist->focus_row <= 0)
+ return;
+ gtk_cmclist_draw_focus (widget);
+ clist->focus_row--;
+ gtk_cmclist_draw_focus (widget);
+ break;
+
+ case GTK_SCROLL_STEP_DOWN:
+ case GTK_SCROLL_STEP_FORWARD:
+ if (clist->focus_row >= clist->rows - 1)
+ return;
+ gtk_cmclist_draw_focus (widget);
+ clist->focus_row++;
+ gtk_cmclist_draw_focus (widget);
+ break;
+ case GTK_SCROLL_PAGE_UP:
+ case GTK_SCROLL_PAGE_BACKWARD:
+ if (clist->focus_row <= 0)
+ return;
+ gtk_cmclist_draw_focus (widget);
+ clist->focus_row = MAX (0, clist->focus_row -
+ (2 * clist->clist_window_height -
+ clist->row_height - CELL_SPACING) /
+ (2 * (clist->row_height + CELL_SPACING)));
+ gtk_cmclist_draw_focus (widget);
+ break;
+ case GTK_SCROLL_PAGE_DOWN:
+ case GTK_SCROLL_PAGE_FORWARD:
+ if (clist->focus_row >= clist->rows - 1)
+ return;
+ gtk_cmclist_draw_focus (widget);
+ clist->focus_row = MIN (clist->rows - 1, clist->focus_row +
+ (2 * clist->clist_window_height -
+ clist->row_height - CELL_SPACING) /
+ (2 * (clist->row_height + CELL_SPACING)));
+ gtk_cmclist_draw_focus (widget);
+ break;
+ case GTK_SCROLL_JUMP:
+ if (position >= 0 && position <= 1)
+ {
+ gtk_cmclist_draw_focus (widget);
+ clist->focus_row = position * (clist->rows - 1);
+ gtk_cmclist_draw_focus (widget);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+scroll_horizontal (GtkCMCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position)
+{
+ gint column = 0;
+ gint last_column;
+
+ g_return_if_fail (clist != 0);
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist_has_grab (clist))
+ return;
+
+ for (last_column = clist->columns - 1;
+ last_column >= 0 && !clist->column[last_column].visible; last_column--)
+ ;
+
+ switch (scroll_type)
+ {
+ case GTK_SCROLL_STEP_BACKWARD:
+ column = COLUMN_FROM_XPIXEL (clist, 0);
+ if (COLUMN_LEFT_XPIXEL (clist, column) - CELL_SPACING - COLUMN_INSET >= 0
+ && column > 0)
+ column--;
+ break;
+ case GTK_SCROLL_STEP_FORWARD:
+ column = COLUMN_FROM_XPIXEL (clist, clist->clist_window_width);
+ if (column < 0)
+ return;
+ if (COLUMN_LEFT_XPIXEL (clist, column) +
+ clist->column[column].area.width +
+ CELL_SPACING + COLUMN_INSET - 1 <= clist->clist_window_width &&
+ column < last_column)
+ column++;
+ break;
+ case GTK_SCROLL_PAGE_BACKWARD:
+ case GTK_SCROLL_PAGE_FORWARD:
+ return;
+ case GTK_SCROLL_JUMP:
+ if (position >= 0 && position <= 1)
+ {
+ gint vis_columns = 0;
+ gint i;
+
+ for (i = 0; i <= last_column; i++)
+ if (clist->column[i].visible)
+ vis_columns++;
+
+ column = position * vis_columns;
+
+ for (i = 0; i <= last_column && column > 0; i++)
+ if (clist->column[i].visible)
+ column--;
+
+ column = i;
+ }
+ else
+ return;
+ break;
+ default:
+ break;
+ }
+
+ if (COLUMN_LEFT_XPIXEL (clist, column) < CELL_SPACING + COLUMN_INSET)
+ gtk_cmclist_moveto (clist, -1, column, 0, 0);
+ else if (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET - 1
+ + clist->column[column].area.width > clist->clist_window_width)
+ {
+ if (column == last_column)
+ gtk_cmclist_moveto (clist, -1, column, 0, 0);
+ else
+ gtk_cmclist_moveto (clist, -1, column, 0, 1);
+ }
+}
+
+static void
+scroll_vertical (GtkCMCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position)
+{
+ gint old_focus_row;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist_has_grab (clist))
+ return;
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_MULTIPLE:
+ if (clist->anchor >= 0)
+ return;
+ case GTK_SELECTION_BROWSE:
+
+ old_focus_row = clist->focus_row;
+ move_focus_row (clist, scroll_type, position);
+
+ if (old_focus_row != clist->focus_row)
+ {
+ if (clist->selection_mode == GTK_SELECTION_BROWSE)
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+ old_focus_row, -1, NULL);
+ else if (!GTK_CMCLIST_ADD_MODE(clist))
+ {
+ gtk_cmclist_unselect_all (clist);
+ clist->undo_anchor = old_focus_row;
+ }
+ }
+
+ switch (gtk_cmclist_row_is_visible (clist, clist->focus_row))
+ {
+ case GTK_VISIBILITY_NONE:
+ if (old_focus_row != clist->focus_row &&
+ !(clist->selection_mode == GTK_SELECTION_MULTIPLE &&
+ GTK_CMCLIST_ADD_MODE(clist)))
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+ clist->focus_row, -1, NULL);
+ switch (scroll_type)
+ {
+ case GTK_SCROLL_PAGE_UP:
+ case GTK_SCROLL_STEP_UP:
+ case GTK_SCROLL_STEP_BACKWARD:
+ case GTK_SCROLL_PAGE_BACKWARD:
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+ break;
+ case GTK_SCROLL_PAGE_DOWN:
+ case GTK_SCROLL_STEP_DOWN:
+ case GTK_SCROLL_STEP_FORWARD:
+ case GTK_SCROLL_PAGE_FORWARD:
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+ break;
+ case GTK_SCROLL_JUMP:
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 0.5, 0);
+ break;
+ default:
+ break;
+ }
+ break;
+ case GTK_VISIBILITY_PARTIAL:
+ switch (scroll_type)
+ {
+ case GTK_SCROLL_STEP_BACKWARD:
+ case GTK_SCROLL_PAGE_BACKWARD:
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+ break;
+ case GTK_SCROLL_STEP_FORWARD:
+ case GTK_SCROLL_PAGE_FORWARD:
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+ break;
+ case GTK_SCROLL_JUMP:
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 0.5, 0);
+ break;
+ default:
+ break;
+ }
+ default:
+ if (old_focus_row != clist->focus_row &&
+ !(clist->selection_mode == GTK_SELECTION_MULTIPLE &&
+ GTK_CMCLIST_ADD_MODE(clist)))
+ g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+ clist->focus_row, -1, NULL);
+ break;
+ }
+ break;
+ default:
+ move_focus_row (clist, scroll_type, position);
+
+ if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
+ clist->clist_window_height)
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+ else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+ break;
+ }
+}
+
+static void
+move_horizontal (GtkCMCList *clist,
+ gint diff)
+{
+ gdouble value;
+
+ if (!clist->hadjustment)
+ return;
+
+ value = CLAMP (clist->hadjustment->value + diff, 0.0,
+ clist->hadjustment->upper - clist->hadjustment->page_size);
+ gtk_adjustment_set_value (clist->hadjustment, value);
+}
+
+static void
+move_vertical (GtkCMCList *clist,
+ gint row,
+ gfloat align)
+{
+ gdouble value;
+
+ if (!clist->vadjustment)
+ return;
+
+ value = (ROW_TOP_YPIXEL (clist, row) - clist->voffset -
+ align * (clist->clist_window_height - clist->row_height) +
+ (2 * align - 1) * CELL_SPACING);
+
+ if (value + clist->vadjustment->page_size > clist->vadjustment->upper)
+ value = clist->vadjustment->upper - clist->vadjustment->page_size;
+
+ gtk_adjustment_set_value (clist->vadjustment, value);
+}
+
+static void
+do_fake_motion (GtkWidget *widget)
+{
+ GdkEvent *event = gdk_event_new (GDK_MOTION_NOTIFY);
+
+ event->motion.send_event = TRUE;
+
+ gtk_cmclist_motion (widget, (GdkEventMotion *)event);
+ gdk_event_free (event);
+}
+
+static gint
+horizontal_timeout (GtkCMCList *clist)
+{
+ clist->htimer = 0;
+ do_fake_motion (GTK_WIDGET (clist));
+
+ return FALSE;
+}
+
+static gint
+vertical_timeout (GtkCMCList *clist)
+{
+ clist->vtimer = 0;
+ do_fake_motion (GTK_WIDGET (clist));
+
+ return FALSE;
+}
+
+static void
+remove_grab (GtkCMCList *clist)
+{
+ GtkWidget *widget = GTK_WIDGET (clist);
+
+ if (GTK_WIDGET_HAS_GRAB (clist))
+ {
+ GdkDisplay *display = gtk_widget_get_display (widget);
+
+ gtk_grab_remove (widget);
+ if (gdk_display_pointer_is_grabbed (display))
+ gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+ }
+
+ if (clist->htimer)
+ {
+ g_source_remove (clist->htimer);
+ clist->htimer = 0;
+ }
+
+ if (clist->vtimer)
+ {
+ g_source_remove (clist->vtimer);
+ clist->vtimer = 0;
+ }
+}
+
+/* PUBLIC SORTING FUNCTIONS
+ * gtk_cmclist_sort
+ * gtk_cmclist_set_compare_func
+ * gtk_cmclist_set_auto_sort
+ * gtk_cmclist_set_sort_type
+ * gtk_cmclist_set_sort_column
+ */
+void
+gtk_cmclist_sort (GtkCMCList *clist)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ GTK_CMCLIST_GET_CLASS (clist)->sort_list (clist);
+}
+
+void
+gtk_cmclist_set_compare_func (GtkCMCList *clist,
+ GtkCMCListCompareFunc cmp_func)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ clist->compare = (cmp_func) ? cmp_func : default_compare;
+}
+
+void
+gtk_cmclist_set_auto_sort (GtkCMCList *clist,
+ gboolean auto_sort)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (GTK_CMCLIST_AUTO_SORT(clist) && !auto_sort)
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_AUTO_SORT);
+ else if (!GTK_CMCLIST_AUTO_SORT(clist) && auto_sort)
+ {
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_AUTO_SORT);
+ gtk_cmclist_sort (clist);
+ }
+}
+
+void
+gtk_cmclist_set_sort_type (GtkCMCList *clist,
+ GtkSortType sort_type)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ clist->sort_type = sort_type;
+}
+
+void
+gtk_cmclist_set_sort_column (GtkCMCList *clist,
+ gint column)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+
+ clist->sort_column = column;
+}
+
+/* PRIVATE SORTING FUNCTIONS
+ * default_compare
+ * real_sort_list
+ * gtk_cmclist_merge
+ * gtk_cmclist_mergesort
+ */
+static gint
+default_compare (GtkCMCList *clist,
+ gconstpointer ptr1,
+ gconstpointer ptr2)
+{
+ char *text1 = NULL;
+ char *text2 = NULL;
+
+ GtkCMCListRow *row1 = (GtkCMCListRow *) ptr1;
+ GtkCMCListRow *row2 = (GtkCMCListRow *) ptr2;
+
+ switch (row1->cell[clist->sort_column].type)
+ {
+ case GTK_CMCELL_TEXT:
+ text1 = GTK_CMCELL_TEXT (row1->cell[clist->sort_column])->text;
+ break;
+ case GTK_CMCELL_PIXTEXT:
+ text1 = GTK_CMCELL_PIXTEXT (row1->cell[clist->sort_column])->text;
+ break;
+ default:
+ break;
+ }
+
+ switch (row2->cell[clist->sort_column].type)
+ {
+ case GTK_CMCELL_TEXT:
+ text2 = GTK_CMCELL_TEXT (row2->cell[clist->sort_column])->text;
+ break;
+ case GTK_CMCELL_PIXTEXT:
+ text2 = GTK_CMCELL_PIXTEXT (row2->cell[clist->sort_column])->text;
+ break;
+ default:
+ break;
+ }
+
+ if (!text2)
+ return (text1 != NULL);
+
+ if (!text1)
+ return -1;
+
+ return strcmp (text1, text2);
+}
+
+static void
+real_sort_list (GtkCMCList *clist)
+{
+ GList *list;
+ GList *work;
+ gint i;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (clist->rows <= 1)
+ return;
+
+ if (clist_has_grab (clist))
+ return;
+
+ gtk_cmclist_freeze (clist);
+
+ if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_MULTIPLE)
+ {
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+ }
+
+ clist->row_list = gtk_cmclist_mergesort (clist, clist->row_list, clist->rows);
+
+ work = clist->selection;
+
+ for (i = 0, list = clist->row_list; i < clist->rows; i++, list = list->next)
+ {
+ if (GTK_CMCLIST_ROW (list)->state == GTK_STATE_SELECTED)
+ {
+ work->data = GINT_TO_POINTER (i);
+ work = work->next;
+ }
+
+ if (i == clist->rows - 1)
+ clist->row_list_end = list;
+ }
+
+ gtk_cmclist_thaw (clist);
+}
+
+static GList *
+gtk_cmclist_merge (GtkCMCList *clist,
+ GList *a, /* first list to merge */
+ GList *b) /* second list to merge */
+{
+ GList z = { 0 }; /* auxiliary node */
+ GList *c;
+ gint cmp;
+
+ c = &z;
+
+ while (a || b)
+ {
+ if (a && !b)
+ {
+ c->next = a;
+ a->prev = c;
+ c = a;
+ a = a->next;
+ break;
+ }
+ else if (!a && b)
+ {
+ c->next = b;
+ b->prev = c;
+ c = b;
+ b = b->next;
+ break;
+ }
+ else /* a && b */
+ {
+ cmp = clist->compare (clist, GTK_CMCLIST_ROW (a), GTK_CMCLIST_ROW (b));
+ if ((cmp >= 0 && clist->sort_type == GTK_SORT_DESCENDING) ||
+ (cmp <= 0 && clist->sort_type == GTK_SORT_ASCENDING) ||
+ (a && !b))
+ {
+ c->next = a;
+ a->prev = c;
+ c = a;
+ a = a->next;
+ }
+ else
+ {
+ c->next = b;
+ b->prev = c;
+ c = b;
+ b = b->next;
+ }
+ }
+ }
+
+ z.next->prev = NULL;
+ return z.next;
+}
+
+static GList *
+gtk_cmclist_mergesort (GtkCMCList *clist,
+ GList *list, /* the list to sort */
+ gint num) /* the list's length */
+{
+ GList *half;
+ gint i;
+
+ if (num <= 1)
+ {
+ return list;
+ }
+ else
+ {
+ /* move "half" to the middle */
+ half = list;
+ for (i = 0; i < num / 2; i++)
+ half = half->next;
+
+ /* cut the list in two */
+ half->prev->next = NULL;
+ half->prev = NULL;
+
+ /* recursively sort both lists */
+ return gtk_cmclist_merge (clist,
+ gtk_cmclist_mergesort (clist, list, num / 2),
+ gtk_cmclist_mergesort (clist, half, num - num / 2));
+ }
+}
+
+/************************/
+
+static void
+drag_source_info_destroy (gpointer data)
+{
+ GtkCMCListCellInfo *info = data;
+
+ g_free (info);
+}
+
+static void
+drag_dest_info_destroy (gpointer data)
+{
+ GtkCMCListDestInfo *info = data;
+
+ g_free (info);
+}
+
+static void
+drag_dest_cell (GtkCMCList *clist,
+ gint x,
+ gint y,
+ GtkCMCListDestInfo *dest_info)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (clist);
+
+ dest_info->insert_pos = GTK_CMCLIST_DRAG_NONE;
+
+ y -= (GTK_CONTAINER (clist)->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_CMCLIST_DRAW_DRAG_RECT(clist))
+ {
+ dest_info->insert_pos = GTK_CMCLIST_DRAG_INTO;
+ h = clist->row_height / 4;
+ }
+ else if (GTK_CMCLIST_DRAW_DRAG_LINE(clist))
+ {
+ dest_info->insert_pos = GTK_CMCLIST_DRAG_BEFORE;
+ h = clist->row_height / 2;
+ }
+
+ if (GTK_CMCLIST_DRAW_DRAG_LINE(clist))
+ {
+ if (y_delta < h)
+ dest_info->insert_pos = GTK_CMCLIST_DRAG_BEFORE;
+ else if (clist->row_height - y_delta < h)
+ dest_info->insert_pos = GTK_CMCLIST_DRAG_AFTER;
+ }
+ }
+}
+
+static void
+gtk_cmclist_drag_begin (GtkWidget *widget,
+ GdkDragContext *context)
+{
+ GtkCMCList *clist;
+ GtkCMCListCellInfo *info;
+
+ g_return_if_fail (GTK_IS_CMCLIST (widget));
+ g_return_if_fail (context != NULL);
+
+ clist = GTK_CMCLIST (widget);
+
+ clist->drag_button = 0;
+ remove_grab (clist);
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_MULTIPLE:
+ update_extended_selection (clist, clist->focus_row);
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+ break;
+ case GTK_SELECTION_SINGLE:
+ clist->anchor = -1;
+ case GTK_SELECTION_BROWSE:
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ info = g_dataset_get_data (context, "gtk-clist-drag-source");
+
+ if (!info)
+ {
+ info = g_new (GtkCMCListCellInfo, 1);
+
+ if (clist->click_cell.row < 0)
+ clist->click_cell.row = 0;
+ else if (clist->click_cell.row >= clist->rows)
+ clist->click_cell.row = clist->rows - 1;
+ info->row = clist->click_cell.row;
+ info->column = clist->click_cell.column;
+
+ g_dataset_set_data_full (context, "gtk-clist-drag-source", info,
+ drag_source_info_destroy);
+ }
+
+ if (GTK_CMCLIST_USE_DRAG_ICONS (clist))
+ gtk_drag_set_icon_default (context);
+}
+
+static void
+gtk_cmclist_drag_end (GtkWidget *widget,
+ GdkDragContext *context)
+{
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCLIST (widget));
+ g_return_if_fail (context != NULL);
+
+ clist = GTK_CMCLIST (widget);
+
+ clist->click_cell.row = -1;
+ clist->click_cell.column = -1;
+}
+
+static void
+gtk_cmclist_drag_leave (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time)
+{
+ GtkCMCList *clist;
+ GtkCMCListDestInfo *dest_info;
+
+ g_return_if_fail (GTK_IS_CMCLIST (widget));
+ g_return_if_fail (context != NULL);
+
+ clist = GTK_CMCLIST (widget);
+
+ dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+
+ if (dest_info)
+ {
+ if (dest_info->cell.row >= 0 &&
+ GTK_CMCLIST_REORDERABLE(clist) &&
+ gtk_drag_get_source_widget (context) == widget)
+ {
+ GList *list;
+ GdkAtom atom = gdk_atom_intern_static_string ("gtk-clist-drag-reorder");
+
+ list = context->targets;
+ while (list)
+ {
+ if (atom == GDK_POINTER_TO_ATOM (list->data))
+ {
+ GTK_CMCLIST_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 = -1;
+ break;
+ }
+ list = list->next;
+ }
+ }
+ g_dataset_remove_data (context, "gtk-clist-drag-dest");
+ }
+}
+
+static gint
+gtk_cmclist_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time)
+{
+ GtkCMCList *clist;
+ GtkCMCListDestInfo new_info;
+ GtkCMCListDestInfo *dest_info;
+
+ g_return_val_if_fail (GTK_IS_CMCLIST (widget), FALSE);
+
+ clist = GTK_CMCLIST (widget);
+
+ dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+
+ if (!dest_info)
+ {
+ dest_info = g_new (GtkCMCListDestInfo, 1);
+
+ dest_info->insert_pos = GTK_CMCLIST_DRAG_NONE;
+ dest_info->cell.row = -1;
+ dest_info->cell.column = -1;
+
+ 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_CMCLIST_REORDERABLE (clist))
+ {
+ GList *list;
+ GdkAtom atom = gdk_atom_intern_static_string ("gtk-clist-drag-reorder");
+
+ list = context->targets;
+ while (list)
+ {
+ if (atom == GDK_POINTER_TO_ATOM (list->data))
+ break;
+ list = list->next;
+ }
+
+ if (list)
+ {
+ if (gtk_drag_get_source_widget (context) != widget ||
+ new_info.insert_pos == GTK_CMCLIST_DRAG_NONE ||
+ new_info.cell.row == clist->click_cell.row ||
+ (new_info.cell.row == clist->click_cell.row - 1 &&
+ new_info.insert_pos == GTK_CMCLIST_DRAG_AFTER) ||
+ (new_info.cell.row == clist->click_cell.row + 1 &&
+ new_info.insert_pos == GTK_CMCLIST_DRAG_BEFORE))
+ {
+ 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_CMCLIST_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_CMCLIST_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 gboolean
+gtk_cmclist_drag_drop (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time)
+{
+ g_return_val_if_fail (GTK_IS_CMCLIST (widget), FALSE);
+ g_return_val_if_fail (context != NULL, FALSE);
+
+ if (GTK_CMCLIST_REORDERABLE (widget) &&
+ gtk_drag_get_source_widget (context) == widget)
+ {
+ GList *list;
+ GdkAtom atom = gdk_atom_intern_static_string ("gtk-clist-drag-reorder");
+
+ list = context->targets;
+ while (list)
+ {
+ if (atom == GDK_POINTER_TO_ATOM (list->data))
+ return TRUE;
+ list = list->next;
+ }
+ }
+ return FALSE;
+}
+
+static void
+gtk_cmclist_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time)
+{
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCLIST (widget));
+ g_return_if_fail (context != NULL);
+ g_return_if_fail (selection_data != NULL);
+
+ clist = GTK_CMCLIST (widget);
+
+ if (GTK_CMCLIST_REORDERABLE (clist) &&
+ gtk_drag_get_source_widget (context) == widget &&
+ selection_data->target ==
+ gdk_atom_intern_static_string ("gtk-clist-drag-reorder") &&
+ selection_data->format == 8 &&
+ selection_data->length == sizeof (GtkCMCListCellInfo))
+ {
+ GtkCMCListCellInfo *source_info;
+
+ source_info = (GtkCMCListCellInfo *)(selection_data->data);
+ if (source_info)
+ {
+ GtkCMCListDestInfo dest_info;
+
+ drag_dest_cell (clist, x, y, &dest_info);
+
+ if (dest_info.insert_pos == GTK_CMCLIST_DRAG_AFTER)
+ dest_info.cell.row++;
+ if (source_info->row < dest_info.cell.row)
+ dest_info.cell.row--;
+ if (dest_info.cell.row != source_info->row)
+ gtk_cmclist_row_move (clist, source_info->row, dest_info.cell.row);
+
+ g_dataset_remove_data (context, "gtk-clist-drag-dest");
+ }
+ }
+}
+
+static void
+gtk_cmclist_drag_data_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (widget));
+ g_return_if_fail (context != NULL);
+ g_return_if_fail (selection_data != NULL);
+
+ if (selection_data->target == gdk_atom_intern_static_string ("gtk-clist-drag-reorder"))
+ {
+ GtkCMCListCellInfo *info;
+
+ info = g_dataset_get_data (context, "gtk-clist-drag-source");
+
+ if (info)
+ {
+ GtkCMCListCellInfo ret_info;
+
+ ret_info.row = info->row;
+ ret_info.column = info->column;
+
+ gtk_selection_data_set (selection_data, selection_data->target,
+ 8, (guchar *) &ret_info,
+ sizeof (GtkCMCListCellInfo));
+ }
+ }
+}
+
+static void
+draw_drag_highlight (GtkCMCList *clist,
+ GtkCMCListRow *dest_row,
+ gint dest_row_number,
+ GtkCMCListDragPos drag_pos)
+{
+ gint y;
+
+ y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
+
+ switch (drag_pos)
+ {
+ case GTK_CMCLIST_DRAG_NONE:
+ break;
+ case GTK_CMCLIST_DRAG_AFTER:
+ y += clist->row_height + 1;
+ case GTK_CMCLIST_DRAG_BEFORE:
+ gdk_draw_line (clist->clist_window, clist->xor_gc,
+ 0, y, clist->clist_window_width, y);
+ break;
+ case GTK_CMCLIST_DRAG_INTO:
+ gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
+ clist->clist_window_width - 1, clist->row_height);
+ break;
+ }
+}
+
+void
+gtk_cmclist_set_reorderable (GtkCMCList *clist,
+ gboolean reorderable)
+{
+ GtkWidget *widget;
+
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if ((GTK_CMCLIST_REORDERABLE(clist) != 0) == reorderable)
+ return;
+
+ widget = GTK_WIDGET (clist);
+
+ if (reorderable)
+ {
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_REORDERABLE);
+ gtk_drag_dest_set (widget,
+ GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+ &clist_target_table, 1, GDK_ACTION_MOVE);
+ }
+ else
+ {
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_REORDERABLE);
+ gtk_drag_dest_unset (GTK_WIDGET (clist));
+ }
+}
+
+void
+gtk_cmclist_set_use_drag_icons (GtkCMCList *clist,
+ gboolean use_icons)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (use_icons != 0)
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_USE_DRAG_ICONS);
+ else
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_USE_DRAG_ICONS);
+}
+
+void
+gtk_cmclist_set_button_actions (GtkCMCList *clist,
+ guint button,
+ guint8 button_actions)
+{
+ g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+ if (button < MAX_BUTTON)
+ {
+ if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))) ||
+ GTK_WIDGET_HAS_GRAB (clist))
+ {
+ remove_grab (clist);
+ clist->drag_button = 0;
+ }
+
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+ clist->button_actions[button] = button_actions;
+ }
+}
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, Josh MacDonald
+ * Copyright (C) 1997-1998 Jay Painter <jpaint@serv.net><jpaint@gimp.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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/.
+ */
+
+#ifndef __GTK_CMCLIST_H__
+#define __GTK_CMCLIST_H__
+
+#include <gdk/gdk.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtkalignment.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkhscrollbar.h>
+#include <gtk/gtkvscrollbar.h>
+#include <gtk/gtkenums.h>
+
+
+G_BEGIN_DECLS
+
+
+/* clist flags */
+enum {
+ GTK_CMCLIST_IN_DRAG = 1 << 0,
+ GTK_CMCLIST_ROW_HEIGHT_SET = 1 << 1,
+ GTK_CMCLIST_SHOW_TITLES = 1 << 2,
+ /* Unused */
+ GTK_CMCLIST_ADD_MODE = 1 << 4,
+ GTK_CMCLIST_AUTO_SORT = 1 << 5,
+ GTK_CMCLIST_AUTO_RESIZE_BLOCKED = 1 << 6,
+ GTK_CMCLIST_REORDERABLE = 1 << 7,
+ GTK_CMCLIST_USE_DRAG_ICONS = 1 << 8,
+ GTK_CMCLIST_DRAW_DRAG_LINE = 1 << 9,
+ GTK_CMCLIST_DRAW_DRAG_RECT = 1 << 10
+};
+
+/* cell types */
+typedef enum
+{
+ GTK_CMCELL_EMPTY,
+ GTK_CMCELL_TEXT,
+ GTK_CMCELL_PIXMAP,
+ GTK_CMCELL_PIXTEXT,
+ GTK_CMCELL_WIDGET
+} GtkCMCellType;
+
+typedef enum
+{
+ GTK_CMCLIST_DRAG_NONE,
+ GTK_CMCLIST_DRAG_BEFORE,
+ GTK_CMCLIST_DRAG_INTO,
+ GTK_CMCLIST_DRAG_AFTER
+} GtkCMCListDragPos;
+
+typedef enum
+{
+ GTK_CMBUTTON_IGNORED = 0,
+ GTK_CMBUTTON_SELECTS = 1 << 0,
+ GTK_CMBUTTON_DRAGS = 1 << 1,
+ GTK_CMBUTTON_EXPANDS = 1 << 2
+} GtkCMButtonAction;
+
+#define GTK_TYPE_CMCLIST (gtk_cmclist_get_type ())
+#define GTK_CMCLIST(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_CMCLIST, GtkCMCList))
+#define GTK_CMCLIST_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CMCLIST, GtkCMCListClass))
+#define GTK_IS_CMCLIST(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_CMCLIST))
+#define GTK_IS_CMCLIST_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CMCLIST))
+#define GTK_CMCLIST_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_CMCLIST, GtkCMCListClass))
+
+
+#define GTK_CMCLIST_FLAGS(clist) (GTK_CMCLIST (clist)->flags)
+#define GTK_CMCLIST_SET_FLAG(clist,flag) (GTK_CMCLIST_FLAGS (clist) |= (GTK_ ## flag))
+#define GTK_CMCLIST_UNSET_FLAG(clist,flag) (GTK_CMCLIST_FLAGS (clist) &= ~(GTK_ ## flag))
+
+#define GTK_CMCLIST_IN_DRAG(clist) (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_IN_DRAG)
+#define GTK_CMCLIST_ROW_HEIGHT_SET(clist) (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_ROW_HEIGHT_SET)
+#define GTK_CMCLIST_SHOW_TITLES(clist) (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_SHOW_TITLES)
+#define GTK_CMCLIST_ADD_MODE(clist) (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_ADD_MODE)
+#define GTK_CMCLIST_AUTO_SORT(clist) (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_AUTO_SORT)
+#define GTK_CMCLIST_AUTO_RESIZE_BLOCKED(clist) (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_AUTO_RESIZE_BLOCKED)
+#define GTK_CMCLIST_REORDERABLE(clist) (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_REORDERABLE)
+#define GTK_CMCLIST_USE_DRAG_ICONS(clist) (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_USE_DRAG_ICONS)
+#define GTK_CMCLIST_DRAW_DRAG_LINE(clist) (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_DRAW_DRAG_LINE)
+#define GTK_CMCLIST_DRAW_DRAG_RECT(clist) (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_DRAW_DRAG_RECT)
+
+#define GTK_CMCLIST_ROW(_glist_) ((GtkCMCListRow *)((_glist_)->data))
+
+/* pointer casting for cells */
+#define GTK_CMCELL_TEXT(cell) (((GtkCMCellText *) &(cell)))
+#define GTK_CMCELL_PIXMAP(cell) (((GtkCMCellPixmap *) &(cell)))
+#define GTK_CMCELL_PIXTEXT(cell) (((GtkCMCellPixText *) &(cell)))
+#define GTK_CMCELL_WIDGET(cell) (((GtkCMCellWidget *) &(cell)))
+
+typedef struct _GtkCMCList GtkCMCList;
+typedef struct _GtkCMCListClass GtkCMCListClass;
+typedef struct _GtkCMCListColumn GtkCMCListColumn;
+typedef struct _GtkCMCListRow GtkCMCListRow;
+
+typedef struct _GtkCMCell GtkCMCell;
+typedef struct _GtkCMCellText GtkCMCellText;
+typedef struct _GtkCMCellPixmap GtkCMCellPixmap;
+typedef struct _GtkCMCellPixText GtkCMCellPixText;
+typedef struct _GtkCMCellWidget GtkCMCellWidget;
+
+typedef gint (*GtkCMCListCompareFunc) (GtkCMCList *clist,
+ gconstpointer ptr1,
+ gconstpointer ptr2);
+
+typedef struct _GtkCMCListCellInfo GtkCMCListCellInfo;
+typedef struct _GtkCMCListDestInfo GtkCMCListDestInfo;
+
+struct _GtkCMCListCellInfo
+{
+ gint row;
+ gint column;
+};
+
+struct _GtkCMCListDestInfo
+{
+ GtkCMCListCellInfo cell;
+ GtkCMCListDragPos insert_pos;
+};
+
+struct _GtkCMCList
+{
+ GtkContainer container;
+
+ guint16 flags;
+
+ gpointer reserved1;
+ gpointer reserved2;
+
+ guint freeze_count;
+
+ /* allocation rectangle after the conatiner_border_width
+ * and the width of the shadow border */
+ GdkRectangle internal_allocation;
+
+ /* rows */
+ gint rows;
+ gint row_height;
+ GList *row_list;
+ GList *row_list_end;
+
+ /* columns */
+ gint columns;
+ GdkRectangle column_title_area;
+ GdkWindow *title_window;
+
+ /* dynamicly allocated array of column structures */
+ GtkCMCListColumn *column;
+
+ /* the scrolling window and its height and width to
+ * make things a little speedier */
+ GdkWindow *clist_window;
+ gint clist_window_width;
+ gint clist_window_height;
+
+ /* offsets for scrolling */
+ gint hoffset;
+ gint voffset;
+
+ /* border shadow style */
+ GtkShadowType shadow_type;
+
+ /* the list's selection mode (gtkenums.h) */
+ GtkSelectionMode selection_mode;
+
+ /* list of selected rows */
+ GList *selection;
+ GList *selection_end;
+
+ GList *undo_selection;
+ GList *undo_unselection;
+ gint undo_anchor;
+
+ /* mouse buttons */
+ guint8 button_actions[5];
+
+ guint8 drag_button;
+
+ /* dnd */
+ GtkCMCListCellInfo click_cell;
+
+ /* scroll adjustments */
+ GtkAdjustment *hadjustment;
+ GtkAdjustment *vadjustment;
+
+ /* xor GC for the vertical drag line */
+ GdkGC *xor_gc;
+
+ /* gc for drawing unselected cells */
+ GdkGC *fg_gc;
+ GdkGC *bg_gc;
+
+ /* cursor used to indicate dragging */
+ GdkCursor *cursor_drag;
+
+ /* the current x-pixel location of the xor-drag line */
+ gint x_drag;
+
+ /* focus handling */
+ gint focus_row;
+
+ gint focus_header_column;
+
+ /* dragging the selection */
+ gint anchor;
+ GtkStateType anchor_state;
+ gint drag_pos;
+ gint htimer;
+ gint vtimer;
+
+ GtkSortType sort_type;
+ GtkCMCListCompareFunc compare;
+ gint sort_column;
+
+ gint drag_highlight_row;
+ GtkCMCListDragPos drag_highlight_pos;
+};
+
+struct _GtkCMCListClass
+{
+ GtkContainerClass parent_class;
+
+ void (*set_scroll_adjustments) (GtkCMCList *clist,
+ GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment);
+ void (*refresh) (GtkCMCList *clist);
+ void (*select_row) (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event);
+ void (*unselect_row) (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event);
+ void (*row_move) (GtkCMCList *clist,
+ gint source_row,
+ gint dest_row);
+ void (*click_column) (GtkCMCList *clist,
+ gint column);
+ void (*resize_column) (GtkCMCList *clist,
+ gint column,
+ gint width);
+ void (*toggle_focus_row) (GtkCMCList *clist);
+ void (*select_all) (GtkCMCList *clist);
+ void (*unselect_all) (GtkCMCList *clist);
+ void (*undo_selection) (GtkCMCList *clist);
+ void (*start_selection) (GtkCMCList *clist);
+ void (*end_selection) (GtkCMCList *clist);
+ void (*extend_selection) (GtkCMCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position,
+ gboolean auto_start_selection);
+ void (*scroll_horizontal) (GtkCMCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position);
+ void (*scroll_vertical) (GtkCMCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position);
+ void (*toggle_add_mode) (GtkCMCList *clist);
+ void (*abort_column_resize) (GtkCMCList *clist);
+ void (*resync_selection) (GtkCMCList *clist,
+ GdkEvent *event);
+ GList* (*selection_find) (GtkCMCList *clist,
+ gint row_number,
+ GList *row_list_element);
+ void (*draw_row) (GtkCMCList *clist,
+ GdkRectangle *area,
+ gint row,
+ GtkCMCListRow *clist_row);
+ void (*draw_drag_highlight) (GtkCMCList *clist,
+ GtkCMCListRow *target_row,
+ gint target_row_number,
+ GtkCMCListDragPos drag_pos);
+ void (*clear) (GtkCMCList *clist);
+ void (*fake_unselect_all) (GtkCMCList *clist,
+ gint row);
+ void (*sort_list) (GtkCMCList *clist);
+ gint (*insert_row) (GtkCMCList *clist,
+ gint row,
+ gchar *text[]);
+ void (*remove_row) (GtkCMCList *clist,
+ gint row);
+ void (*set_cell_contents) (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ GtkCMCellType type,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask);
+ void (*cell_size_request) (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ GtkRequisition *requisition);
+
+};
+
+struct _GtkCMCListColumn
+{
+ gchar *title;
+ GdkRectangle area;
+
+ GtkWidget *button;
+ GdkWindow *window;
+
+ gint width;
+ gint min_width;
+ gint max_width;
+ GtkJustification justification;
+
+ guint visible : 1;
+ guint width_set : 1;
+ guint resizeable : 1;
+ guint auto_resize : 1;
+ guint button_passive : 1;
+};
+
+struct _GtkCMCListRow
+{
+ GtkCMCell *cell;
+ GtkStateType state;
+
+ GdkColor foreground;
+ GdkColor background;
+
+ GtkStyle *style;
+
+ gpointer data;
+ GtkDestroyNotify destroy;
+
+ guint fg_set : 1;
+ guint bg_set : 1;
+ guint selectable : 1;
+};
+
+/* Cell Structures */
+struct _GtkCMCellText
+{
+ GtkCMCellType type;
+
+ gint16 vertical;
+ gint16 horizontal;
+
+ GtkStyle *style;
+
+ gchar *text;
+};
+
+struct _GtkCMCellPixmap
+{
+ GtkCMCellType type;
+
+ gint16 vertical;
+ gint16 horizontal;
+
+ GtkStyle *style;
+
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+};
+
+struct _GtkCMCellPixText
+{
+ GtkCMCellType type;
+
+ gint16 vertical;
+ gint16 horizontal;
+
+ GtkStyle *style;
+
+ gchar *text;
+ guint8 spacing;
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+};
+
+struct _GtkCMCellWidget
+{
+ GtkCMCellType type;
+
+ gint16 vertical;
+ gint16 horizontal;
+
+ GtkStyle *style;
+
+ GtkWidget *widget;
+};
+
+struct _GtkCMCell
+{
+ GtkCMCellType type;
+
+ gint16 vertical;
+ gint16 horizontal;
+
+ GtkStyle *style;
+
+ union {
+ gchar *text;
+
+ struct {
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+ } pm;
+
+ struct {
+ gchar *text;
+ guint8 spacing;
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+ } pt;
+
+ GtkWidget *widget;
+ } u;
+};
+
+GType gtk_cmclist_get_type (void);
+
+/* create a new GtkCMCList */
+GtkWidget* gtk_cmclist_new (gint columns);
+GtkWidget* gtk_cmclist_new_with_titles (gint columns,
+ gchar *titles[]);
+
+/* set adjustments of clist */
+void gtk_cmclist_set_hadjustment (GtkCMCList *clist,
+ GtkAdjustment *adjustment);
+void gtk_cmclist_set_vadjustment (GtkCMCList *clist,
+ GtkAdjustment *adjustment);
+
+/* get adjustments of clist */
+GtkAdjustment* gtk_cmclist_get_hadjustment (GtkCMCList *clist);
+GtkAdjustment* gtk_cmclist_get_vadjustment (GtkCMCList *clist);
+
+/* set the border style of the clist */
+void gtk_cmclist_set_shadow_type (GtkCMCList *clist,
+ GtkShadowType type);
+
+/* set the clist's selection mode */
+void gtk_cmclist_set_selection_mode (GtkCMCList *clist,
+ GtkSelectionMode mode);
+
+/* enable clists reorder ability */
+void gtk_cmclist_set_reorderable (GtkCMCList *clist,
+ gboolean reorderable);
+void gtk_cmclist_set_use_drag_icons (GtkCMCList *clist,
+ gboolean use_icons);
+void gtk_cmclist_set_button_actions (GtkCMCList *clist,
+ guint button,
+ guint8 button_actions);
+
+/* freeze all visual updates of the list, and then thaw the list after
+ * you have made a number of changes and the updates wil occure in a
+ * more efficent mannor than if you made them on a unfrozen list
+ */
+void gtk_cmclist_freeze (GtkCMCList *clist);
+void gtk_cmclist_thaw (GtkCMCList *clist);
+
+/* show and hide the column title buttons */
+void gtk_cmclist_column_titles_show (GtkCMCList *clist);
+void gtk_cmclist_column_titles_hide (GtkCMCList *clist);
+
+/* set the column title to be a active title (responds to button presses,
+ * prelights, and grabs keyboard focus), or passive where it acts as just
+ * a title
+ */
+void gtk_cmclist_column_title_active (GtkCMCList *clist,
+ gint column);
+void gtk_cmclist_column_title_passive (GtkCMCList *clist,
+ gint column);
+void gtk_cmclist_column_titles_active (GtkCMCList *clist);
+void gtk_cmclist_column_titles_passive (GtkCMCList *clist);
+
+/* set the title in the column title button */
+void gtk_cmclist_set_column_title (GtkCMCList *clist,
+ gint column,
+ const gchar *title);
+
+/* returns the title of column. Returns NULL if title is not set */
+gchar * gtk_cmclist_get_column_title (GtkCMCList *clist,
+ gint column);
+
+/* set a widget instead of a title for the column title button */
+void gtk_cmclist_set_column_widget (GtkCMCList *clist,
+ gint column,
+ GtkWidget *widget);
+
+/* returns the column widget */
+GtkWidget * gtk_cmclist_get_column_widget (GtkCMCList *clist,
+ gint column);
+
+/* set the justification on a column */
+void gtk_cmclist_set_column_justification (GtkCMCList *clist,
+ gint column,
+ GtkJustification justification);
+
+/* set visibility of a column */
+void gtk_cmclist_set_column_visibility (GtkCMCList *clist,
+ gint column,
+ gboolean visible);
+
+/* enable/disable column resize operations by mouse */
+void gtk_cmclist_set_column_resizeable (GtkCMCList *clist,
+ gint column,
+ gboolean resizeable);
+
+/* resize column automatically to its optimal width */
+void gtk_cmclist_set_column_auto_resize (GtkCMCList *clist,
+ gint column,
+ gboolean auto_resize);
+
+gint gtk_cmclist_columns_autosize (GtkCMCList *clist);
+
+/* return the optimal column width, i.e. maximum of all cell widths */
+gint gtk_cmclist_optimal_column_width (GtkCMCList *clist,
+ gint column);
+
+/* set the pixel width of a column; this is a necessary step in
+ * creating a CList because otherwise the column width is chozen from
+ * the width of the column title, which will never be right
+ */
+void gtk_cmclist_set_column_width (GtkCMCList *clist,
+ gint column,
+ gint width);
+
+/* set column minimum/maximum width. min/max_width < 0 => no restriction */
+void gtk_cmclist_set_column_min_width (GtkCMCList *clist,
+ gint column,
+ gint min_width);
+void gtk_cmclist_set_column_max_width (GtkCMCList *clist,
+ gint column,
+ gint max_width);
+
+/* change the height of the rows, the default (height=0) is
+ * the hight of the current font.
+ */
+void gtk_cmclist_set_row_height (GtkCMCList *clist,
+ guint height);
+
+/* scroll the viewing area of the list to the given column and row;
+ * row_align and col_align are between 0-1 representing the location the
+ * row should appear on the screnn, 0.0 being top or left, 1.0 being
+ * bottom or right; if row or column is -1 then then there is no change
+ */
+void gtk_cmclist_moveto (GtkCMCList *clist,
+ gint row,
+ gint column,
+ gfloat row_align,
+ gfloat col_align);
+
+/* returns whether the row is visible */
+GtkVisibility gtk_cmclist_row_is_visible (GtkCMCList *clist,
+ gint row);
+
+/* returns the cell type */
+GtkCMCellType gtk_cmclist_get_cell_type (GtkCMCList *clist,
+ gint row,
+ gint column);
+
+/* sets a given cell's text, replacing its current contents */
+void gtk_cmclist_set_text (GtkCMCList *clist,
+ gint row,
+ gint column,
+ const gchar *text);
+
+/* for the "get" functions, any of the return pointer can be
+ * NULL if you are not interested
+ */
+gint gtk_cmclist_get_text (GtkCMCList *clist,
+ gint row,
+ gint column,
+ gchar **text);
+
+/* sets a given cell's pixmap, replacing its current contents */
+void gtk_cmclist_set_pixmap (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask);
+
+gint gtk_cmclist_get_pixmap (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkPixmap **pixmap,
+ GdkBitmap **mask);
+
+/* sets a given cell's pixmap and text, replacing its current contents */
+void gtk_cmclist_set_pixtext (GtkCMCList *clist,
+ gint row,
+ gint column,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask);
+
+gint gtk_cmclist_get_pixtext (GtkCMCList *clist,
+ gint row,
+ gint column,
+ gchar **text,
+ guint8 *spacing,
+ GdkPixmap **pixmap,
+ GdkBitmap **mask);
+
+/* sets the foreground color of a row, the color must already
+ * be allocated
+ */
+void gtk_cmclist_set_foreground (GtkCMCList *clist,
+ gint row,
+ const GdkColor *color);
+
+/* sets the background color of a row, the color must already
+ * be allocated
+ */
+void gtk_cmclist_set_background (GtkCMCList *clist,
+ gint row,
+ const GdkColor *color);
+
+/* set / get cell styles */
+void gtk_cmclist_set_cell_style (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GtkStyle *style);
+
+GtkStyle *gtk_cmclist_get_cell_style (GtkCMCList *clist,
+ gint row,
+ gint column);
+
+void gtk_cmclist_set_row_style (GtkCMCList *clist,
+ gint row,
+ GtkStyle *style);
+
+GtkStyle *gtk_cmclist_get_row_style (GtkCMCList *clist,
+ gint row);
+
+/* this sets a horizontal and vertical shift for drawing
+ * the contents of a cell; it can be positive or negitive;
+ * this is particulary useful for indenting items in a column
+ */
+void gtk_cmclist_set_shift (GtkCMCList *clist,
+ gint row,
+ gint column,
+ gint vertical,
+ gint horizontal);
+
+/* set/get selectable flag of a single row */
+void gtk_cmclist_set_selectable (GtkCMCList *clist,
+ gint row,
+ gboolean selectable);
+gboolean gtk_cmclist_get_selectable (GtkCMCList *clist,
+ gint row);
+
+/* prepend/append returns the index of the row you just added,
+ * making it easier to append and modify a row
+ */
+gint gtk_cmclist_prepend (GtkCMCList *clist,
+ gchar *text[]);
+gint gtk_cmclist_append (GtkCMCList *clist,
+ gchar *text[]);
+
+/* inserts a row at index row and returns the row where it was
+ * actually inserted (may be different from "row" in auto_sort mode)
+ */
+gint gtk_cmclist_insert (GtkCMCList *clist,
+ gint row,
+ gchar *text[]);
+
+/* removes row at index row */
+void gtk_cmclist_remove (GtkCMCList *clist,
+ gint row);
+
+/* sets a arbitrary data pointer for a given row */
+void gtk_cmclist_set_row_data (GtkCMCList *clist,
+ gint row,
+ gpointer data);
+
+/* sets a data pointer for a given row with destroy notification */
+void gtk_cmclist_set_row_data_full (GtkCMCList *clist,
+ gint row,
+ gpointer data,
+ GtkDestroyNotify destroy);
+
+/* returns the data set for a row */
+gpointer gtk_cmclist_get_row_data (GtkCMCList *clist,
+ gint row);
+
+/* givin a data pointer, find the first (and hopefully only!)
+ * row that points to that data, or -1 if none do
+ */
+gint gtk_cmclist_find_row_from_data (GtkCMCList *clist,
+ gpointer data);
+
+/* force selection of a row */
+void gtk_cmclist_select_row (GtkCMCList *clist,
+ gint row,
+ gint column);
+
+/* force unselection of a row */
+void gtk_cmclist_unselect_row (GtkCMCList *clist,
+ gint row,
+ gint column);
+
+/* undo the last select/unselect operation */
+void gtk_cmclist_undo_selection (GtkCMCList *clist);
+
+/* clear the entire list -- this is much faster than removing
+ * each item with gtk_cmclist_remove
+ */
+void gtk_cmclist_clear (GtkCMCList *clist);
+
+/* return the row column corresponding to the x and y coordinates,
+ * the returned values are only valid if the x and y coordinates
+ * are respectively to a window == clist->clist_window
+ */
+gint gtk_cmclist_get_selection_info (GtkCMCList *clist,
+ gint x,
+ gint y,
+ gint *row,
+ gint *column);
+
+/* in multiple or extended mode, select all rows */
+void gtk_cmclist_select_all (GtkCMCList *clist);
+
+/* in all modes except browse mode, deselect all rows */
+void gtk_cmclist_unselect_all (GtkCMCList *clist);
+
+/* swap the position of two rows */
+void gtk_cmclist_swap_rows (GtkCMCList *clist,
+ gint row1,
+ gint row2);
+
+/* move row from source_row position to dest_row position */
+void gtk_cmclist_row_move (GtkCMCList *clist,
+ gint source_row,
+ gint dest_row);
+
+/* sets a compare function different to the default */
+void gtk_cmclist_set_compare_func (GtkCMCList *clist,
+ GtkCMCListCompareFunc cmp_func);
+
+/* the column to sort by */
+void gtk_cmclist_set_sort_column (GtkCMCList *clist,
+ gint column);
+
+/* how to sort : ascending or descending */
+void gtk_cmclist_set_sort_type (GtkCMCList *clist,
+ GtkSortType sort_type);
+
+/* sort the list with the current compare function */
+void gtk_cmclist_sort (GtkCMCList *clist);
+
+/* Automatically sort upon insertion */
+void gtk_cmclist_set_auto_sort (GtkCMCList *clist,
+ gboolean auto_sort);
+
+/* Private function for clist, ctree */
+
+PangoLayout *_gtk_cmclist_create_cell_layout (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column);
+
+
+G_END_DECLS
+
+
+#endif /* __GTK_CMCLIST_H__ */
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, Josh MacDonald,
+ * Copyright (C) 1997-1998 Jay Painter <jpaint@serv.net><jpaint@gimp.org>
+ *
+ * GtkCMCTree widget for GTK+
+ * 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 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
+ * Lesser General Public License for more details.
+ *
+ * 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 <config.h>
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include "gtkcmctree.h"
+#include "claws-marshal.h"
+
+#define PM_SIZE 8
+#define TAB_SIZE (PM_SIZE + 6)
+#define CELL_SPACING 1
+#define CLIST_OPTIMUM_SIZE 64
+#define COLUMN_INSET 3
+#define DRAG_WIDTH 6
+
+#define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
+ (((row) + 1) * CELL_SPACING) + \
+ (clist)->voffset)
+#define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
+ ((clist)->row_height + CELL_SPACING))
+#define COLUMN_LEFT_XPIXEL(clist, col) ((clist)->column[(col)].area.x \
+ + (clist)->hoffset)
+#define COLUMN_LEFT(clist, column) ((clist)->column[(column)].area.x)
+
+GType
+gtk_cmctree_pos_get_type (void)
+{
+ static GType etype = 0;
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ { GTK_CMCTREE_POS_BEFORE, "GTK_CMCTREE_POS_BEFORE", "before" },
+ { GTK_CMCTREE_POS_AS_CHILD, "GTK_CMCTREE_POS_AS_CHILD", "as-child" },
+ { GTK_CMCTREE_POS_AFTER, "GTK_CMCTREE_POS_AFTER", "after" },
+ { 0, NULL, NULL }
+ };
+ etype = g_enum_register_static (g_intern_static_string ("GtkCMCTreePos"), values);
+ }
+ return etype;
+}
+GType
+gtk_cmctree_line_style_get_type (void)
+{
+ static GType etype = 0;
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ { GTK_CMCTREE_LINES_NONE, "GTK_CMCTREE_LINES_NONE", "none" },
+ { GTK_CMCTREE_LINES_SOLID, "GTK_CMCTREE_LINES_SOLID", "solid" },
+ { GTK_CMCTREE_LINES_DOTTED, "GTK_CMCTREE_LINES_DOTTED", "dotted" },
+ { GTK_CMCTREE_LINES_TABBED, "GTK_CMCTREE_LINES_TABBED", "tabbed" },
+ { 0, NULL, NULL }
+ };
+ etype = g_enum_register_static (g_intern_static_string ("GtkCMCTreeLineStyle"), values);
+ }
+ return etype;
+}
+GType
+gtk_cmctree_expander_style_get_type (void)
+{
+ static GType etype = 0;
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ { GTK_CMCTREE_EXPANDER_NONE, "GTK_CMCTREE_EXPANDER_NONE", "none" },
+ { GTK_CMCTREE_EXPANDER_SQUARE, "GTK_CMCTREE_EXPANDER_SQUARE", "square" },
+ { GTK_CMCTREE_EXPANDER_TRIANGLE, "GTK_CMCTREE_EXPANDER_TRIANGLE", "triangle" },
+ { GTK_CMCTREE_EXPANDER_CIRCULAR, "GTK_CMCTREE_EXPANDER_CIRCULAR", "circular" },
+ { 0, NULL, NULL }
+ };
+ etype = g_enum_register_static (g_intern_static_string ("GtkCMCTreeExpanderStyle"), values);
+ }
+ return etype;
+}
+GType
+gtk_cmctree_expansion_type_get_type (void)
+{
+ static GType etype = 0;
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ { GTK_CMCTREE_EXPANSION_EXPAND, "GTK_CMCTREE_EXPANSION_EXPAND", "expand" },
+ { GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE, "GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE", "expand-recursive" },
+ { GTK_CMCTREE_EXPANSION_COLLAPSE, "GTK_CMCTREE_EXPANSION_COLLAPSE", "collapse" },
+ { GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE, "GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE", "collapse-recursive" },
+ { GTK_CMCTREE_EXPANSION_TOGGLE, "GTK_CMCTREE_EXPANSION_TOGGLE", "toggle" },
+ { GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE, "GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE", "toggle-recursive" },
+ { 0, NULL, NULL }
+ };
+ etype = g_enum_register_static (g_intern_static_string ("GtkCMCTreeExpansionType"), values);
+ }
+ return etype;
+}
+
+
+static inline gint
+COLUMN_FROM_XPIXEL (GtkCMCList * 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) (((GtkCMCList*) (clist))->freeze_count == 0)
+#define CLIST_REFRESH(clist) G_STMT_START { \
+ if (CLIST_UNFROZEN (clist)) \
+ GTK_CMCLIST_GET_CLASS (clist)->refresh ((GtkCMCList*) (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_cmctree_class_init (GtkCMCTreeClass *klass);
+static void gtk_cmctree_init (GtkCMCTree *ctree);
+static GObject* gtk_cmctree_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params);
+static void gtk_cmctree_set_arg (GObject *object,
+ guint arg_id,
+ const GValue *value,
+ GParamSpec *spec);
+static void gtk_cmctree_get_arg (GObject *object,
+ guint arg_id,
+ GValue *value,
+ GParamSpec *spec);
+static void gtk_cmctree_realize (GtkWidget *widget);
+static void gtk_cmctree_unrealize (GtkWidget *widget);
+static gint gtk_cmctree_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static void ctree_attach_styles (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+static void ctree_detach_styles (GtkCMCTree *ctree,
+ GtkCMCTreeNode *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 (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint state,
+ gint column,
+ GtkStyle **style,
+ GdkGC **fg_gc,
+ GdkGC **bg_gc);
+static gint gtk_cmctree_draw_expander (GtkCMCTree *ctree,
+ GtkCMCTreeRow *ctree_row,
+ GtkStyle *style,
+ GdkRectangle *clip_rectangle,
+ gint x);
+static gint gtk_cmctree_draw_lines (GtkCMCTree *ctree,
+ GtkCMCTreeRow *ctree_row,
+ gint row,
+ gint column,
+ gint state,
+ GdkRectangle *clip_rectangle,
+ GdkRectangle *cell_rectangle,
+ GdkRectangle *crect,
+ GdkRectangle *area,
+ GtkStyle *style);
+static void draw_row (GtkCMCList *clist,
+ GdkRectangle *area,
+ gint row,
+ GtkCMCListRow *clist_row);
+static void draw_drag_highlight (GtkCMCList *clist,
+ GtkCMCListRow *dest_row,
+ gint dest_row_number,
+ GtkCMCListDragPos drag_pos);
+static void tree_draw_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+static void set_cell_contents (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ GtkCMCellType type,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask);
+static void set_node_info (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap_closed,
+ GdkBitmap *mask_closed,
+ GdkPixmap *pixmap_opened,
+ GdkBitmap *mask_opened,
+ gboolean is_leaf,
+ gboolean expanded);
+static GtkCMCTreeRow *row_new (GtkCMCTree *ctree);
+static void row_delete (GtkCMCTree *ctree,
+ GtkCMCTreeRow *ctree_row);
+static void tree_delete (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+static void tree_delete_row (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+static void real_clear (GtkCMCList *clist);
+static void tree_update_level (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+static void tree_select (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+static void tree_unselect (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+static void real_select_all (GtkCMCList *clist);
+static void real_unselect_all (GtkCMCList *clist);
+static void tree_expand (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+static void tree_collapse (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+static void tree_collapse_to_depth (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint depth);
+static void tree_toggle_expansion (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+static void change_focus_row_expansion (GtkCMCTree *ctree,
+ GtkCMCTreeExpansionType expansion);
+static void real_select_row (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event);
+static void real_unselect_row (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event);
+static void real_tree_select (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column);
+static void real_tree_unselect (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column);
+static void real_tree_expand (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+static void real_tree_collapse (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+static void real_tree_move (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *new_parent,
+ GtkCMCTreeNode *new_sibling);
+static void real_row_move (GtkCMCList *clist,
+ gint source_row,
+ gint dest_row);
+static void gtk_cmctree_link (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *sibling,
+ gboolean update_focus_row);
+static void gtk_cmctree_unlink (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gboolean update_focus_row);
+static GtkCMCTreeNode * gtk_cmctree_last_visible (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+static gboolean ctree_is_hot_spot (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint row,
+ gint x,
+ gint y);
+static void tree_sort (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+static void fake_unselect_all (GtkCMCList *clist,
+ gint row);
+static GList * selection_find (GtkCMCList *clist,
+ gint row_number,
+ GList *row_list_element);
+static void resync_selection (GtkCMCList *clist,
+ GdkEvent *event);
+static void real_undo_selection (GtkCMCList *clist);
+static void select_row_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+static gint real_insert_row (GtkCMCList *clist,
+ gint row,
+ gchar *text[]);
+static void real_remove_row (GtkCMCList *clist,
+ gint row);
+static void real_sort_list (GtkCMCList *clist);
+static void cell_size_request (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ GtkRequisition *requisition);
+static void column_auto_resize (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ gint old_width);
+static void auto_resize_columns (GtkCMCList *clist);
+
+
+static gboolean check_drag (GtkCMCTree *ctree,
+ GtkCMCTreeNode *drag_source,
+ GtkCMCTreeNode *drag_target,
+ GtkCMCListDragPos insert_pos);
+static void gtk_cmctree_drag_begin (GtkWidget *widget,
+ GdkDragContext *context);
+static gint gtk_cmctree_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time);
+static void gtk_cmctree_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint32 time);
+static void remove_grab (GtkCMCList *clist);
+static void drag_dest_cell (GtkCMCList *clist,
+ gint x,
+ gint y,
+ GtkCMCListDestInfo *dest_info);
+
+
+enum
+{
+ TREE_SELECT_ROW,
+ TREE_UNSELECT_ROW,
+ TREE_EXPAND,
+ TREE_COLLAPSE,
+ TREE_MOVE,
+ CHANGE_FOCUS_ROW_EXPANSION,
+ LAST_SIGNAL
+};
+
+static GtkCMCListClass *parent_class = NULL;
+static GtkContainerClass *container_class = NULL;
+static guint ctree_signals[LAST_SIGNAL] = {0};
+
+
+GType
+gtk_cmctree_get_type (void)
+{
+ static GType ctree_type = 0;
+
+ if (!ctree_type)
+ {
+ static const GTypeInfo ctree_info =
+ {
+ sizeof (GtkCMCTreeClass),
+
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+
+ (GClassInitFunc) gtk_cmctree_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+
+ sizeof (GtkCMCTree),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gtk_cmctree_init,
+ };
+
+ ctree_type = g_type_register_static (GTK_TYPE_CMCLIST, "GtkCMCTree", &ctree_info, (GTypeFlags)0);
+ }
+
+ return ctree_type;
+}
+
+static void
+gtk_cmctree_class_init (GtkCMCTreeClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkCMCListClass *clist_class;
+ GtkBindingSet *binding_set;
+
+ gobject_class->constructor = gtk_cmctree_constructor;
+
+ object_class = (GtkObjectClass *) klass;
+ widget_class = (GtkWidgetClass *) klass;
+ container_class = (GtkContainerClass *) klass;
+ clist_class = (GtkCMCListClass *) klass;
+
+ parent_class = gtk_type_class (GTK_TYPE_CMCLIST);
+ container_class = gtk_type_class (GTK_TYPE_CONTAINER);
+
+ gobject_class->set_property = gtk_cmctree_set_arg;
+ gobject_class->get_property = gtk_cmctree_get_arg;
+
+ widget_class->realize = gtk_cmctree_realize;
+ widget_class->unrealize = gtk_cmctree_unrealize;
+ widget_class->button_press_event = gtk_cmctree_button_press;
+
+ widget_class->drag_begin = gtk_cmctree_drag_begin;
+ widget_class->drag_motion = gtk_cmctree_drag_motion;
+ widget_class->drag_data_received = gtk_cmctree_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;
+
+ g_object_class_install_property (gobject_class,
+ ARG_N_COLUMNS,
+ g_param_spec_uint ("n-columns",
+ "N-Columns",
+ "N-Columns",
+ 1,
+ G_MAXINT,
+ 1,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (gobject_class,
+ ARG_TREE_COLUMN,
+ g_param_spec_uint ("tree-column",
+ "tree-column",
+ "tree-column",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (gobject_class,
+ ARG_INDENT,
+ g_param_spec_uint ("indent",
+ "indent",
+ "indent",
+ 1,
+ G_MAXINT,
+ 1,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ ARG_SPACING,
+ g_param_spec_uint ("spacing",
+ "spacing",
+ "spacing",
+ 1,
+ G_MAXINT,
+ 1,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ ARG_SHOW_STUB,
+ g_param_spec_boolean ("show-stub",
+ "show-stub",
+ "show-stub",
+ TRUE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ ARG_LINE_STYLE,
+ g_param_spec_enum ("line-style",
+ "line-style",
+ "line-style",
+ GTK_TYPE_CMCTREE_LINE_STYLE, 0,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ ARG_EXPANDER_STYLE,
+ g_param_spec_enum ("expander-style",
+ "expander-style",
+ "expander-style",
+ GTK_TYPE_CMCTREE_EXPANDER_STYLE, 0,
+ G_PARAM_READWRITE));
+
+ ctree_signals[TREE_SELECT_ROW] =
+ g_signal_new ("tree_select_row",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkCMCTreeClass, tree_select_row),
+ NULL, NULL,
+ claws_marshal_VOID__POINTER_INT,
+ G_TYPE_NONE, 2,
+ GTK_TYPE_CMCTREE_NODE,
+ G_TYPE_INT);
+ ctree_signals[TREE_UNSELECT_ROW] =
+ g_signal_new ("tree_unselect_row",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkCMCTreeClass, tree_unselect_row),
+ NULL, NULL,
+ claws_marshal_VOID__POINTER_INT,
+ G_TYPE_NONE, 2,
+ GTK_TYPE_CMCTREE_NODE,
+ G_TYPE_INT);
+ ctree_signals[TREE_EXPAND] =
+ g_signal_new ("tree_expand",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkCMCTreeClass, tree_expand),
+ NULL, NULL,
+ claws_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_CMCTREE_NODE);
+ ctree_signals[TREE_COLLAPSE] =
+ g_signal_new ("tree_collapse",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkCMCTreeClass, tree_collapse),
+ NULL, NULL,
+ claws_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_CMCTREE_NODE);
+ ctree_signals[TREE_MOVE] =
+ g_signal_new ("tree_move",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkCMCTreeClass, tree_move),
+ NULL, NULL,
+ claws_marshal_VOID__POINTER_POINTER_POINTER,
+ G_TYPE_NONE, 3,
+ GTK_TYPE_CMCTREE_NODE,GTK_TYPE_CMCTREE_NODE,GTK_TYPE_CMCTREE_NODE);
+ ctree_signals[CHANGE_FOCUS_ROW_EXPANSION] =
+ g_signal_new ("change_focus_row_expansion",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkCMCTreeClass, change_focus_row_expansion),
+ NULL, NULL,
+ claws_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1, GTK_TYPE_CMCTREE_EXPANSION_TYPE);
+
+ binding_set = gtk_binding_set_by_class (klass);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_plus, 0,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_EXPAND);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_plus, GDK_CONTROL_MASK,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE);
+
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KP_Add, 0,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_EXPAND);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KP_Add, GDK_CONTROL_MASK,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE);
+
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_minus, 0,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_COLLAPSE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_minus, GDK_CONTROL_MASK,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM,
+ GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KP_Subtract, 0,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_COLLAPSE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KP_Subtract, GDK_CONTROL_MASK,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM,
+ GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_equal, 0,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_TOGGLE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KP_Equal, 0,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_TOGGLE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KP_Multiply, 0,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_TOGGLE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_asterisk, 0,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_TOGGLE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KP_Multiply, GDK_CONTROL_MASK,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM,
+ GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_asterisk, GDK_CONTROL_MASK,
+ "change_focus_row_expansion", 1,
+ G_TYPE_ENUM,
+ GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE);
+}
+
+static void
+gtk_cmctree_set_arg (GObject *object,
+ guint arg_id,
+ const GValue *value,
+ GParamSpec *spec)
+{
+ GtkCMCTree *ctree;
+ GtkCMCList *clist;
+
+ ctree = GTK_CMCTREE (object);
+ clist = GTK_CMCLIST (ctree);
+
+ switch (arg_id)
+ {
+ case ARG_N_COLUMNS: /* construct-only arg, only set at construction time */
+ clist->columns = MAX (1, g_value_get_uint (value));
+ 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 = g_value_get_uint (value);
+ ctree->tree_column = CLAMP (ctree->tree_column, 0, clist->columns);
+ break;
+ case ARG_INDENT:
+ gtk_cmctree_set_indent (ctree, g_value_get_uint (value));
+ break;
+ case ARG_SPACING:
+ gtk_cmctree_set_spacing (ctree, g_value_get_uint (value));
+ break;
+ case ARG_SHOW_STUB:
+ gtk_cmctree_set_show_stub (ctree, g_value_get_boolean (value));
+ break;
+ case ARG_LINE_STYLE:
+ gtk_cmctree_set_line_style (ctree, g_value_get_enum (value));
+ break;
+ case ARG_EXPANDER_STYLE:
+ gtk_cmctree_set_expander_style (ctree, g_value_get_enum (value));
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+gtk_cmctree_get_arg (GObject *object,
+ guint arg_id,
+ GValue *value,
+ GParamSpec *spec)
+{
+ GtkCMCTree *ctree;
+
+ ctree = GTK_CMCTREE (object);
+
+ switch (arg_id)
+ {
+ case ARG_N_COLUMNS:
+ g_value_set_uint(value, GTK_CMCLIST (ctree)->columns);
+ break;
+ case ARG_TREE_COLUMN:
+ g_value_set_uint(value, ctree->tree_column);
+ break;
+ case ARG_INDENT:
+ g_value_set_uint(value, ctree->tree_indent);
+ break;
+ case ARG_SPACING:
+ g_value_set_uint(value, ctree->tree_spacing);
+ break;
+ case ARG_SHOW_STUB:
+ g_value_set_boolean(value, ctree->show_stub);
+ break;
+ case ARG_LINE_STYLE:
+ g_value_set_enum(value, ctree->line_style);
+ break;
+ case ARG_EXPANDER_STYLE:
+ g_value_set_enum(value, ctree->expander_style);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, spec);
+ break;
+ }
+}
+
+static void
+gtk_cmctree_init (GtkCMCTree *ctree)
+{
+ GtkCMCList *clist;
+
+ GTK_CMCLIST_SET_FLAG (ctree, CMCLIST_DRAW_DRAG_RECT);
+ GTK_CMCLIST_SET_FLAG (ctree, CMCLIST_DRAW_DRAG_LINE);
+
+ clist = GTK_CMCLIST (ctree);
+
+ ctree->tree_indent = 20;
+ ctree->tree_spacing = 5;
+ ctree->tree_column = 0;
+ ctree->line_style = GTK_CMCTREE_LINES_SOLID;
+ ctree->expander_style = GTK_CMCTREE_EXPANDER_SQUARE;
+ ctree->drag_compare = NULL;
+ ctree->show_stub = TRUE;
+
+ clist->button_actions[0] |= GTK_CMBUTTON_EXPANDS;
+}
+
+static void
+ctree_attach_styles (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ GtkCMCList *clist;
+ gint i;
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (GTK_CMCTREE_ROW (node)->row.style)
+ GTK_CMCTREE_ROW (node)->row.style =
+ gtk_style_attach (GTK_CMCTREE_ROW (node)->row.style, clist->clist_window);
+
+ if (GTK_CMCTREE_ROW (node)->row.fg_set || GTK_CMCTREE_ROW (node)->row.bg_set)
+ {
+ GdkColormap *colormap;
+
+ colormap = gtk_widget_get_colormap (GTK_WIDGET (ctree));
+ if (GTK_CMCTREE_ROW (node)->row.fg_set)
+ gdk_colormap_alloc_color (colormap, &(GTK_CMCTREE_ROW (node)->row.foreground), TRUE, TRUE);
+ if (GTK_CMCTREE_ROW (node)->row.bg_set)
+ gdk_colormap_alloc_color (colormap, &(GTK_CMCTREE_ROW (node)->row.background), TRUE, TRUE);
+ }
+
+ for (i = 0; i < clist->columns; i++)
+ if (GTK_CMCTREE_ROW (node)->row.cell[i].style)
+ GTK_CMCTREE_ROW (node)->row.cell[i].style =
+ gtk_style_attach (GTK_CMCTREE_ROW (node)->row.cell[i].style,
+ clist->clist_window);
+}
+
+static void
+ctree_detach_styles (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ GtkCMCList *clist;
+ gint i;
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (GTK_CMCTREE_ROW (node)->row.style)
+ gtk_style_detach (GTK_CMCTREE_ROW (node)->row.style);
+ for (i = 0; i < clist->columns; i++)
+ if (GTK_CMCTREE_ROW (node)->row.cell[i].style)
+ gtk_style_detach (GTK_CMCTREE_ROW (node)->row.cell[i].style);
+}
+
+static void
+gtk_cmctree_realize (GtkWidget *widget)
+{
+ GtkCMCTree *ctree;
+ GtkCMCList *clist;
+ GdkGCValues values;
+ GtkCMCTreeNode *node;
+ GtkCMCTreeNode *child;
+ gint i;
+
+ g_return_if_fail (GTK_IS_CMCTREE (widget));
+
+ GTK_WIDGET_CLASS (parent_class)->realize (widget);
+
+ ctree = GTK_CMCTREE (widget);
+ clist = GTK_CMCLIST (widget);
+
+ node = GTK_CMCTREE_NODE (clist->row_list);
+ for (i = 0; i < clist->rows; i++)
+ {
+ if (GTK_CMCTREE_ROW (node)->children && !GTK_CMCTREE_ROW (node)->expanded)
+ for (child = GTK_CMCTREE_ROW (node)->children; child;
+ child = GTK_CMCTREE_ROW (child)->sibling)
+ gtk_cmctree_pre_recursive (ctree, child, ctree_attach_styles, NULL);
+ node = GTK_CMCTREE_NODE_NEXT (node);
+ }
+
+ values.foreground = widget->style->fg[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_CMCLIST(widget)->clist_window,
+ &values,
+ GDK_GC_FOREGROUND |
+ GDK_GC_BACKGROUND |
+ GDK_GC_SUBWINDOW |
+ GDK_GC_LINE_STYLE);
+
+ if (ctree->line_style == GTK_CMCTREE_LINES_DOTTED)
+ {
+ gdk_gc_set_line_attributes (ctree->lines_gc, 1,
+ GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_MITER);
+ gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
+ }
+}
+
+static void
+gtk_cmctree_unrealize (GtkWidget *widget)
+{
+ GtkCMCTree *ctree;
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCTREE (widget));
+
+ GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
+
+ ctree = GTK_CMCTREE (widget);
+ clist = GTK_CMCLIST (widget);
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ GtkCMCTreeNode *node;
+ GtkCMCTreeNode *child;
+ gint i;
+
+ node = GTK_CMCTREE_NODE (clist->row_list);
+ for (i = 0; i < clist->rows; i++)
+ {
+ if (GTK_CMCTREE_ROW (node)->children &&
+ !GTK_CMCTREE_ROW (node)->expanded)
+ for (child = GTK_CMCTREE_ROW (node)->children; child;
+ child = GTK_CMCTREE_ROW (child)->sibling)
+ gtk_cmctree_pre_recursive(ctree, child, ctree_detach_styles, NULL);
+ node = GTK_CMCTREE_NODE_NEXT (node);
+ }
+ }
+
+ g_object_unref (ctree->lines_gc);
+}
+
+static gint
+gtk_cmctree_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkCMCTree *ctree;
+ GtkCMCList *clist;
+ gint button_actions;
+
+ g_return_val_if_fail (GTK_IS_CMCTREE (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ ctree = GTK_CMCTREE (widget);
+ clist = GTK_CMCLIST (widget);
+
+ button_actions = clist->button_actions[event->button - 1];
+
+ if (button_actions == GTK_CMBUTTON_IGNORED)
+ return FALSE;
+
+ if (event->window == clist->clist_window)
+ {
+ GtkCMCTreeNode *work;
+ gint x;
+ gint y;
+ gint row;
+ gint column;
+
+ x = event->x;
+ y = event->y;
+
+ if (!gtk_cmclist_get_selection_info (clist, x, y, &row, &column))
+ return FALSE;
+
+ work = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, row));
+
+ if (button_actions & GTK_CMBUTTON_EXPANDS &&
+ (GTK_CMCTREE_ROW (work)->children && !GTK_CMCTREE_ROW (work)->is_leaf &&
+ (event->type == GDK_2BUTTON_PRESS ||
+ ctree_is_hot_spot (ctree, work, row, x, y))))
+ {
+ if (GTK_CMCTREE_ROW (work)->expanded)
+ gtk_cmctree_collapse (ctree, work);
+ else
+ gtk_cmctree_expand (ctree, work);
+
+ return TRUE;
+ }
+ }
+
+ return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event);
+}
+
+static void
+draw_drag_highlight (GtkCMCList *clist,
+ GtkCMCListRow *dest_row,
+ gint dest_row_number,
+ GtkCMCListDragPos drag_pos)
+{
+ GtkCMCTree *ctree;
+ GdkPoint points[4];
+ gint level;
+ gint i;
+ gint y = 0;
+
+ g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+ ctree = GTK_CMCTREE (clist);
+
+ level = ((GtkCMCTreeRow *)(dest_row))->level;
+
+ y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
+
+ switch (drag_pos)
+ {
+ case GTK_CMCLIST_DRAG_NONE:
+ break;
+ case GTK_CMCLIST_DRAG_AFTER:
+ y += clist->row_height + 1;
+ case GTK_CMCLIST_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_CMCLIST_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;
+ }
+}
+
+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)
+{
+ gint xsrc = 0;
+ gint ysrc = 0;
+
+ 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;
+
+ 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 (width > 0 && height > 0)
+ gdk_draw_drawable (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
+
+ if (mask)
+ {
+ gdk_gc_set_clip_rectangle (fg_gc, NULL);
+ gdk_gc_set_clip_origin (fg_gc, 0, 0);
+ }
+
+ return x + MAX (width, 0);
+}
+
+static void
+get_cell_style (GtkCMCList *clist,
+ GtkCMCListRow *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;
+
+ 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 (state != GTK_STATE_SELECTED)
+ {
+ if (fg_gc && clist_row->fg_set)
+ *fg_gc = clist->fg_gc;
+ if (bg_gc && clist_row->bg_set)
+ *bg_gc = clist->bg_gc;
+ }
+ }
+}
+
+static gint
+gtk_cmctree_draw_expander (GtkCMCTree *ctree,
+ GtkCMCTreeRow *ctree_row,
+ GtkStyle *style,
+ GdkRectangle *clip_rectangle,
+ gint x)
+{
+ GtkCMCList *clist;
+ GdkPoint points[3];
+ gint justification_factor;
+ gint y;
+
+ if (ctree->expander_style == GTK_CMCTREE_EXPANDER_NONE)
+ return x;
+
+ clist = GTK_CMCLIST (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_CMCTREE_EXPANDER_NONE:
+ return x;
+ case GTK_CMCTREE_EXPANDER_TRIANGLE:
+ return x + justification_factor * (PM_SIZE + 3);
+ case GTK_CMCTREE_EXPANDER_SQUARE:
+ case GTK_CMCTREE_EXPANDER_CIRCULAR:
+ return x + justification_factor * (PM_SIZE + 1);
+ }
+ }
+
+ 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);
+
+ switch (ctree->expander_style)
+ {
+ case GTK_CMCTREE_EXPANDER_NONE:
+ break;
+ case GTK_CMCTREE_EXPANDER_TRIANGLE:
+ if (ctree_row->expanded)
+ {
+ 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_CMCTREE_EXPANDER_SQUARE:
+ case GTK_CMCTREE_EXPANDER_CIRCULAR:
+ if (justification_factor == -1)
+ x += justification_factor * (PM_SIZE + 1);
+
+ if (ctree->expander_style == GTK_CMCTREE_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;
+ }
+
+ 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_cmctree_draw_lines (GtkCMCTree *ctree,
+ GtkCMCTreeRow *ctree_row,
+ gint row,
+ gint column,
+ gint state,
+ GdkRectangle *clip_rectangle,
+ GdkRectangle *cell_rectangle,
+ GdkRectangle *crect,
+ GdkRectangle *area,
+ GtkStyle *style)
+{
+ GtkCMCList *clist;
+ GtkCMCTreeNode *node;
+ GtkCMCTreeNode *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_CMCLIST (ctree);
+ ycenter = clip_rectangle->y + (clip_rectangle->height / 2);
+ justify_right = (clist->column[column].justification == GTK_JUSTIFY_RIGHT);
+
+ 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;
+ }
+
+ switch (ctree->line_style)
+ {
+ case GTK_CMCTREE_LINES_NONE:
+ break;
+ case GTK_CMCTREE_LINES_TABBED:
+ xcenter = offset + justification_factor * TAB_SIZE;
+
+ 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 (area)
+ {
+ tree_rectangle.y = crect->y;
+ tree_rectangle.height = crect->height;
+
+ if (justify_right)
+ {
+ tree_rectangle.x = xcenter;
+ tree_rectangle.width = column_right - xcenter;
+ }
+ else
+ {
+ tree_rectangle.x = column_left;
+ tree_rectangle.width = xcenter - column_left;
+ }
+
+ if (!gdk_rectangle_intersect (area, &tree_rectangle, &tc_rectangle))
+ {
+ offset += justification_factor * 3;
+ break;
+ }
+ }
+
+ gdk_gc_set_clip_rectangle (ctree->lines_gc, crect);
+
+ next_level = ctree_row->level;
+
+ if (!ctree_row->sibling || (ctree_row->children && ctree_row->expanded))
+ {
+ node = gtk_cmctree_find_node_ptr (ctree, ctree_row);
+ if (GTK_CMCTREE_NODE_NEXT (node))
+ next_level = GTK_CMCTREE_ROW (GTK_CMCTREE_NODE_NEXT (node))->level;
+ else
+ next_level = 0;
+ }
+
+ if (ctree->tree_indent > 0)
+ {
+ node = ctree_row->parent;
+ while (node)
+ {
+ xcenter -= (justification_factor * ctree->tree_indent);
+
+ if ((justify_right && xcenter < column_left) ||
+ (!justify_right && xcenter > column_right))
+ {
+ node = GTK_CMCTREE_ROW (node)->parent;
+ continue;
+ }
+
+ 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);
+ }
+
+ if (!area || gdk_rectangle_intersect (area, &tree_rectangle,
+ &tc_rectangle))
+ {
+ get_cell_style (clist, >K_CMCTREE_ROW (node)->row,
+ state, column, NULL, NULL, &bg_gc);
+
+ if (bg_gc == clist->bg_gc)
+ gdk_gc_set_foreground
+ (clist->bg_gc, >K_CMCTREE_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_CMCTREE_ROW (node)->level)
+ gdk_draw_line (clist->clist_window, ctree->lines_gc,
+ xcenter, crect->y,
+ xcenter, crect->y + crect->height);
+ else
+ {
+ gint width;
+
+ offset_x = MIN (ctree->tree_indent, 2 * TAB_SIZE);
+ width = offset_x / 2 + offset_x % 2;
+
+ parent = GTK_CMCTREE_ROW (node)->parent;
+
+ tree_rectangle.y = ycenter;
+ tree_rectangle.height = (cell_rectangle->y - ycenter +
+ cell_rectangle->height);
+
+ 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);
+ }
+
+ if (!area ||
+ gdk_rectangle_intersect (area, &tree_rectangle,
+ &tc_rectangle))
+ {
+ if (parent)
+ {
+ get_cell_style (clist, >K_CMCTREE_ROW (parent)->row,
+ state, column, NULL, NULL, &bg_gc);
+ if (bg_gc == clist->bg_gc)
+ gdk_gc_set_foreground
+ (clist->bg_gc,
+ >K_CMCTREE_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);
+ }
+
+ get_cell_style (clist, >K_CMCTREE_ROW (node)->row,
+ state, column, NULL, NULL, &bg_gc);
+ if (bg_gc == clist->bg_gc)
+ gdk_gc_set_foreground
+ (clist->bg_gc, >K_CMCTREE_ROW (node)->row.background);
+
+ 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);
+
+ gdk_draw_line (clist->clist_window, ctree->lines_gc,
+ xcenter, cell_rectangle->y, xcenter, ycenter);
+
+ 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_CMCTREE_ROW (node)->parent;
+ }
+ }
+
+ 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;
+
+ 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);
+ }
+
+ xcenter = offset + (justification_factor * ctree->tree_indent / 2);
+
+ 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);
+
+ gdk_gc_set_clip_rectangle (bg_gc, crect);
+ if (ctree_row->is_leaf)
+ {
+ GdkPoint points[6];
+
+ points[0].x = offset + justification_factor * TAB_SIZE;
+ points[0].y = cell_rectangle->y;
+
+ points[1].x = points[0].x - justification_factor * 4;
+ points[1].y = points[0].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;
+ default:
+ xcenter = offset + justification_factor * PM_SIZE / 2;
+
+ if (area)
+ {
+ 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_CMCTREE_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);
+
+ if (GTK_CMCTREE_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_CMCTREE_ROW (node)->parent;
+ }
+ gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
+ clip_rectangle->y++;
+ clip_rectangle->height--;
+ break;
+ }
+ return offset;
+}
+
+static void
+draw_row (GtkCMCList *clist,
+ GdkRectangle *area,
+ gint row,
+ GtkCMCListRow *clist_row)
+{
+ GtkWidget *widget;
+ GtkCMCTree *ctree;
+ GdkRectangle *crect;
+ GdkRectangle row_rectangle;
+ GdkRectangle cell_rectangle;
+ GdkRectangle clip_rectangle;
+ GdkRectangle intersect_rectangle;
+ 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) || row < 0 || row >= clist->rows)
+ return;
+
+ widget = GTK_WIDGET (clist);
+ ctree = GTK_CMCTREE (clist);
+
+ /* if the function is passed the pointer to the row instead of null,
+ * it avoids this expensive lookup */
+ if (!clist_row)
+ clist_row = (g_list_nth (clist->row_list, row))->data;
+
+ /* rectangle of the entire row */
+ row_rectangle.x = 0;
+ row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
+ row_rectangle.width = clist->clist_window_width;
+ row_rectangle.height = clist->row_height;
+
+ /* rectangle of the cell spacing above the row */
+ cell_rectangle.x = 0;
+ cell_rectangle.y = row_rectangle.y - CELL_SPACING;
+ cell_rectangle.width = row_rectangle.width;
+ cell_rectangle.height = CELL_SPACING;
+
+ /* 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;
+
+ if (clist_row->state == GTK_STATE_NORMAL)
+ {
+ if (clist_row->fg_set)
+ 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);
+ }
+
+ state = clist_row->state;
+
+ gdk_gc_set_foreground (ctree->lines_gc,
+ &widget->style->fg[clist_row->state]);
+
+ /* draw the cell borders */
+ if (area)
+ {
+ crect = &intersect_rectangle;
+
+ 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
+ {
+ crect = &cell_rectangle;
+
+ gdk_draw_rectangle (clist->clist_window,
+ widget->style->base_gc[GTK_STATE_NORMAL], TRUE,
+ crect->x, crect->y, crect->width, crect->height);
+ }
+
+ /* horizontal black lines */
+ if (ctree->line_style == GTK_CMCTREE_LINES_TABBED)
+ {
+
+ 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);
+
+ switch (clist->column[ctree->tree_column].justification)
+ {
+ case GTK_JUSTIFY_CENTER:
+ case GTK_JUSTIFY_FILL:
+ case GTK_JUSTIFY_LEFT:
+ offset = (column_left + ctree->tree_indent *
+ (((GtkCMCTreeRow *)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 *
+ (((GtkCMCTreeRow *)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 (!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);
+
+ /* horizontal black lines */
+ if (ctree->line_style == GTK_CMCTREE_LINES_TABBED)
+ {
+ switch (clist->column[ctree->tree_column].justification)
+ {
+ 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 +
+ (((GtkCMCTreeRow *)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 -
+ (((GtkCMCTreeRow *)clist_row)->level > 1) *
+ MIN (ctree->tree_indent / 2, TAB_SIZE),
+ column_left - 1), cell_rectangle.y);
+ break;
+ }
+ }
+ }
+ }
+
+ for (last_column = clist->columns - 1;
+ last_column >= 0 && !clist->column[last_column].visible; last_column--)
+ ;
+
+ /* 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;
+
+ get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
+
+ /* calculate clipping region */
+ clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
+ clip_rectangle.width = clist->column[i].area.width;
+
+ 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;
+
+ string_width = 0;
+ pixmap_width = 0;
+
+ if (area && !gdk_rectangle_intersect (area, &cell_rectangle,
+ &intersect_rectangle))
+ {
+ if (i != ctree->tree_column)
+ continue;
+ }
+ else
+ {
+ gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
+ crect->x, crect->y, crect->width, crect->height);
+
+
+ layout = _gtk_cmclist_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;
+
+ switch (clist_row->cell[i].type)
+ {
+ case GTK_CMCELL_PIXMAP:
+ gdk_drawable_get_size
+ (GTK_CMCELL_PIXMAP (clist_row->cell[i])->pixmap, &pixmap_width,
+ &height);
+ width += pixmap_width;
+ break;
+ case GTK_CMCELL_PIXTEXT:
+ if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+ {
+ gdk_drawable_get_size
+ (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+ &pixmap_width, &height);
+ width += pixmap_width;
+ }
+
+ if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->text &&
+ GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+ width += GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
+
+ if (i == ctree->tree_column)
+ width += (ctree->tree_indent *
+ ((GtkCMCTreeRow *)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 + 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_CMCELL_PIXMAP:
+ draw_cell_pixmap
+ (clist->clist_window, &clip_rectangle, fg_gc,
+ GTK_CMCELL_PIXMAP (clist_row->cell[i])->pixmap,
+ GTK_CMCELL_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_CMCELL_PIXTEXT:
+ offset = draw_cell_pixmap
+ (clist->clist_window, &clip_rectangle, fg_gc,
+ GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+ GTK_CMCELL_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_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
+
+ /* Fall through */
+ case GTK_CMCELL_TEXT:
+ if (layout)
+ {
+ gint row_center_offset = (clist->row_height - logical_rect.height) / 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));
+ }
+ break;
+ default:
+ break;
+ }
+ continue;
+ }
+ }
+
+ if (bg_gc == clist->bg_gc)
+ gdk_gc_set_background (ctree->lines_gc, &clist_row->background);
+
+ /* draw ctree->tree_column */
+ cell_rectangle.y -= CELL_SPACING;
+ cell_rectangle.height += CELL_SPACING;
+
+ if (area && !gdk_rectangle_intersect (area, &cell_rectangle,
+ &intersect_rectangle))
+ {
+ if (layout)
+ g_object_unref (G_OBJECT (layout));
+ continue;
+ }
+
+ /* draw lines */
+ offset = gtk_cmctree_draw_lines (ctree, (GtkCMCTreeRow *)clist_row, row, i,
+ state, &clip_rectangle, &cell_rectangle,
+ crect, area, style);
+
+ /* draw expander */
+ offset = gtk_cmctree_draw_expander (ctree, (GtkCMCTreeRow *)clist_row,
+ style, &clip_rectangle, offset);
+
+ 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_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+ GTK_CMCELL_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 = (clist->row_height - logical_rect.height) / 2;
+
+ if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
+ {
+ offset = (old_offset - string_width);
+ if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+ offset -= GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
+ }
+ else
+ {
+ if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+ offset += GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
+ }
+
+ 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);
+
+ g_object_unref (G_OBJECT (layout));
+ }
+ gdk_gc_set_clip_rectangle (fg_gc, NULL);
+ }
+
+ /* draw focus rectangle */
+ if (clist->focus_row == row &&
+ GTK_WIDGET_CAN_FOCUS (widget) && GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ 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);
+ }
+ }
+}
+
+static void
+tree_draw_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ GtkCMCList *clist;
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (CLIST_UNFROZEN (clist) && gtk_cmctree_is_viewable (ctree, node))
+ {
+ GtkCMCTreeNode *work;
+ gint num = 0;
+
+ work = GTK_CMCTREE_NODE (clist->row_list);
+ while (work && work != node)
+ {
+ work = GTK_CMCTREE_NODE_NEXT (work);
+ num++;
+ }
+ if (work && gtk_cmclist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row
+ (clist, NULL, num, GTK_CMCLIST_ROW ((GList *) node));
+ }
+}
+
+static GtkCMCTreeNode *
+gtk_cmctree_last_visible (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ GtkCMCTreeNode *work;
+
+ if (!node)
+ return NULL;
+
+ work = GTK_CMCTREE_ROW (node)->children;
+
+ if (!work || !GTK_CMCTREE_ROW (node)->expanded)
+ return node;
+
+ while (GTK_CMCTREE_ROW (work)->sibling)
+ work = GTK_CMCTREE_ROW (work)->sibling;
+
+ return gtk_cmctree_last_visible (ctree, work);
+}
+
+static void
+gtk_cmctree_link (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *sibling,
+ gboolean update_focus_row)
+{
+ GtkCMCList *clist;
+ GList *list_end;
+ GList *list;
+ GList *work;
+ gboolean visible = FALSE;
+ gint rows = 0;
+
+ if (sibling)
+ g_return_if_fail (GTK_CMCTREE_ROW (sibling)->parent == parent);
+ g_return_if_fail (node != NULL);
+ g_return_if_fail (node != sibling);
+ g_return_if_fail (node != parent);
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (update_focus_row && clist->selection_mode == GTK_SELECTION_MULTIPLE)
+ {
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+ }
+
+ for (rows = 1, list_end = (GList *)node; list_end->next;
+ list_end = list_end->next)
+ rows++;
+
+ GTK_CMCTREE_ROW (node)->parent = parent;
+ GTK_CMCTREE_ROW (node)->sibling = sibling;
+
+ if (!parent || (parent && (gtk_cmctree_is_viewable (ctree, parent) &&
+ GTK_CMCTREE_ROW (parent)->expanded)))
+ {
+ visible = TRUE;
+ clist->rows += rows;
+ }
+
+ if (parent)
+ work = (GList *)(GTK_CMCTREE_ROW (parent)->children);
+ else
+ work = clist->row_list;
+
+ if (sibling)
+ {
+ if (work != (GList *)sibling)
+ {
+ while (GTK_CMCTREE_ROW (work)->sibling != sibling)
+ work = (GList *)(GTK_CMCTREE_ROW (work)->sibling);
+ GTK_CMCTREE_ROW (work)->sibling = node;
+ }
+
+ if (sibling == GTK_CMCTREE_NODE (clist->row_list))
+ clist->row_list = (GList *) node;
+ if (GTK_CMCTREE_NODE_PREV (sibling) &&
+ GTK_CMCTREE_NODE_NEXT (GTK_CMCTREE_NODE_PREV (sibling)) == sibling)
+ {
+ list = (GList *)GTK_CMCTREE_NODE_PREV (sibling);
+ list->next = (GList *)node;
+ }
+
+ list = (GList *)node;
+ list->prev = (GList *)GTK_CMCTREE_NODE_PREV (sibling);
+ list_end->next = (GList *)sibling;
+ list = (GList *)sibling;
+ list->prev = list_end;
+ if (parent && GTK_CMCTREE_ROW (parent)->children == sibling)
+ GTK_CMCTREE_ROW (parent)->children = node;
+ }
+ else
+ {
+ if (work)
+ {
+ /* find sibling */
+ while (GTK_CMCTREE_ROW (work)->sibling)
+ work = (GList *)(GTK_CMCTREE_ROW (work)->sibling);
+ GTK_CMCTREE_ROW (work)->sibling = node;
+
+ /* find last visible child of sibling */
+ work = (GList *) gtk_cmctree_last_visible (ctree,
+ GTK_CMCTREE_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_CMCTREE_ROW (parent)->children = node;
+ list = (GList *)node;
+ list->prev = (GList *)parent;
+ if (GTK_CMCTREE_ROW (parent)->expanded)
+ {
+ list_end->next = (GList *)GTK_CMCTREE_NODE_NEXT (parent);
+ if (GTK_CMCTREE_NODE_NEXT(parent))
+ {
+ list = (GList *)GTK_CMCTREE_NODE_NEXT (parent);
+ list->prev = list_end;
+ }
+ list = (GList *)parent;
+ list->next = (GList *)node;
+ }
+ else
+ list_end->next = NULL;
+ }
+ else
+ {
+ clist->row_list = (GList *)node;
+ list = (GList *)node;
+ list->prev = NULL;
+ list_end->next = NULL;
+ }
+ }
+ }
+
+ gtk_cmctree_pre_recursive (ctree, node, tree_update_level, NULL);
+
+ if (clist->row_list_end == NULL ||
+ clist->row_list_end->next == (GList *)node)
+ clist->row_list_end = list_end;
+
+ if (visible && update_focus_row)
+ {
+ gint pos;
+
+ pos = g_list_position (clist->row_list, (GList *)node);
+
+ if (pos <= clist->focus_row)
+ {
+ clist->focus_row += rows;
+ clist->undo_anchor = clist->focus_row;
+ }
+ }
+}
+
+static void
+gtk_cmctree_unlink (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gboolean update_focus_row)
+{
+ GtkCMCList *clist;
+ gint rows;
+ gint level;
+ gint visible;
+ GtkCMCTreeNode *work;
+ GtkCMCTreeNode *parent;
+ GList *list;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (update_focus_row && clist->selection_mode == GTK_SELECTION_MULTIPLE)
+ {
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+ }
+
+ visible = gtk_cmctree_is_viewable (ctree, node);
+
+ /* clist->row_list_end unlinked ? */
+ if (visible &&
+ (GTK_CMCTREE_NODE_NEXT (node) == NULL ||
+ (GTK_CMCTREE_ROW (node)->children &&
+ gtk_cmctree_is_ancestor (ctree, node,
+ GTK_CMCTREE_NODE (clist->row_list_end)))))
+ clist->row_list_end = (GList *) (GTK_CMCTREE_NODE_PREV (node));
+
+ /* update list */
+ rows = 0;
+ level = GTK_CMCTREE_ROW (node)->level;
+ work = GTK_CMCTREE_NODE_NEXT (node);
+ while (work && GTK_CMCTREE_ROW (work)->level > level)
+ {
+ work = GTK_CMCTREE_NODE_NEXT (work);
+ rows++;
+ }
+
+ if (visible)
+ {
+ clist->rows -= (rows + 1);
+
+ if (update_focus_row)
+ {
+ gint pos;
+
+ pos = g_list_position (clist->row_list, (GList *)node);
+ if (pos + rows < clist->focus_row)
+ clist->focus_row -= (rows + 1);
+ else if (pos <= clist->focus_row)
+ {
+ if (!GTK_CMCTREE_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)
+ {
+ list = (GList *)GTK_CMCTREE_NODE_PREV (work);
+ list->next = NULL;
+ list = (GList *)work;
+ list->prev = (GList *)GTK_CMCTREE_NODE_PREV (node);
+ }
+
+ if (GTK_CMCTREE_NODE_PREV (node) &&
+ GTK_CMCTREE_NODE_NEXT (GTK_CMCTREE_NODE_PREV (node)) == node)
+ {
+ list = (GList *)GTK_CMCTREE_NODE_PREV (node);
+ list->next = (GList *)work;
+ }
+
+ /* update tree */
+ parent = GTK_CMCTREE_ROW (node)->parent;
+ if (parent)
+ {
+ if (GTK_CMCTREE_ROW (parent)->children == node)
+ {
+ GTK_CMCTREE_ROW (parent)->children = GTK_CMCTREE_ROW (node)->sibling;
+ if (!GTK_CMCTREE_ROW (parent)->children)
+ gtk_cmctree_collapse (ctree, parent);
+ }
+ else
+ {
+ GtkCMCTreeNode *sibling;
+
+ sibling = GTK_CMCTREE_ROW (parent)->children;
+ while (GTK_CMCTREE_ROW (sibling)->sibling != node)
+ sibling = GTK_CMCTREE_ROW (sibling)->sibling;
+ GTK_CMCTREE_ROW (sibling)->sibling = GTK_CMCTREE_ROW (node)->sibling;
+ }
+ }
+ else
+ {
+ if (clist->row_list == (GList *)node)
+ clist->row_list = (GList *) (GTK_CMCTREE_ROW (node)->sibling);
+ else
+ {
+ GtkCMCTreeNode *sibling;
+
+ sibling = GTK_CMCTREE_NODE (clist->row_list);
+ while (GTK_CMCTREE_ROW (sibling)->sibling != node)
+ sibling = GTK_CMCTREE_ROW (sibling)->sibling;
+ GTK_CMCTREE_ROW (sibling)->sibling = GTK_CMCTREE_ROW (node)->sibling;
+ }
+ }
+}
+
+static void
+real_row_move (GtkCMCList *clist,
+ gint source_row,
+ gint dest_row)
+{
+ GtkCMCTree *ctree;
+ GtkCMCTreeNode *node;
+
+ g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+ if (GTK_CMCLIST_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_CMCTREE (clist);
+ node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, source_row));
+
+ if (source_row < dest_row)
+ {
+ GtkCMCTreeNode *work;
+
+ dest_row++;
+ work = GTK_CMCTREE_ROW (node)->children;
+
+ while (work && GTK_CMCTREE_ROW (work)->level > GTK_CMCTREE_ROW (node)->level)
+ {
+ work = GTK_CMCTREE_NODE_NEXT (work);
+ dest_row++;
+ }
+
+ if (dest_row > clist->rows)
+ dest_row = clist->rows;
+ }
+
+ if (dest_row < clist->rows)
+ {
+ GtkCMCTreeNode *sibling;
+
+ sibling = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, dest_row));
+ gtk_cmctree_move (ctree, node, GTK_CMCTREE_ROW (sibling)->parent, sibling);
+ }
+ else
+ gtk_cmctree_move (ctree, node, NULL, NULL);
+}
+
+static void
+real_tree_move (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *new_parent,
+ GtkCMCTreeNode *new_sibling)
+{
+ GtkCMCList *clist;
+ GtkCMCTreeNode *work;
+ gboolean visible = FALSE;
+
+ g_return_if_fail (ctree != NULL);
+ g_return_if_fail (node != NULL);
+ g_return_if_fail (!new_sibling ||
+ GTK_CMCTREE_ROW (new_sibling)->parent == new_parent);
+
+ if (new_parent && GTK_CMCTREE_ROW (new_parent)->is_leaf)
+ return;
+
+ /* new_parent != child of child */
+ for (work = new_parent; work; work = GTK_CMCTREE_ROW (work)->parent)
+ if (work == node)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ visible = gtk_cmctree_is_viewable (ctree, node);
+
+ if (clist->selection_mode == GTK_SELECTION_MULTIPLE)
+ {
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+ }
+
+ if (GTK_CMCLIST_AUTO_SORT (clist))
+ {
+ if (new_parent == GTK_CMCTREE_ROW (node)->parent)
+ return;
+
+ if (new_parent)
+ new_sibling = GTK_CMCTREE_ROW (new_parent)->children;
+ else
+ new_sibling = GTK_CMCTREE_NODE (clist->row_list);
+
+ while (new_sibling && clist->compare
+ (clist, GTK_CMCTREE_ROW (node), GTK_CMCTREE_ROW (new_sibling)) > 0)
+ new_sibling = GTK_CMCTREE_ROW (new_sibling)->sibling;
+ }
+
+ if (new_parent == GTK_CMCTREE_ROW (node)->parent &&
+ new_sibling == GTK_CMCTREE_ROW (node)->sibling)
+ return;
+
+ gtk_cmclist_freeze (clist);
+
+ work = NULL;
+ if (gtk_cmctree_is_viewable (ctree, node))
+ work = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
+
+ gtk_cmctree_unlink (ctree, node, FALSE);
+ gtk_cmctree_link (ctree, node, new_parent, new_sibling, FALSE);
+
+ if (work)
+ {
+ while (work && !gtk_cmctree_is_viewable (ctree, work))
+ work = GTK_CMCTREE_ROW (work)->parent;
+ clist->focus_row = g_list_position (clist->row_list, (GList *)work);
+ clist->undo_anchor = clist->focus_row;
+ }
+
+ if (clist->column[ctree->tree_column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist) &&
+ (visible || gtk_cmctree_is_viewable (ctree, node)))
+ gtk_cmclist_set_column_width
+ (clist, ctree->tree_column,
+ gtk_cmclist_optimal_column_width (clist, ctree->tree_column));
+
+ gtk_cmclist_thaw (clist);
+}
+
+static void
+change_focus_row_expansion (GtkCMCTree *ctree,
+ GtkCMCTreeExpansionType action)
+{
+ GtkCMCList *clist;
+ GtkCMCTreeNode *node;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (ctree))) &&
+ GTK_WIDGET_HAS_GRAB (ctree))
+ return;
+
+ if (!(node =
+ GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row))) ||
+ GTK_CMCTREE_ROW (node)->is_leaf || !(GTK_CMCTREE_ROW (node)->children))
+ return;
+
+ switch (action)
+ {
+ case GTK_CMCTREE_EXPANSION_EXPAND:
+ gtk_cmctree_expand (ctree, node);
+ break;
+ case GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE:
+ gtk_cmctree_expand_recursive (ctree, node);
+ break;
+ case GTK_CMCTREE_EXPANSION_COLLAPSE:
+ gtk_cmctree_collapse (ctree, node);
+ break;
+ case GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE:
+ gtk_cmctree_collapse_recursive (ctree, node);
+ break;
+ case GTK_CMCTREE_EXPANSION_TOGGLE:
+ gtk_cmctree_toggle_expansion (ctree, node);
+ break;
+ case GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE:
+ gtk_cmctree_toggle_expansion_recursive (ctree, node);
+ break;
+ }
+}
+
+static void
+real_tree_expand (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ GtkCMCList *clist;
+ GtkCMCTreeNode *work;
+ GtkRequisition requisition;
+ gboolean visible;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ if (!node || GTK_CMCTREE_ROW (node)->expanded || GTK_CMCTREE_ROW (node)->is_leaf)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+ GTK_CMCTREE_ROW (node)->expanded = TRUE;
+
+ visible = gtk_cmctree_is_viewable (ctree, node);
+ /* get cell width if tree_column is auto resized */
+ if (visible && clist->column[ctree->tree_column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+ (clist, >K_CMCTREE_ROW (node)->row, ctree->tree_column, &requisition);
+
+ /* unref/unset closed pixmap */
+ if (GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
+ {
+ g_object_unref
+ (GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
+
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
+
+ if (GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
+ {
+ g_object_unref
+ (GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
+ }
+ }
+
+ /* set/ref opened pixmap */
+ if (GTK_CMCTREE_ROW (node)->pixmap_opened)
+ {
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
+ g_object_ref (GTK_CMCTREE_ROW (node)->pixmap_opened);
+
+ if (GTK_CMCTREE_ROW (node)->mask_opened)
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
+ g_object_ref (GTK_CMCTREE_ROW (node)->mask_opened);
+ }
+
+
+ work = GTK_CMCTREE_ROW (node)->children;
+ if (work)
+ {
+ GList *list = (GList *)work;
+ gint *cell_width = NULL;
+ gint tmp = 0;
+ gint row;
+ gint i;
+
+ if (visible && !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ {
+ 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_CMCLIST_GET_CLASS (clist)->cell_size_request
+ (clist, >K_CMCTREE_ROW (work)->row, i, &requisition);
+ cell_width[i] = MAX (requisition.width, cell_width[i]);
+ }
+
+ list = (GList *)work;
+ work = GTK_CMCTREE_NODE_NEXT (work);
+ tmp++;
+ }
+ }
+ else
+ while (work)
+ {
+ list = (GList *)work;
+ work = GTK_CMCTREE_NODE_NEXT (work);
+ tmp++;
+ }
+
+ list->next = (GList *)GTK_CMCTREE_NODE_NEXT (node);
+
+ if (GTK_CMCTREE_NODE_NEXT (node))
+ {
+ GList *tmp_list;
+
+ tmp_list = (GList *)GTK_CMCTREE_NODE_NEXT (node);
+ tmp_list->prev = list;
+ }
+ else
+ clist->row_list_end = list;
+
+ list = (GList *)node;
+ list->next = (GList *)(GTK_CMCTREE_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_cmclist_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;
+
+ 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_CMCTREE_ROW (node)->row, ctree->tree_column,
+ requisition.width);
+}
+
+static void
+real_tree_collapse (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ GtkCMCList *clist;
+ GtkCMCTreeNode *work;
+ GtkRequisition requisition;
+ gboolean visible;
+ gint level;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ if (!node || !GTK_CMCTREE_ROW (node)->expanded ||
+ GTK_CMCTREE_ROW (node)->is_leaf)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+ GTK_CMCTREE_ROW (node)->expanded = FALSE;
+ level = GTK_CMCTREE_ROW (node)->level;
+
+ visible = gtk_cmctree_is_viewable (ctree, node);
+ /* get cell width if tree_column is auto resized */
+ if (visible && clist->column[ctree->tree_column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+ (clist, >K_CMCTREE_ROW (node)->row, ctree->tree_column, &requisition);
+
+ /* unref/unset opened pixmap */
+ if (GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
+ {
+ g_object_unref
+ (GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
+
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
+
+ if (GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
+ {
+ g_object_unref
+ (GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
+ }
+ }
+
+ /* set/ref closed pixmap */
+ if (GTK_CMCTREE_ROW (node)->pixmap_closed)
+ {
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
+ g_object_ref (GTK_CMCTREE_ROW (node)->pixmap_closed);
+
+ if (GTK_CMCTREE_ROW (node)->mask_closed)
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
+ g_object_ref (GTK_CMCTREE_ROW (node)->mask_closed);
+ }
+
+ work = GTK_CMCTREE_ROW (node)->children;
+ if (work)
+ {
+ gint tmp = 0;
+ gint row;
+ GList *list;
+
+ while (work && GTK_CMCTREE_ROW (work)->level > level)
+ {
+ work = GTK_CMCTREE_NODE_NEXT (work);
+ tmp++;
+ }
+
+ if (work)
+ {
+ list = (GList *)node;
+ list->next = (GList *)work;
+ list = (GList *)GTK_CMCTREE_NODE_PREV (work);
+ list->next = NULL;
+ list = (GList *)work;
+ list->prev = (GList *)node;
+ }
+ else
+ {
+ list = (GList *)node;
+ list->next = NULL;
+ clist->row_list_end = (GList *)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;
+ CLIST_REFRESH (clist);
+ }
+ }
+ else if (visible && clist->column[ctree->tree_column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ /* resize tree_column if needed */
+ column_auto_resize (clist, >K_CMCTREE_ROW (node)->row, ctree->tree_column,
+ requisition.width);
+
+}
+
+static void
+column_auto_resize (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ gint old_width)
+{
+ /* resize column if needed for auto_resize */
+ GtkRequisition requisition;
+
+ if (!clist->column[column].auto_resize ||
+ GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ return;
+
+ if (clist_row)
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+ column, &requisition);
+ else
+ requisition.width = 0;
+
+ if (requisition.width > clist->column[column].width)
+ gtk_cmclist_set_column_width (clist, column, requisition.width);
+ else if (requisition.width < old_width &&
+ old_width == clist->column[column].width)
+ {
+ GList *list;
+ gint new_width;
+
+ /* run a "gtk_cmclist_optimal_column_width" but break, if
+ * the column doesn't shrink */
+ if (GTK_CMCLIST_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_CMCLIST_GET_CLASS (clist)->cell_size_request
+ (clist, GTK_CMCLIST_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_cmclist_set_column_width (clist, column, new_width);
+ }
+}
+
+static void
+auto_resize_columns (GtkCMCList *clist)
+{
+ gint i;
+
+ if (GTK_CMCLIST_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 (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ GtkRequisition *requisition)
+{
+ GtkCMCTree *ctree;
+ gint width;
+ gint height;
+ PangoLayout *layout;
+ PangoRectangle logical_rect;
+
+ g_return_if_fail (GTK_IS_CMCTREE (clist));
+ g_return_if_fail (requisition != NULL);
+
+ ctree = GTK_CMCTREE (clist);
+
+ layout = _gtk_cmclist_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)
+ {
+ case GTK_CMCELL_PIXTEXT:
+ if (GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap)
+ {
+ gdk_drawable_get_size (GTK_CMCELL_PIXTEXT
+ (clist_row->cell[column])->pixmap,
+ &width, &height);
+ width += GTK_CMCELL_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 *
+ (((GtkCMCTreeRow *) clist_row)->level - 1));
+ switch (ctree->expander_style)
+ {
+ case GTK_CMCTREE_EXPANDER_NONE:
+ break;
+ case GTK_CMCTREE_EXPANDER_TRIANGLE:
+ requisition->width += PM_SIZE + 3;
+ break;
+ case GTK_CMCTREE_EXPANDER_SQUARE:
+ case GTK_CMCTREE_EXPANDER_CIRCULAR:
+ requisition->width += PM_SIZE + 1;
+ break;
+ }
+ if (ctree->line_style == GTK_CMCTREE_LINES_TABBED)
+ requisition->width += 3;
+ }
+ break;
+ case GTK_CMCELL_PIXMAP:
+ gdk_drawable_get_size (GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap,
+ &width, &height);
+ requisition->width += width;
+ requisition->height = MAX (requisition->height, height);
+ break;
+ default:
+ break;
+ }
+
+ requisition->width += clist_row->cell[column].horizontal;
+ requisition->height += clist_row->cell[column].vertical;
+}
+
+static void
+set_cell_contents (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
+ gint column,
+ GtkCMCellType type,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask)
+{
+ gboolean visible = FALSE;
+ GtkCMCTree *ctree;
+ GtkRequisition requisition;
+ gchar *old_text = NULL;
+ GdkPixmap *old_pixmap = NULL;
+ GdkBitmap *old_mask = NULL;
+
+ g_return_if_fail (GTK_IS_CMCTREE (clist));
+ g_return_if_fail (clist_row != NULL);
+
+ ctree = GTK_CMCTREE (clist);
+
+ if (clist->column[column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ {
+ GtkCMCTreeNode *parent;
+
+ parent = ((GtkCMCTreeRow *)clist_row)->parent;
+ if (!parent || (parent && GTK_CMCTREE_ROW (parent)->expanded &&
+ gtk_cmctree_is_viewable (ctree, parent)))
+ {
+ visible = TRUE;
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+ column, &requisition);
+ }
+ }
+
+ switch (clist_row->cell[column].type)
+ {
+ case GTK_CMCELL_EMPTY:
+ break;
+ case GTK_CMCELL_TEXT:
+ old_text = GTK_CMCELL_TEXT (clist_row->cell[column])->text;
+ break;
+ case GTK_CMCELL_PIXMAP:
+ old_pixmap = GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap;
+ old_mask = GTK_CMCELL_PIXMAP (clist_row->cell[column])->mask;
+ break;
+ case GTK_CMCELL_PIXTEXT:
+ old_text = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text;
+ old_pixmap = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap;
+ old_mask = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask;
+ break;
+ case GTK_CMCELL_WIDGET:
+ /* unimplemented */
+ break;
+
+ default:
+ break;
+ }
+
+ clist_row->cell[column].type = GTK_CMCELL_EMPTY;
+ if (column == ctree->tree_column && type != GTK_CMCELL_EMPTY)
+ type = GTK_CMCELL_PIXTEXT;
+
+ /* Note that pixmap and mask were already ref'ed by the caller
+ */
+ switch (type)
+ {
+ case GTK_CMCELL_TEXT:
+ if (text)
+ {
+ clist_row->cell[column].type = GTK_CMCELL_TEXT;
+ GTK_CMCELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
+ }
+ break;
+ case GTK_CMCELL_PIXMAP:
+ if (pixmap)
+ {
+ clist_row->cell[column].type = GTK_CMCELL_PIXMAP;
+ GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
+ /* We set the mask even if it is NULL */
+ GTK_CMCELL_PIXMAP (clist_row->cell[column])->mask = mask;
+ }
+ break;
+ case GTK_CMCELL_PIXTEXT:
+ if (column == ctree->tree_column)
+ {
+ clist_row->cell[column].type = GTK_CMCELL_PIXTEXT;
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
+ if (text)
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
+ else
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text = NULL;
+ if (pixmap)
+ {
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask = mask;
+ }
+ else
+ {
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap = NULL;
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask = NULL;
+ }
+ }
+ else if (text && pixmap)
+ {
+ clist_row->cell[column].type = GTK_CMCELL_PIXTEXT;
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
+ GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask = mask;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (visible && clist->column[column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ column_auto_resize (clist, clist_row, column, requisition.width);
+
+ g_free (old_text);
+ if (old_pixmap)
+ g_object_unref (old_pixmap);
+ if (old_mask)
+ g_object_unref (old_mask);
+}
+
+static void
+set_node_info (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap_closed,
+ GdkBitmap *mask_closed,
+ GdkPixmap *pixmap_opened,
+ GdkBitmap *mask_opened,
+ gboolean is_leaf,
+ gboolean expanded)
+{
+ if (GTK_CMCTREE_ROW (node)->pixmap_opened)
+ {
+ g_object_unref (GTK_CMCTREE_ROW (node)->pixmap_opened);
+ if (GTK_CMCTREE_ROW (node)->mask_opened)
+ g_object_unref (GTK_CMCTREE_ROW (node)->mask_opened);
+ }
+ if (GTK_CMCTREE_ROW (node)->pixmap_closed)
+ {
+ g_object_unref (GTK_CMCTREE_ROW (node)->pixmap_closed);
+ if (GTK_CMCTREE_ROW (node)->mask_closed)
+ g_object_unref (GTK_CMCTREE_ROW (node)->mask_closed);
+ }
+
+ GTK_CMCTREE_ROW (node)->pixmap_opened = NULL;
+ GTK_CMCTREE_ROW (node)->mask_opened = NULL;
+ GTK_CMCTREE_ROW (node)->pixmap_closed = NULL;
+ GTK_CMCTREE_ROW (node)->mask_closed = NULL;
+
+ if (pixmap_closed)
+ {
+ GTK_CMCTREE_ROW (node)->pixmap_closed = g_object_ref (pixmap_closed);
+ if (mask_closed)
+ GTK_CMCTREE_ROW (node)->mask_closed = g_object_ref (mask_closed);
+ }
+ if (pixmap_opened)
+ {
+ GTK_CMCTREE_ROW (node)->pixmap_opened = g_object_ref (pixmap_opened);
+ if (mask_opened)
+ GTK_CMCTREE_ROW (node)->mask_opened = g_object_ref (mask_opened);
+ }
+
+ GTK_CMCTREE_ROW (node)->is_leaf = is_leaf;
+ GTK_CMCTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
+
+ if (GTK_CMCTREE_ROW (node)->expanded)
+ gtk_cmctree_node_set_pixtext (ctree, node, ctree->tree_column,
+ text, spacing, pixmap_opened, mask_opened);
+ else
+ gtk_cmctree_node_set_pixtext (ctree, node, ctree->tree_column,
+ text, spacing, pixmap_closed, mask_closed);
+}
+
+static void
+tree_delete (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ tree_unselect (ctree, node, NULL);
+ row_delete (ctree, GTK_CMCTREE_ROW (node));
+ g_list_free_1 ((GList *)node);
+}
+
+static void
+tree_delete_row (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ row_delete (ctree, GTK_CMCTREE_ROW (node));
+ g_list_free_1 ((GList *)node);
+}
+
+static void
+tree_update_level (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ if (!node)
+ return;
+
+ if (GTK_CMCTREE_ROW (node)->parent)
+ GTK_CMCTREE_ROW (node)->level =
+ GTK_CMCTREE_ROW (GTK_CMCTREE_ROW (node)->parent)->level + 1;
+ else
+ GTK_CMCTREE_ROW (node)->level = 1;
+}
+
+static void
+tree_select (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ if (node && GTK_CMCTREE_ROW (node)->row.state != GTK_STATE_SELECTED &&
+ GTK_CMCTREE_ROW (node)->row.selectable)
+ g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], 0,
+ node, -1);
+}
+
+static void
+tree_unselect (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ if (node && GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
+ g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW], 0,
+ node, -1);
+}
+
+static void
+tree_expand (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ if (node && !GTK_CMCTREE_ROW (node)->expanded)
+ g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], 0,node);
+}
+
+static void
+tree_collapse (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ if (node && GTK_CMCTREE_ROW (node)->expanded)
+ g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], 0,node);
+}
+
+static void
+tree_collapse_to_depth (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint depth)
+{
+ if (node && GTK_CMCTREE_ROW (node)->level == depth)
+ gtk_cmctree_collapse_recursive (ctree, node);
+}
+
+static void
+tree_toggle_expansion (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ if (!node)
+ return;
+
+ if (GTK_CMCTREE_ROW (node)->expanded)
+ g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], 0,node);
+ else
+ g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], 0,node);
+}
+
+static GtkCMCTreeRow *
+row_new (GtkCMCTree *ctree)
+{
+ GtkCMCList *clist;
+ GtkCMCTreeRow *ctree_row;
+ int i;
+
+ clist = GTK_CMCLIST (ctree);
+ ctree_row = g_slice_new (GtkCMCTreeRow);
+ ctree_row->row.cell = g_slice_alloc (sizeof (GtkCMCell) * clist->columns);
+
+ for (i = 0; i < clist->columns; i++)
+ {
+ ctree_row->row.cell[i].type = GTK_CMCELL_EMPTY;
+ ctree_row->row.cell[i].vertical = 0;
+ ctree_row->row.cell[i].horizontal = 0;
+ ctree_row->row.cell[i].style = NULL;
+ }
+
+ GTK_CMCELL_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.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;
+ ctree_row->parent = NULL;
+ ctree_row->sibling = NULL;
+ ctree_row->children = NULL;
+ ctree_row->pixmap_closed = NULL;
+ ctree_row->mask_closed = NULL;
+ ctree_row->pixmap_opened = NULL;
+ ctree_row->mask_opened = NULL;
+
+ return ctree_row;
+}
+
+static void
+row_delete (GtkCMCTree *ctree,
+ GtkCMCTreeRow *ctree_row)
+{
+ GtkCMCList *clist;
+ gint i;
+
+ clist = GTK_CMCLIST (ctree);
+
+ for (i = 0; i < clist->columns; i++)
+ {
+ GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+ (clist, &(ctree_row->row), i, GTK_CMCELL_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)
+ {
+ g_object_unref (ctree_row->pixmap_closed);
+ if (ctree_row->mask_closed)
+ g_object_unref (ctree_row->mask_closed);
+ }
+
+ if (ctree_row->pixmap_opened)
+ {
+ g_object_unref (ctree_row->pixmap_opened);
+ if (ctree_row->mask_opened)
+ g_object_unref (ctree_row->mask_opened);
+ }
+
+ if (ctree_row->row.destroy)
+ {
+ GtkDestroyNotify dnotify = ctree_row->row.destroy;
+ gpointer ddata = ctree_row->row.data;
+
+ ctree_row->row.destroy = NULL;
+ ctree_row->row.data = NULL;
+
+ dnotify (ddata);
+ }
+
+ g_slice_free1 (sizeof (GtkCMCell) * clist->columns, ctree_row->row.cell);
+ g_slice_free (GtkCMCTreeRow, ctree_row);
+}
+
+static void
+real_select_row (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event)
+{
+ GList *node;
+
+ g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+ if ((node = g_list_nth (clist->row_list, row)) &&
+ GTK_CMCTREE_ROW (node)->row.selectable)
+ g_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_SELECT_ROW],0,
+ node, column);
+}
+
+static void
+real_unselect_row (GtkCMCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event)
+{
+ GList *node;
+
+ g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+ if ((node = g_list_nth (clist->row_list, row)))
+ g_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_UNSELECT_ROW],0,
+ node, column);
+}
+
+static void
+real_tree_select (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column)
+{
+ GtkCMCList *clist;
+ GList *list;
+ GtkCMCTreeNode *sel_row;
+ gboolean node_selected;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ if (!node || GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
+ !GTK_CMCTREE_ROW (node)->row.selectable)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_SINGLE:
+ case GTK_SELECTION_BROWSE:
+
+ node_selected = FALSE;
+ list = clist->selection;
+
+ while (list)
+ {
+ sel_row = list->data;
+ list = list->next;
+
+ if (node == sel_row)
+ node_selected = TRUE;
+ else
+ g_signal_emit (GTK_OBJECT (ctree),
+ ctree_signals[TREE_UNSELECT_ROW], 0, sel_row, column);
+ }
+
+ if (node_selected)
+ return;
+
+ default:
+ break;
+ }
+
+ GTK_CMCTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
+
+ if (!clist->selection)
+ {
+ clist->selection = g_list_append (clist->selection, node);
+ clist->selection_end = clist->selection;
+ }
+ else
+ clist->selection_end = g_list_append (clist->selection_end, node)->next;
+
+ tree_draw_node (ctree, node);
+}
+
+static void
+real_tree_unselect (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column)
+{
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ if (!node || GTK_CMCTREE_ROW (node)->row.state != GTK_STATE_SELECTED)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (clist->selection_end && clist->selection_end->data == node)
+ clist->selection_end = clist->selection_end->prev;
+
+ clist->selection = g_list_remove (clist->selection, node);
+
+ GTK_CMCTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
+
+ tree_draw_node (ctree, node);
+}
+
+static void
+select_row_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ if (!node || GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
+ !GTK_CMCTREE_ROW (node)->row.selectable)
+ return;
+
+ GTK_CMCLIST (ctree)->undo_unselection =
+ g_list_prepend (GTK_CMCLIST (ctree)->undo_unselection, node);
+ gtk_cmctree_select (ctree, node);
+}
+
+static void
+real_select_all (GtkCMCList *clist)
+{
+ GtkCMCTree *ctree;
+ GtkCMCTreeNode *node;
+
+ g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+ ctree = GTK_CMCTREE (clist);
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_SINGLE:
+ case GTK_SELECTION_BROWSE:
+ return;
+
+ case GTK_SELECTION_MULTIPLE:
+
+ gtk_cmclist_freeze (clist);
+
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+
+ clist->anchor_state = GTK_STATE_SELECTED;
+ clist->anchor = -1;
+ clist->drag_pos = -1;
+ clist->undo_anchor = clist->focus_row;
+
+ for (node = GTK_CMCTREE_NODE (clist->row_list); node;
+ node = GTK_CMCTREE_NODE_NEXT (node))
+ gtk_cmctree_pre_recursive (ctree, node, select_row_recursive, NULL);
+
+ gtk_cmclist_thaw (clist);
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+}
+
+static void
+real_unselect_all (GtkCMCList *clist)
+{
+ GtkCMCTree *ctree;
+ GtkCMCTreeNode *node;
+ GList *list;
+
+ g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+ ctree = GTK_CMCTREE (clist);
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_BROWSE:
+ if (clist->focus_row >= 0)
+ {
+ gtk_cmctree_select
+ (ctree,
+ GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row)));
+ return;
+ }
+ break;
+
+ case GTK_SELECTION_MULTIPLE:
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+
+ clist->anchor = -1;
+ clist->drag_pos = -1;
+ clist->undo_anchor = clist->focus_row;
+ break;
+
+ default:
+ break;
+ }
+
+ list = clist->selection;
+
+ while (list)
+ {
+ node = list->data;
+ list = list->next;
+ gtk_cmctree_unselect (ctree, node);
+ }
+}
+
+static gboolean
+ctree_is_hot_spot (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint row,
+ gint x,
+ gint y)
+{
+ GtkCMCTreeRow *tree_row;
+ GtkCMCList *clist;
+ gint xl;
+ gint yu;
+
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (!clist->column[ctree->tree_column].visible ||
+ ctree->expander_style == GTK_CMCTREE_EXPANDER_NONE)
+ return FALSE;
+
+ tree_row = GTK_CMCTREE_ROW (node);
+
+ 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 - 1 + clist->hoffset -
+ (tree_row->level - 1) * ctree->tree_indent - PM_SIZE -
+ (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
+ else
+ xl = (clist->column[ctree->tree_column].area.x + clist->hoffset +
+ (tree_row->level - 1) * ctree->tree_indent +
+ (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
+
+ return (x >= xl && x <= xl + PM_SIZE && y >= yu && y <= yu + PM_SIZE);
+}
+
+/***********************************************************
+ ***********************************************************
+ *** Public interface ***
+ ***********************************************************
+ ***********************************************************/
+
+
+/***********************************************************
+ * Creation, insertion, deletion *
+ ***********************************************************/
+
+static GObject*
+gtk_cmctree_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object = G_OBJECT_CLASS (parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties);
+
+ return object;
+}
+
+GtkWidget*
+gtk_cmctree_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_widget_new (GTK_TYPE_CMCTREE,
+ "n_columns", columns,
+ "tree_column", tree_column,
+ NULL);
+ if (titles)
+ {
+ GtkCMCList *clist = GTK_CMCLIST (widget);
+ guint i;
+
+ for (i = 0; i < columns; i++)
+ gtk_cmclist_set_column_title (clist, i, titles[i]);
+ gtk_cmclist_column_titles_show (clist);
+ }
+
+ return widget;
+}
+
+GtkWidget *
+gtk_cmctree_new (gint columns,
+ gint tree_column)
+{
+ return gtk_cmctree_new_with_titles (columns, tree_column, NULL);
+}
+
+static gint
+real_insert_row (GtkCMCList *clist,
+ gint row,
+ gchar *text[])
+{
+ GtkCMCTreeNode *parent = NULL;
+ GtkCMCTreeNode *sibling;
+ GtkCMCTreeNode *node;
+
+ g_return_val_if_fail (GTK_IS_CMCTREE (clist), -1);
+
+ sibling = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, row));
+ if (sibling)
+ parent = GTK_CMCTREE_ROW (sibling)->parent;
+
+ node = gtk_cmctree_insert_node (GTK_CMCTREE (clist), parent, sibling, text, 5,
+ NULL, NULL, NULL, NULL, TRUE, FALSE);
+
+ if (GTK_CMCLIST_AUTO_SORT (clist) || !sibling)
+ return g_list_position (clist->row_list, (GList *) node);
+
+ return row;
+}
+
+GtkCMCTreeNode *
+gtk_cmctree_insert_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *sibling,
+ gchar *text[],
+ guint8 spacing,
+ GdkPixmap *pixmap_closed,
+ GdkBitmap *mask_closed,
+ GdkPixmap *pixmap_opened,
+ GdkBitmap *mask_opened,
+ gboolean is_leaf,
+ gboolean expanded)
+{
+ GtkCMCList *clist;
+ GtkCMCTreeRow *new_row;
+ GtkCMCTreeNode *node;
+ GList *list;
+ gint i;
+
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+ if (sibling)
+ g_return_val_if_fail (GTK_CMCTREE_ROW (sibling)->parent == parent, NULL);
+
+ if (parent && GTK_CMCTREE_ROW (parent)->is_leaf)
+ return NULL;
+
+ clist = GTK_CMCLIST (ctree);
+
+ /* create the row */
+ new_row = row_new (ctree);
+ list = g_list_alloc ();
+ list->data = new_row;
+ node = GTK_CMCTREE_NODE (list);
+
+ if (text)
+ for (i = 0; i < clist->columns; i++)
+ if (text[i] && i != ctree->tree_column)
+ GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+ (clist, &(new_row->row), i, GTK_CMCELL_TEXT, text[i], 0, NULL, NULL);
+
+ 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 (GTK_CMCLIST_AUTO_SORT (clist))
+ {
+ if (parent)
+ sibling = GTK_CMCTREE_ROW (parent)->children;
+ else
+ sibling = GTK_CMCTREE_NODE (clist->row_list);
+
+ while (sibling && clist->compare
+ (clist, GTK_CMCTREE_ROW (node), GTK_CMCTREE_ROW (sibling)) > 0)
+ sibling = GTK_CMCTREE_ROW (sibling)->sibling;
+ }
+
+ gtk_cmctree_link (ctree, node, parent, sibling, TRUE);
+
+ if (text && !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist) &&
+ gtk_cmctree_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_cmctree_select (ctree, node);
+ }
+
+
+ CLIST_REFRESH (clist);
+
+ return node;
+}
+
+GtkCMCTreeNode *
+gtk_cmctree_insert_gnode (GtkCMCTree *ctree,
+ GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *sibling,
+ GNode *gnode,
+ GtkCMCTreeGNodeFunc func,
+ gpointer data)
+{
+ GtkCMCList *clist;
+ GtkCMCTreeNode *cnode = NULL;
+ GtkCMCTreeNode *child = NULL;
+ GtkCMCTreeNode *new_child;
+ GList *list;
+ GNode *work;
+ guint depth = 1;
+
+ g_return_val_if_fail (GTK_IS_CMCTREE (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_CMCTREE_ROW (sibling)->parent == parent, NULL);
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (parent)
+ depth = GTK_CMCTREE_ROW (parent)->level + 1;
+
+ list = g_list_alloc ();
+ list->data = row_new (ctree);
+ cnode = GTK_CMCTREE_NODE (list);
+
+ gtk_cmclist_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_cmclist_thaw (clist);
+ return NULL;
+ }
+
+ if (GTK_CMCLIST_AUTO_SORT (clist))
+ {
+ if (parent)
+ sibling = GTK_CMCTREE_ROW (parent)->children;
+ else
+ sibling = GTK_CMCTREE_NODE (clist->row_list);
+
+ while (sibling && clist->compare
+ (clist, GTK_CMCTREE_ROW (cnode), GTK_CMCTREE_ROW (sibling)) > 0)
+ sibling = GTK_CMCTREE_ROW (sibling)->sibling;
+ }
+
+ gtk_cmctree_link (ctree, cnode, parent, sibling, TRUE);
+
+ for (work = g_node_last_child (gnode); work; work = work->prev)
+ {
+ new_child = gtk_cmctree_insert_gnode (ctree, cnode, child,
+ work, func, data);
+ if (new_child)
+ child = new_child;
+ }
+
+ gtk_cmclist_thaw (clist);
+
+ return cnode;
+}
+
+GNode *
+gtk_cmctree_export_to_gnode (GtkCMCTree *ctree,
+ GNode *parent,
+ GNode *sibling,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeGNodeFunc func,
+ gpointer data)
+{
+ GtkCMCTreeNode *work;
+ GNode *gnode;
+ gint depth;
+
+ g_return_val_if_fail (GTK_IS_CMCTREE (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_CMCTREE_ROW (node)->is_leaf)
+ {
+ GNode *new_sibling = NULL;
+
+ for (work = GTK_CMCTREE_ROW (node)->children; work;
+ work = GTK_CMCTREE_ROW (work)->sibling)
+ new_sibling = gtk_cmctree_export_to_gnode (ctree, gnode, new_sibling,
+ work, func, data);
+
+ g_node_reverse_children (gnode);
+ }
+
+ return gnode;
+}
+
+static void
+real_remove_row (GtkCMCList *clist,
+ gint row)
+{
+ GtkCMCTreeNode *node;
+
+ g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+ node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, row));
+
+ if (node)
+ gtk_cmctree_remove_node (GTK_CMCTREE (clist), node);
+}
+
+void
+gtk_cmctree_remove_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ clist = GTK_CMCLIST (ctree);
+
+ gtk_cmclist_freeze (clist);
+
+ if (node)
+ {
+ gtk_cmctree_unlink (ctree, node, TRUE);
+ gtk_cmctree_post_recursive (ctree, node, GTK_CMCTREE_FUNC (tree_delete),
+ NULL);
+ if (clist->selection_mode == GTK_SELECTION_BROWSE && !clist->selection &&
+ clist->focus_row >= 0)
+ gtk_cmclist_select_row (clist, clist->focus_row, -1);
+
+ auto_resize_columns (clist);
+ }
+ else
+ gtk_cmclist_clear (clist);
+
+ gtk_cmclist_thaw (clist);
+}
+
+static void
+real_clear (GtkCMCList *clist)
+{
+ GtkCMCTree *ctree;
+ GtkCMCTreeNode *work;
+ GtkCMCTreeNode *ptr;
+
+ g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+ ctree = GTK_CMCTREE (clist);
+
+ /* remove all rows */
+ work = GTK_CMCTREE_NODE (clist->row_list);
+ clist->row_list = NULL;
+ clist->row_list_end = NULL;
+
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+ while (work)
+ {
+ ptr = work;
+ work = GTK_CMCTREE_ROW (work)->sibling;
+ gtk_cmctree_post_recursive (ctree, ptr, GTK_CMCTREE_FUNC (tree_delete_row),
+ NULL);
+ }
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+
+ parent_class->clear (clist);
+}
+
+
+/***********************************************************
+ * Generic recursive functions, querying / finding tree *
+ * information *
+ ***********************************************************/
+
+
+void
+gtk_cmctree_post_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeFunc func,
+ gpointer data)
+{
+ GtkCMCTreeNode *work;
+ GtkCMCTreeNode *tmp;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (func != NULL);
+
+ if (node)
+ work = GTK_CMCTREE_ROW (node)->children;
+ else
+ work = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+ while (work)
+ {
+ tmp = GTK_CMCTREE_ROW (work)->sibling;
+ gtk_cmctree_post_recursive (ctree, work, func, data);
+ work = tmp;
+ }
+
+ if (node)
+ func (ctree, node, data);
+}
+
+void
+gtk_cmctree_post_recursive_to_depth (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint depth,
+ GtkCMCTreeFunc func,
+ gpointer data)
+{
+ GtkCMCTreeNode *work;
+ GtkCMCTreeNode *tmp;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (func != NULL);
+
+ if (depth < 0)
+ {
+ gtk_cmctree_post_recursive (ctree, node, func, data);
+ return;
+ }
+
+ if (node)
+ work = GTK_CMCTREE_ROW (node)->children;
+ else
+ work = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+ if (work && GTK_CMCTREE_ROW (work)->level <= depth)
+ {
+ while (work)
+ {
+ tmp = GTK_CMCTREE_ROW (work)->sibling;
+ gtk_cmctree_post_recursive_to_depth (ctree, work, depth, func, data);
+ work = tmp;
+ }
+ }
+
+ if (node && GTK_CMCTREE_ROW (node)->level <= depth)
+ func (ctree, node, data);
+}
+
+void
+gtk_cmctree_pre_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeFunc func,
+ gpointer data)
+{
+ GtkCMCTreeNode *work;
+ GtkCMCTreeNode *tmp;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (func != NULL);
+
+ if (node)
+ {
+ work = GTK_CMCTREE_ROW (node)->children;
+ func (ctree, node, data);
+ }
+ else
+ work = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+ while (work)
+ {
+ tmp = GTK_CMCTREE_ROW (work)->sibling;
+ gtk_cmctree_pre_recursive (ctree, work, func, data);
+ work = tmp;
+ }
+}
+
+void
+gtk_cmctree_pre_recursive_to_depth (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint depth,
+ GtkCMCTreeFunc func,
+ gpointer data)
+{
+ GtkCMCTreeNode *work;
+ GtkCMCTreeNode *tmp;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (func != NULL);
+
+ if (depth < 0)
+ {
+ gtk_cmctree_pre_recursive (ctree, node, func, data);
+ return;
+ }
+
+ if (node)
+ {
+ work = GTK_CMCTREE_ROW (node)->children;
+ if (GTK_CMCTREE_ROW (node)->level <= depth)
+ func (ctree, node, data);
+ }
+ else
+ work = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+ if (work && GTK_CMCTREE_ROW (work)->level <= depth)
+ {
+ while (work)
+ {
+ tmp = GTK_CMCTREE_ROW (work)->sibling;
+ gtk_cmctree_pre_recursive_to_depth (ctree, work, depth, func, data);
+ work = tmp;
+ }
+ }
+}
+
+gboolean
+gtk_cmctree_is_viewable (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ GtkCMCTreeRow *work;
+
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ work = GTK_CMCTREE_ROW (node);
+
+ while (work->parent && GTK_CMCTREE_ROW (work->parent)->expanded)
+ work = GTK_CMCTREE_ROW (work->parent);
+
+ if (!work->parent)
+ return TRUE;
+
+ return FALSE;
+}
+
+GtkCMCTreeNode *
+gtk_cmctree_last (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+
+ if (!node)
+ return NULL;
+
+ while (GTK_CMCTREE_ROW (node)->sibling)
+ node = GTK_CMCTREE_ROW (node)->sibling;
+
+ if (GTK_CMCTREE_ROW (node)->children)
+ return gtk_cmctree_last (ctree, GTK_CMCTREE_ROW (node)->children);
+
+ return node;
+}
+
+GtkCMCTreeNode *
+gtk_cmctree_find_node_ptr (GtkCMCTree *ctree,
+ GtkCMCTreeRow *ctree_row)
+{
+ GtkCMCTreeNode *node;
+
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+ g_return_val_if_fail (ctree_row != NULL, NULL);
+
+ if (ctree_row->parent)
+ node = GTK_CMCTREE_ROW (ctree_row->parent)->children;
+ else
+ node = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+ while (GTK_CMCTREE_ROW (node) != ctree_row)
+ node = GTK_CMCTREE_ROW (node)->sibling;
+
+ return node;
+}
+
+GtkCMCTreeNode *
+gtk_cmctree_node_nth (GtkCMCTree *ctree,
+ guint row)
+{
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+
+ if ((row >= GTK_CMCLIST(ctree)->rows))
+ return NULL;
+
+ return GTK_CMCTREE_NODE (g_list_nth (GTK_CMCLIST (ctree)->row_list, row));
+}
+
+gboolean
+gtk_cmctree_find (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *child)
+{
+ if (!child)
+ return FALSE;
+
+ if (!node)
+ node = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+ while (node)
+ {
+ if (node == child)
+ return TRUE;
+ if (GTK_CMCTREE_ROW (node)->children)
+ {
+ if (gtk_cmctree_find (ctree, GTK_CMCTREE_ROW (node)->children, child))
+ return TRUE;
+ }
+ node = GTK_CMCTREE_ROW (node)->sibling;
+ }
+ return FALSE;
+}
+
+gboolean
+gtk_cmctree_is_ancestor (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *child)
+{
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ if (GTK_CMCTREE_ROW (node)->children)
+ return gtk_cmctree_find (ctree, GTK_CMCTREE_ROW (node)->children, child);
+
+ return FALSE;
+}
+
+GtkCMCTreeNode *
+gtk_cmctree_find_by_row_data (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ GtkCMCTreeNode *work;
+
+ if (!node)
+ node = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+ while (node)
+ {
+ if (GTK_CMCTREE_ROW (node)->row.data == data)
+ return node;
+ if (GTK_CMCTREE_ROW (node)->children &&
+ (work = gtk_cmctree_find_by_row_data
+ (ctree, GTK_CMCTREE_ROW (node)->children, data)))
+ return work;
+ node = GTK_CMCTREE_ROW (node)->sibling;
+ }
+ return NULL;
+}
+
+GList *
+gtk_cmctree_find_all_by_row_data (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ GList *list = NULL;
+
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+
+ /* if node == NULL then look in the whole tree */
+ if (!node)
+ node = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+ while (node)
+ {
+ if (GTK_CMCTREE_ROW (node)->row.data == data)
+ list = g_list_append (list, node);
+
+ if (GTK_CMCTREE_ROW (node)->children)
+ {
+ GList *sub_list;
+
+ sub_list = gtk_cmctree_find_all_by_row_data (ctree,
+ GTK_CMCTREE_ROW
+ (node)->children,
+ data);
+ list = g_list_concat (list, sub_list);
+ }
+ node = GTK_CMCTREE_ROW (node)->sibling;
+ }
+ return list;
+}
+
+GtkCMCTreeNode *
+gtk_cmctree_find_by_row_data_custom (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data,
+ GCompareFunc func)
+{
+ GtkCMCTreeNode *work;
+
+ g_return_val_if_fail (func != NULL, NULL);
+
+ if (!node)
+ node = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+ while (node)
+ {
+ if (!func (GTK_CMCTREE_ROW (node)->row.data, data))
+ return node;
+ if (GTK_CMCTREE_ROW (node)->children &&
+ (work = gtk_cmctree_find_by_row_data_custom
+ (ctree, GTK_CMCTREE_ROW (node)->children, data, func)))
+ return work;
+ node = GTK_CMCTREE_ROW (node)->sibling;
+ }
+ return NULL;
+}
+
+GList *
+gtk_cmctree_find_all_by_row_data_custom (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data,
+ GCompareFunc func)
+{
+ GList *list = NULL;
+
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+ g_return_val_if_fail (func != NULL, NULL);
+
+ /* if node == NULL then look in the whole tree */
+ if (!node)
+ node = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+ while (node)
+ {
+ if (!func (GTK_CMCTREE_ROW (node)->row.data, data))
+ list = g_list_append (list, node);
+
+ if (GTK_CMCTREE_ROW (node)->children)
+ {
+ GList *sub_list;
+
+ sub_list = gtk_cmctree_find_all_by_row_data_custom (ctree,
+ GTK_CMCTREE_ROW
+ (node)->children,
+ data,
+ func);
+ list = g_list_concat (list, sub_list);
+ }
+ node = GTK_CMCTREE_ROW (node)->sibling;
+ }
+ return list;
+}
+
+gboolean
+gtk_cmctree_is_hot_spot (GtkCMCTree *ctree,
+ gint x,
+ gint y)
+{
+ GtkCMCTreeNode *node;
+ gint column;
+ gint row;
+
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+
+ if (gtk_cmclist_get_selection_info (GTK_CMCLIST (ctree), x, y, &row, &column))
+ if ((node = GTK_CMCTREE_NODE(g_list_nth (GTK_CMCLIST (ctree)->row_list, row))))
+ return ctree_is_hot_spot (ctree, node, row, x, y);
+
+ return FALSE;
+}
+
+
+/***********************************************************
+ * Tree signals : move, expand, collapse, (un)select *
+ ***********************************************************/
+
+
+void
+gtk_cmctree_move (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *new_parent,
+ GtkCMCTreeNode *new_sibling)
+{
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_MOVE], 0, node,
+ new_parent, new_sibling);
+}
+
+void
+gtk_cmctree_expand (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ if (GTK_CMCTREE_ROW (node)->is_leaf)
+ return;
+
+ g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], 0, node);
+}
+
+void
+gtk_cmctree_expand_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ GtkCMCList *clist;
+ gboolean thaw = FALSE;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (node && GTK_CMCTREE_ROW (node)->is_leaf)
+ return;
+
+ if (CLIST_UNFROZEN (clist) && (!node || gtk_cmctree_is_viewable (ctree, node)))
+ {
+ gtk_cmclist_freeze (clist);
+ thaw = TRUE;
+ }
+
+ gtk_cmctree_post_recursive (ctree, node, GTK_CMCTREE_FUNC (tree_expand), NULL);
+
+ if (thaw)
+ gtk_cmclist_thaw (clist);
+}
+
+void
+gtk_cmctree_expand_to_depth (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint depth)
+{
+ GtkCMCList *clist;
+ gboolean thaw = FALSE;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (node && GTK_CMCTREE_ROW (node)->is_leaf)
+ return;
+
+ if (CLIST_UNFROZEN (clist) && (!node || gtk_cmctree_is_viewable (ctree, node)))
+ {
+ gtk_cmclist_freeze (clist);
+ thaw = TRUE;
+ }
+
+ gtk_cmctree_post_recursive_to_depth (ctree, node, depth,
+ GTK_CMCTREE_FUNC (tree_expand), NULL);
+
+ if (thaw)
+ gtk_cmclist_thaw (clist);
+}
+
+void
+gtk_cmctree_collapse (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ if (GTK_CMCTREE_ROW (node)->is_leaf)
+ return;
+
+ g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], 0, node);
+}
+
+void
+gtk_cmctree_collapse_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ GtkCMCList *clist;
+ gboolean thaw = FALSE;
+ gint i;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ if (node && GTK_CMCTREE_ROW (node)->is_leaf)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (CLIST_UNFROZEN (clist) && (!node || gtk_cmctree_is_viewable (ctree, node)))
+ {
+ gtk_cmclist_freeze (clist);
+ thaw = TRUE;
+ }
+
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+ gtk_cmctree_post_recursive (ctree, node, GTK_CMCTREE_FUNC (tree_collapse), NULL);
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].auto_resize)
+ gtk_cmclist_set_column_width (clist, i,
+ gtk_cmclist_optimal_column_width (clist, i));
+
+ if (thaw)
+ gtk_cmclist_thaw (clist);
+}
+
+void
+gtk_cmctree_collapse_to_depth (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint depth)
+{
+ GtkCMCList *clist;
+ gboolean thaw = FALSE;
+ gint i;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ if (node && GTK_CMCTREE_ROW (node)->is_leaf)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (CLIST_UNFROZEN (clist) && (!node || gtk_cmctree_is_viewable (ctree, node)))
+ {
+ gtk_cmclist_freeze (clist);
+ thaw = TRUE;
+ }
+
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+ gtk_cmctree_post_recursive_to_depth (ctree, node, depth,
+ GTK_CMCTREE_FUNC (tree_collapse_to_depth),
+ GINT_TO_POINTER (depth));
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].auto_resize)
+ gtk_cmclist_set_column_width (clist, i,
+ gtk_cmclist_optimal_column_width (clist, i));
+
+ if (thaw)
+ gtk_cmclist_thaw (clist);
+}
+
+void
+gtk_cmctree_toggle_expansion (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ if (GTK_CMCTREE_ROW (node)->is_leaf)
+ return;
+
+ tree_toggle_expansion (ctree, node, NULL);
+}
+
+void
+gtk_cmctree_toggle_expansion_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ GtkCMCList *clist;
+ gboolean thaw = FALSE;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ if (node && GTK_CMCTREE_ROW (node)->is_leaf)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (CLIST_UNFROZEN (clist) && (!node || gtk_cmctree_is_viewable (ctree, node)))
+ {
+ gtk_cmclist_freeze (clist);
+ thaw = TRUE;
+ }
+
+ gtk_cmctree_post_recursive (ctree, node,
+ GTK_CMCTREE_FUNC (tree_toggle_expansion), NULL);
+
+ if (thaw)
+ gtk_cmclist_thaw (clist);
+}
+
+void
+gtk_cmctree_select (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ if (GTK_CMCTREE_ROW (node)->row.selectable)
+ g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], 0,
+ node, -1);
+}
+
+void
+gtk_cmctree_unselect (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW], 0,
+ node, -1);
+}
+
+void
+gtk_cmctree_select_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ gtk_cmctree_real_select_recursive (ctree, node, TRUE);
+}
+
+void
+gtk_cmctree_unselect_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ gtk_cmctree_real_select_recursive (ctree, node, FALSE);
+}
+
+void
+gtk_cmctree_real_select_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint state)
+{
+ GtkCMCList *clist;
+ gboolean thaw = FALSE;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ clist = GTK_CMCLIST (ctree);
+
+ if ((state &&
+ (clist->selection_mode == GTK_SELECTION_BROWSE ||
+ clist->selection_mode == GTK_SELECTION_SINGLE)) ||
+ (!state && clist->selection_mode == GTK_SELECTION_BROWSE))
+ return;
+
+ if (CLIST_UNFROZEN (clist) && (!node || gtk_cmctree_is_viewable (ctree, node)))
+ {
+ gtk_cmclist_freeze (clist);
+ thaw = TRUE;
+ }
+
+ if (clist->selection_mode == GTK_SELECTION_MULTIPLE)
+ {
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+ }
+
+ if (state)
+ gtk_cmctree_post_recursive (ctree, node,
+ GTK_CMCTREE_FUNC (tree_select), NULL);
+ else
+ gtk_cmctree_post_recursive (ctree, node,
+ GTK_CMCTREE_FUNC (tree_unselect), NULL);
+
+ if (thaw)
+ gtk_cmclist_thaw (clist);
+}
+
+
+/***********************************************************
+ * Analogons of GtkCMCList functions *
+ ***********************************************************/
+
+
+void
+gtk_cmctree_node_set_text (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ const gchar *text)
+{
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+ (clist, &(GTK_CMCTREE_ROW (node)->row), column, GTK_CMCELL_TEXT,
+ text, 0, NULL, NULL);
+
+ tree_draw_node (ctree, node);
+}
+
+void
+gtk_cmctree_node_set_pixmap (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask)
+{
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+ g_return_if_fail (pixmap != NULL);
+
+ if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+ return;
+
+ g_object_ref (pixmap);
+ if (mask)
+ g_object_ref (mask);
+
+ clist = GTK_CMCLIST (ctree);
+
+ GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+ (clist, &(GTK_CMCTREE_ROW (node)->row), column, GTK_CMCELL_PIXMAP,
+ NULL, 0, pixmap, mask);
+
+ tree_draw_node (ctree, node);
+}
+
+void
+gtk_cmctree_node_set_pixtext (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask)
+{
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+ if (column != ctree->tree_column)
+ g_return_if_fail (pixmap != NULL);
+ if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (pixmap)
+ {
+ g_object_ref (pixmap);
+ if (mask)
+ g_object_ref (mask);
+ }
+
+ GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+ (clist, &(GTK_CMCTREE_ROW (node)->row), column, GTK_CMCELL_PIXTEXT,
+ text, spacing, pixmap, mask);
+
+ tree_draw_node (ctree, node);
+}
+
+void
+gtk_cmctree_set_node_info (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap_closed,
+ GdkBitmap *mask_closed,
+ GdkPixmap *pixmap_opened,
+ GdkBitmap *mask_opened,
+ gboolean is_leaf,
+ gboolean expanded)
+{
+ gboolean old_leaf;
+ gboolean old_expanded;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ old_leaf = GTK_CMCTREE_ROW (node)->is_leaf;
+ old_expanded = GTK_CMCTREE_ROW (node)->expanded;
+
+ if (is_leaf && GTK_CMCTREE_ROW (node)->children)
+ {
+ GtkCMCTreeNode *work;
+ GtkCMCTreeNode *ptr;
+
+ work = GTK_CMCTREE_ROW (node)->children;
+ while (work)
+ {
+ ptr = work;
+ work = GTK_CMCTREE_ROW (work)->sibling;
+ gtk_cmctree_remove_node (ctree, ptr);
+ }
+ }
+
+ set_node_info (ctree, node, text, spacing, pixmap_closed, mask_closed,
+ pixmap_opened, mask_opened, is_leaf, expanded);
+
+ if (!is_leaf && !old_leaf)
+ {
+ GTK_CMCTREE_ROW (node)->expanded = old_expanded;
+ if (expanded && !old_expanded)
+ gtk_cmctree_expand (ctree, node);
+ else if (!expanded && old_expanded)
+ gtk_cmctree_collapse (ctree, node);
+ }
+
+ GTK_CMCTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
+
+ tree_draw_node (ctree, node);
+}
+
+void
+gtk_cmctree_node_set_shift (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ gint vertical,
+ gint horizontal)
+{
+ GtkCMCList *clist;
+ GtkRequisition requisition;
+ gboolean visible = FALSE;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (clist->column[column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ {
+ visible = gtk_cmctree_is_viewable (ctree, node);
+ if (visible)
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+ (clist, >K_CMCTREE_ROW (node)->row, column, &requisition);
+ }
+
+ GTK_CMCTREE_ROW (node)->row.cell[column].vertical = vertical;
+ GTK_CMCTREE_ROW (node)->row.cell[column].horizontal = horizontal;
+
+ if (visible)
+ column_auto_resize (clist, >K_CMCTREE_ROW (node)->row,
+ column, requisition.width);
+
+ tree_draw_node (ctree, node);
+}
+
+static void
+remove_grab (GtkCMCList *clist)
+{
+ if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))) &&
+ GTK_WIDGET_HAS_GRAB (clist))
+ {
+ gtk_grab_remove (GTK_WIDGET (clist));
+ gdk_display_pointer_ungrab (gtk_widget_get_display (GTK_WIDGET (clist)),
+ GDK_CURRENT_TIME);
+ }
+
+ if (clist->htimer)
+ {
+ g_source_remove (clist->htimer);
+ clist->htimer = 0;
+ }
+
+ if (clist->vtimer)
+ {
+ g_source_remove (clist->vtimer);
+ clist->vtimer = 0;
+ }
+}
+
+void
+gtk_cmctree_node_set_selectable (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gboolean selectable)
+{
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ if (selectable == GTK_CMCTREE_ROW (node)->row.selectable)
+ return;
+
+ GTK_CMCTREE_ROW (node)->row.selectable = selectable;
+
+ if (!selectable && GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
+ {
+ GtkCMCList *clist;
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (clist->anchor >= 0 &&
+ clist->selection_mode == GTK_SELECTION_MULTIPLE)
+ {
+ clist->drag_button = 0;
+ remove_grab (clist);
+
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+ }
+ gtk_cmctree_unselect (ctree, node);
+ }
+}
+
+gboolean
+gtk_cmctree_node_get_selectable (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ return GTK_CMCTREE_ROW (node)->row.selectable;
+}
+
+GtkCMCellType
+gtk_cmctree_node_get_cell_type (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column)
+{
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), -1);
+ g_return_val_if_fail (node != NULL, -1);
+
+ if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+ return -1;
+
+ return GTK_CMCTREE_ROW (node)->row.cell[column].type;
+}
+
+gboolean
+gtk_cmctree_node_get_text (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ gchar **text)
+{
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+ return FALSE;
+
+ if (GTK_CMCTREE_ROW (node)->row.cell[column].type != GTK_CMCELL_TEXT)
+ return FALSE;
+
+ if (text)
+ *text = GTK_CMCELL_TEXT (GTK_CMCTREE_ROW (node)->row.cell[column])->text;
+
+ return TRUE;
+}
+
+gboolean
+gtk_cmctree_node_get_pixmap (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ GdkPixmap **pixmap,
+ GdkBitmap **mask)
+{
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+ return FALSE;
+
+ if (GTK_CMCTREE_ROW (node)->row.cell[column].type != GTK_CMCELL_PIXMAP)
+ return FALSE;
+
+ if (pixmap)
+ *pixmap = GTK_CMCELL_PIXMAP (GTK_CMCTREE_ROW (node)->row.cell[column])->pixmap;
+ if (mask)
+ *mask = GTK_CMCELL_PIXMAP (GTK_CMCTREE_ROW (node)->row.cell[column])->mask;
+
+ return TRUE;
+}
+
+gboolean
+gtk_cmctree_node_get_pixtext (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ gchar **text,
+ guint8 *spacing,
+ GdkPixmap **pixmap,
+ GdkBitmap **mask)
+{
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+ return FALSE;
+
+ if (GTK_CMCTREE_ROW (node)->row.cell[column].type != GTK_CMCELL_PIXTEXT)
+ return FALSE;
+
+ if (text)
+ *text = GTK_CMCELL_PIXTEXT (GTK_CMCTREE_ROW (node)->row.cell[column])->text;
+ if (spacing)
+ *spacing = GTK_CMCELL_PIXTEXT (GTK_CMCTREE_ROW
+ (node)->row.cell[column])->spacing;
+ if (pixmap)
+ *pixmap = GTK_CMCELL_PIXTEXT (GTK_CMCTREE_ROW
+ (node)->row.cell[column])->pixmap;
+ if (mask)
+ *mask = GTK_CMCELL_PIXTEXT (GTK_CMCTREE_ROW (node)->row.cell[column])->mask;
+
+ return TRUE;
+}
+
+gboolean
+gtk_cmctree_get_node_info (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gchar **text,
+ guint8 *spacing,
+ GdkPixmap **pixmap_closed,
+ GdkBitmap **mask_closed,
+ GdkPixmap **pixmap_opened,
+ GdkBitmap **mask_opened,
+ gboolean *is_leaf,
+ gboolean *expanded)
+{
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ if (text)
+ *text = GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->text;
+ if (spacing)
+ *spacing = GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->spacing;
+ if (pixmap_closed)
+ *pixmap_closed = GTK_CMCTREE_ROW (node)->pixmap_closed;
+ if (mask_closed)
+ *mask_closed = GTK_CMCTREE_ROW (node)->mask_closed;
+ if (pixmap_opened)
+ *pixmap_opened = GTK_CMCTREE_ROW (node)->pixmap_opened;
+ if (mask_opened)
+ *mask_opened = GTK_CMCTREE_ROW (node)->mask_opened;
+ if (is_leaf)
+ *is_leaf = GTK_CMCTREE_ROW (node)->is_leaf;
+ if (expanded)
+ *expanded = GTK_CMCTREE_ROW (node)->expanded;
+
+ return TRUE;
+}
+
+void
+gtk_cmctree_node_set_cell_style (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ GtkStyle *style)
+{
+ GtkCMCList *clist;
+ GtkRequisition requisition;
+ gboolean visible = FALSE;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (column < 0 || column >= clist->columns)
+ return;
+
+ if (GTK_CMCTREE_ROW (node)->row.cell[column].style == style)
+ return;
+
+ if (clist->column[column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ {
+ visible = gtk_cmctree_is_viewable (ctree, node);
+ if (visible)
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+ (clist, >K_CMCTREE_ROW (node)->row, column, &requisition);
+ }
+
+ if (GTK_CMCTREE_ROW (node)->row.cell[column].style)
+ {
+ if (GTK_WIDGET_REALIZED (ctree))
+ gtk_style_detach (GTK_CMCTREE_ROW (node)->row.cell[column].style);
+ g_object_unref (GTK_CMCTREE_ROW (node)->row.cell[column].style);
+ }
+
+ GTK_CMCTREE_ROW (node)->row.cell[column].style = style;
+
+ if (GTK_CMCTREE_ROW (node)->row.cell[column].style)
+ {
+ g_object_ref (GTK_CMCTREE_ROW (node)->row.cell[column].style);
+
+ if (GTK_WIDGET_REALIZED (ctree))
+ GTK_CMCTREE_ROW (node)->row.cell[column].style =
+ gtk_style_attach (GTK_CMCTREE_ROW (node)->row.cell[column].style,
+ clist->clist_window);
+ }
+
+ if (visible)
+ column_auto_resize (clist, >K_CMCTREE_ROW (node)->row, column,
+ requisition.width);
+
+ tree_draw_node (ctree, node);
+}
+
+GtkStyle *
+gtk_cmctree_node_get_cell_style (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column)
+{
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+ g_return_val_if_fail (node != NULL, NULL);
+
+ if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+ return NULL;
+
+ return GTK_CMCTREE_ROW (node)->row.cell[column].style;
+}
+
+void
+gtk_cmctree_node_set_row_style (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkStyle *style)
+{
+ GtkCMCList *clist;
+ GtkRequisition requisition;
+ gboolean visible;
+ gint *old_width = NULL;
+ gint i;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (GTK_CMCTREE_ROW (node)->row.style == style)
+ return;
+
+ visible = gtk_cmctree_is_viewable (ctree, node);
+ if (visible && !GTK_CMCLIST_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_CMCLIST_GET_CLASS (clist)->cell_size_request
+ (clist, >K_CMCTREE_ROW (node)->row, i, &requisition);
+ old_width[i] = requisition.width;
+ }
+ }
+
+ if (GTK_CMCTREE_ROW (node)->row.style)
+ {
+ if (GTK_WIDGET_REALIZED (ctree))
+ gtk_style_detach (GTK_CMCTREE_ROW (node)->row.style);
+ g_object_unref (GTK_CMCTREE_ROW (node)->row.style);
+ }
+
+ GTK_CMCTREE_ROW (node)->row.style = style;
+
+ if (GTK_CMCTREE_ROW (node)->row.style)
+ {
+ g_object_ref (GTK_CMCTREE_ROW (node)->row.style);
+
+ if (GTK_WIDGET_REALIZED (ctree))
+ GTK_CMCTREE_ROW (node)->row.style =
+ gtk_style_attach (GTK_CMCTREE_ROW (node)->row.style,
+ clist->clist_window);
+ }
+
+ if (visible && !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ {
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].auto_resize)
+ column_auto_resize (clist, >K_CMCTREE_ROW (node)->row, i,
+ old_width[i]);
+ g_free (old_width);
+ }
+ tree_draw_node (ctree, node);
+}
+
+GtkStyle *
+gtk_cmctree_node_get_row_style (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+ g_return_val_if_fail (node != NULL, NULL);
+
+ return GTK_CMCTREE_ROW (node)->row.style;
+}
+
+void
+gtk_cmctree_node_set_foreground (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ const GdkColor *color)
+{
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ if (color)
+ {
+ GTK_CMCTREE_ROW (node)->row.foreground = *color;
+ GTK_CMCTREE_ROW (node)->row.fg_set = TRUE;
+ if (GTK_WIDGET_REALIZED (ctree))
+ gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (ctree)),
+ >K_CMCTREE_ROW (node)->row.foreground, TRUE, TRUE);
+ }
+ else
+ GTK_CMCTREE_ROW (node)->row.fg_set = FALSE;
+
+ tree_draw_node (ctree, node);
+}
+
+void
+gtk_cmctree_node_set_background (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ const GdkColor *color)
+{
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ if (color)
+ {
+ GTK_CMCTREE_ROW (node)->row.background = *color;
+ GTK_CMCTREE_ROW (node)->row.bg_set = TRUE;
+ if (GTK_WIDGET_REALIZED (ctree))
+ gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (ctree)),
+ >K_CMCTREE_ROW (node)->row.background, TRUE, TRUE);
+ }
+ else
+ GTK_CMCTREE_ROW (node)->row.bg_set = FALSE;
+
+ tree_draw_node (ctree, node);
+}
+
+void
+gtk_cmctree_node_set_row_data (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ gtk_cmctree_node_set_row_data_full (ctree, node, data, NULL);
+}
+
+void
+gtk_cmctree_node_set_row_data_full (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data,
+ GtkDestroyNotify destroy)
+{
+ GtkDestroyNotify dnotify;
+ gpointer ddata;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (node != NULL);
+
+ dnotify = GTK_CMCTREE_ROW (node)->row.destroy;
+ ddata = GTK_CMCTREE_ROW (node)->row.data;
+
+ GTK_CMCTREE_ROW (node)->row.data = data;
+ GTK_CMCTREE_ROW (node)->row.destroy = destroy;
+
+ if (dnotify)
+ dnotify (ddata);
+}
+
+gpointer
+gtk_cmctree_node_get_row_data (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+
+ return node ? GTK_CMCTREE_ROW (node)->row.data : NULL;
+}
+
+void
+gtk_cmctree_node_moveto (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ gfloat row_align,
+ gfloat col_align)
+{
+ gint row = -1;
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ clist = GTK_CMCLIST (ctree);
+
+ while (node && !gtk_cmctree_is_viewable (ctree, node))
+ node = GTK_CMCTREE_ROW (node)->parent;
+
+ if (node)
+ row = g_list_position (clist->row_list, (GList *)node);
+
+ gtk_cmclist_moveto (clist, row, column, row_align, col_align);
+}
+
+GtkVisibility
+gtk_cmctree_node_is_visible (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ gint row;
+
+ g_return_val_if_fail (ctree != NULL, 0);
+ g_return_val_if_fail (node != NULL, 0);
+
+ row = g_list_position (GTK_CMCLIST (ctree)->row_list, (GList*) node);
+ return gtk_cmclist_row_is_visible (GTK_CMCLIST (ctree), row);
+}
+
+
+/***********************************************************
+ * GtkCMCTree specific functions *
+ ***********************************************************/
+
+void
+gtk_cmctree_set_indent (GtkCMCTree *ctree,
+ gint indent)
+{
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (indent >= 0);
+
+ if (indent == ctree->tree_indent)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+ ctree->tree_indent = indent;
+
+ if (clist->column[ctree->tree_column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ gtk_cmclist_set_column_width
+ (clist, ctree->tree_column,
+ gtk_cmclist_optimal_column_width (clist, ctree->tree_column));
+ else
+ CLIST_REFRESH (ctree);
+}
+
+void
+gtk_cmctree_set_spacing (GtkCMCTree *ctree,
+ gint spacing)
+{
+ GtkCMCList *clist;
+ gint old_spacing;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+ g_return_if_fail (spacing >= 0);
+
+ if (spacing == ctree->tree_spacing)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ old_spacing = ctree->tree_spacing;
+ ctree->tree_spacing = spacing;
+
+ if (clist->column[ctree->tree_column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ gtk_cmclist_set_column_width (clist, ctree->tree_column,
+ clist->column[ctree->tree_column].width +
+ spacing - old_spacing);
+ else
+ CLIST_REFRESH (ctree);
+}
+
+void
+gtk_cmctree_set_show_stub (GtkCMCTree *ctree,
+ gboolean show_stub)
+{
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ show_stub = show_stub != FALSE;
+
+ if (show_stub != ctree->show_stub)
+ {
+ GtkCMCList *clist;
+
+ clist = GTK_CMCLIST (ctree);
+ ctree->show_stub = show_stub;
+
+ if (CLIST_UNFROZEN (clist) && clist->rows &&
+ gtk_cmclist_row_is_visible (clist, 0) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row
+ (clist, NULL, 0, GTK_CMCLIST_ROW (clist->row_list));
+ }
+}
+
+void
+gtk_cmctree_set_line_style (GtkCMCTree *ctree,
+ GtkCMCTreeLineStyle line_style)
+{
+ GtkCMCList *clist;
+ GtkCMCTreeLineStyle old_style;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ if (line_style == ctree->line_style)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ old_style = ctree->line_style;
+ ctree->line_style = line_style;
+
+ if (clist->column[ctree->tree_column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ {
+ if (old_style == GTK_CMCTREE_LINES_TABBED)
+ gtk_cmclist_set_column_width
+ (clist, ctree->tree_column,
+ clist->column[ctree->tree_column].width - 3);
+ else if (line_style == GTK_CMCTREE_LINES_TABBED)
+ gtk_cmclist_set_column_width
+ (clist, ctree->tree_column,
+ clist->column[ctree->tree_column].width + 3);
+ }
+
+ if (GTK_WIDGET_REALIZED (ctree))
+ {
+ switch (line_style)
+ {
+ case GTK_CMCTREE_LINES_SOLID:
+ if (GTK_WIDGET_REALIZED (ctree))
+ gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
+ GDK_CAP_BUTT, GDK_JOIN_MITER);
+ break;
+ case GTK_CMCTREE_LINES_DOTTED:
+ if (GTK_WIDGET_REALIZED (ctree))
+ gdk_gc_set_line_attributes (ctree->lines_gc, 1,
+ 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_CMCTREE_LINES_TABBED:
+ if (GTK_WIDGET_REALIZED (ctree))
+ gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
+ GDK_CAP_BUTT, GDK_JOIN_MITER);
+ break;
+ case GTK_CMCTREE_LINES_NONE:
+ break;
+ default:
+ return;
+ }
+ CLIST_REFRESH (ctree);
+ }
+}
+
+void
+gtk_cmctree_set_expander_style (GtkCMCTree *ctree,
+ GtkCMCTreeExpanderStyle expander_style)
+{
+ GtkCMCList *clist;
+ GtkCMCTreeExpanderStyle old_style;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ if (expander_style == ctree->expander_style)
+ return;
+
+ clist = GTK_CMCLIST (ctree);
+
+ old_style = ctree->expander_style;
+ ctree->expander_style = expander_style;
+
+ if (clist->column[ctree->tree_column].auto_resize &&
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ {
+ gint new_width;
+
+ new_width = clist->column[ctree->tree_column].width;
+ switch (old_style)
+ {
+ case GTK_CMCTREE_EXPANDER_NONE:
+ break;
+ case GTK_CMCTREE_EXPANDER_TRIANGLE:
+ new_width -= PM_SIZE + 3;
+ break;
+ case GTK_CMCTREE_EXPANDER_SQUARE:
+ case GTK_CMCTREE_EXPANDER_CIRCULAR:
+ new_width -= PM_SIZE + 1;
+ break;
+ }
+
+ switch (expander_style)
+ {
+ case GTK_CMCTREE_EXPANDER_NONE:
+ break;
+ case GTK_CMCTREE_EXPANDER_TRIANGLE:
+ new_width += PM_SIZE + 3;
+ break;
+ case GTK_CMCTREE_EXPANDER_SQUARE:
+ case GTK_CMCTREE_EXPANDER_CIRCULAR:
+ new_width += PM_SIZE + 1;
+ break;
+ }
+
+ gtk_cmclist_set_column_width (clist, ctree->tree_column, new_width);
+ }
+
+ if (GTK_WIDGET_DRAWABLE (clist))
+ CLIST_REFRESH (clist);
+}
+
+
+/***********************************************************
+ * Tree sorting functions *
+ ***********************************************************/
+
+
+static void
+tree_sort (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data)
+{
+ GtkCMCTreeNode *list_start;
+ GtkCMCTreeNode *cmp;
+ GtkCMCTreeNode *work;
+ GtkCMCList *clist;
+
+ clist = GTK_CMCLIST (ctree);
+
+ if (node)
+ list_start = GTK_CMCTREE_ROW (node)->children;
+ else
+ list_start = GTK_CMCTREE_NODE (clist->row_list);
+
+ while (list_start)
+ {
+ cmp = list_start;
+ work = GTK_CMCTREE_ROW (cmp)->sibling;
+ while (work)
+ {
+ if (clist->sort_type == GTK_SORT_ASCENDING)
+ {
+ if (clist->compare
+ (clist, GTK_CMCTREE_ROW (work), GTK_CMCTREE_ROW (cmp)) < 0)
+ cmp = work;
+ }
+ else
+ {
+ if (clist->compare
+ (clist, GTK_CMCTREE_ROW (work), GTK_CMCTREE_ROW (cmp)) > 0)
+ cmp = work;
+ }
+ work = GTK_CMCTREE_ROW (work)->sibling;
+ }
+ if (cmp == list_start)
+ list_start = GTK_CMCTREE_ROW (cmp)->sibling;
+ else
+ {
+ gtk_cmctree_unlink (ctree, cmp, FALSE);
+ gtk_cmctree_link (ctree, cmp, node, list_start, FALSE);
+ }
+ }
+}
+
+void
+gtk_cmctree_sort_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ GtkCMCList *clist;
+ GtkCMCTreeNode *focus_node = NULL;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ clist = GTK_CMCLIST (ctree);
+
+ gtk_cmclist_freeze (clist);
+
+ if (clist->selection_mode == GTK_SELECTION_MULTIPLE)
+ {
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+ }
+
+ if (!node || (node && gtk_cmctree_is_viewable (ctree, node)))
+ focus_node =
+ GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
+
+ gtk_cmctree_post_recursive (ctree, node, GTK_CMCTREE_FUNC (tree_sort), NULL);
+
+ if (!node)
+ tree_sort (ctree, NULL, NULL);
+
+ if (focus_node)
+ {
+ clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
+ clist->undo_anchor = clist->focus_row;
+ }
+
+ gtk_cmclist_thaw (clist);
+}
+
+static void
+real_sort_list (GtkCMCList *clist)
+{
+ gtk_cmctree_sort_recursive (GTK_CMCTREE (clist), NULL);
+}
+
+void
+gtk_cmctree_sort_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
+{
+ GtkCMCList *clist;
+ GtkCMCTreeNode *focus_node = NULL;
+
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ clist = GTK_CMCLIST (ctree);
+
+ gtk_cmclist_freeze (clist);
+
+ if (clist->selection_mode == GTK_SELECTION_MULTIPLE)
+ {
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+ }
+
+ if (!node || (node && gtk_cmctree_is_viewable (ctree, node)))
+ focus_node = GTK_CMCTREE_NODE
+ (g_list_nth (clist->row_list, clist->focus_row));
+
+ tree_sort (ctree, node, NULL);
+
+ if (focus_node)
+ {
+ clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
+ clist->undo_anchor = clist->focus_row;
+ }
+
+ gtk_cmclist_thaw (clist);
+}
+
+/************************************************************************/
+
+static void
+fake_unselect_all (GtkCMCList *clist,
+ gint row)
+{
+ GList *list;
+ GList *focus_node = NULL;
+
+ if (row >= 0 && (focus_node = g_list_nth (clist->row_list, row)))
+ {
+ if (GTK_CMCTREE_ROW (focus_node)->row.state == GTK_STATE_NORMAL &&
+ GTK_CMCTREE_ROW (focus_node)->row.selectable)
+ {
+ GTK_CMCTREE_ROW (focus_node)->row.state = GTK_STATE_SELECTED;
+
+ if (CLIST_UNFROZEN (clist) &&
+ gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row,
+ GTK_CMCLIST_ROW (focus_node));
+ }
+ }
+
+ clist->undo_selection = clist->selection;
+ clist->selection = NULL;
+ clist->selection_end = NULL;
+
+ for (list = clist->undo_selection; list; list = list->next)
+ {
+ if (list->data == focus_node)
+ continue;
+
+ GTK_CMCTREE_ROW ((GList *)(list->data))->row.state = GTK_STATE_NORMAL;
+ tree_draw_node (GTK_CMCTREE (clist), GTK_CMCTREE_NODE (list->data));
+ }
+}
+
+static GList *
+selection_find (GtkCMCList *clist,
+ gint row_number,
+ GList *row_list_element)
+{
+ return g_list_find (clist->selection, row_list_element);
+}
+
+static void
+resync_selection (GtkCMCList *clist, GdkEvent *event)
+{
+ GtkCMCTree *ctree;
+ GList *list;
+ GtkCMCTreeNode *node;
+ gint i;
+ gint e;
+ gint row;
+ gboolean unselect;
+
+ g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+ if (clist->selection_mode != GTK_SELECTION_MULTIPLE)
+ return;
+
+ if (clist->anchor < 0 || clist->drag_pos < 0)
+ return;
+
+ ctree = GTK_CMCTREE (clist);
+
+ clist->freeze_count++;
+
+ i = MIN (clist->anchor, clist->drag_pos);
+ e = MAX (clist->anchor, clist->drag_pos);
+
+ if (clist->undo_selection)
+ {
+ list = clist->selection;
+ clist->selection = clist->undo_selection;
+ clist->selection_end = g_list_last (clist->selection);
+ clist->undo_selection = list;
+ list = clist->selection;
+
+ while (list)
+ {
+ node = list->data;
+ list = list->next;
+
+ unselect = TRUE;
+
+ if (gtk_cmctree_is_viewable (ctree, node))
+ {
+ row = g_list_position (clist->row_list, (GList *)node);
+ if (row >= i && row <= e)
+ unselect = FALSE;
+ }
+ if (unselect && GTK_CMCTREE_ROW (node)->row.selectable)
+ {
+ GTK_CMCTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
+ gtk_cmctree_unselect (ctree, node);
+ clist->undo_selection = g_list_prepend (clist->undo_selection,
+ node);
+ }
+ }
+ }
+
+ if (clist->anchor < clist->drag_pos)
+ {
+ for (node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, i)); i <= e;
+ i++, node = GTK_CMCTREE_NODE_NEXT (node))
+ if (GTK_CMCTREE_ROW (node)->row.selectable)
+ {
+ if (g_list_find (clist->selection, node))
+ {
+ if (GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_NORMAL)
+ {
+ GTK_CMCTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
+ gtk_cmctree_unselect (ctree, node);
+ clist->undo_selection =
+ g_list_prepend (clist->undo_selection, node);
+ }
+ }
+ else if (GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
+ {
+ GTK_CMCTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
+ clist->undo_unselection =
+ g_list_prepend (clist->undo_unselection, node);
+ }
+ }
+ }
+ else
+ {
+ for (node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, e)); i <= e;
+ e--, node = GTK_CMCTREE_NODE_PREV (node))
+ if (GTK_CMCTREE_ROW (node)->row.selectable)
+ {
+ if (g_list_find (clist->selection, node))
+ {
+ if (GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_NORMAL)
+ {
+ GTK_CMCTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
+ gtk_cmctree_unselect (ctree, node);
+ clist->undo_selection =
+ g_list_prepend (clist->undo_selection, node);
+ }
+ }
+ else if (GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
+ {
+ GTK_CMCTREE_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_cmctree_select (ctree, list->data);
+
+ clist->anchor = -1;
+ clist->drag_pos = -1;
+
+ if (!CLIST_UNFROZEN (clist))
+ clist->freeze_count--;
+}
+
+static void
+real_undo_selection (GtkCMCList *clist)
+{
+ GtkCMCTree *ctree;
+ GList *work;
+
+ g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+ if (clist->selection_mode != GTK_SELECTION_MULTIPLE)
+ return;
+
+ if (!(clist->undo_selection || clist->undo_unselection))
+ {
+ gtk_cmclist_unselect_all (clist);
+ return;
+ }
+
+ ctree = GTK_CMCTREE (clist);
+
+ for (work = clist->undo_selection; work; work = work->next)
+ if (GTK_CMCTREE_ROW (work->data)->row.selectable)
+ gtk_cmctree_select (ctree, GTK_CMCTREE_NODE (work->data));
+
+ for (work = clist->undo_unselection; work; work = work->next)
+ if (GTK_CMCTREE_ROW (work->data)->row.selectable)
+ gtk_cmctree_unselect (ctree, GTK_CMCTREE_NODE (work->data));
+
+ if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
+ {
+ clist->focus_row = clist->undo_anchor;
+ gtk_widget_queue_draw (GTK_WIDGET (clist));
+ }
+ else
+ clist->focus_row = clist->undo_anchor;
+
+ clist->undo_anchor = -1;
+
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+
+ if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
+ clist->clist_window_height)
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+ else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+ gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+
+}
+
+void
+gtk_cmctree_set_drag_compare_func (GtkCMCTree *ctree,
+ GtkCMCTreeCompareDragFunc cmp_func)
+{
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+ ctree->drag_compare = cmp_func;
+}
+
+static gboolean
+check_drag (GtkCMCTree *ctree,
+ GtkCMCTreeNode *drag_source,
+ GtkCMCTreeNode *drag_target,
+ GtkCMCListDragPos insert_pos)
+{
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+
+ if (drag_source && drag_source != drag_target &&
+ (!GTK_CMCTREE_ROW (drag_source)->children ||
+ !gtk_cmctree_is_ancestor (ctree, drag_source, drag_target)))
+ {
+ switch (insert_pos)
+ {
+ case GTK_CMCLIST_DRAG_NONE:
+ return FALSE;
+ case GTK_CMCLIST_DRAG_AFTER:
+ if (GTK_CMCTREE_ROW (drag_target)->sibling != drag_source)
+ return (!ctree->drag_compare ||
+ ctree->drag_compare (ctree,
+ drag_source,
+ GTK_CMCTREE_ROW (drag_target)->parent,
+ GTK_CMCTREE_ROW (drag_target)->sibling));
+ break;
+ case GTK_CMCLIST_DRAG_BEFORE:
+ if (GTK_CMCTREE_ROW (drag_source)->sibling != drag_target)
+ return (!ctree->drag_compare ||
+ ctree->drag_compare (ctree,
+ drag_source,
+ GTK_CMCTREE_ROW (drag_target)->parent,
+ drag_target));
+ break;
+ case GTK_CMCLIST_DRAG_INTO:
+ if (!GTK_CMCTREE_ROW (drag_target)->is_leaf &&
+ GTK_CMCTREE_ROW (drag_target)->children != drag_source)
+ return (!ctree->drag_compare ||
+ ctree->drag_compare (ctree,
+ drag_source,
+ drag_target,
+ GTK_CMCTREE_ROW (drag_target)->children));
+ break;
+ }
+ }
+ return FALSE;
+}
+
+
+
+/************************************/
+static void
+drag_dest_info_destroy (gpointer data)
+{
+ GtkCMCListDestInfo *info = data;
+
+ g_free (info);
+}
+
+static void
+drag_dest_cell (GtkCMCList *clist,
+ gint x,
+ gint y,
+ GtkCMCListDestInfo *dest_info)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (clist);
+
+ dest_info->insert_pos = GTK_CMCLIST_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_CMCLIST_DRAW_DRAG_RECT(clist) &&
+ !GTK_CMCTREE_ROW (g_list_nth (clist->row_list,
+ dest_info->cell.row))->is_leaf)
+ {
+ dest_info->insert_pos = GTK_CMCLIST_DRAG_INTO;
+ h = clist->row_height / 4;
+ }
+ else if (GTK_CMCLIST_DRAW_DRAG_LINE(clist))
+ {
+ dest_info->insert_pos = GTK_CMCLIST_DRAG_BEFORE;
+ h = clist->row_height / 2;
+ }
+
+ if (GTK_CMCLIST_DRAW_DRAG_LINE(clist))
+ {
+ if (y_delta < h)
+ dest_info->insert_pos = GTK_CMCLIST_DRAG_BEFORE;
+ else if (clist->row_height - y_delta < h)
+ dest_info->insert_pos = GTK_CMCLIST_DRAG_AFTER;
+ }
+ }
+}
+
+static void
+gtk_cmctree_drag_begin (GtkWidget *widget,
+ GdkDragContext *context)
+{
+ GtkCMCList *clist;
+ GtkCMCTree *ctree;
+ gboolean use_icons;
+
+ g_return_if_fail (GTK_IS_CMCTREE (widget));
+ g_return_if_fail (context != NULL);
+
+ clist = GTK_CMCLIST (widget);
+ ctree = GTK_CMCTREE (widget);
+
+ use_icons = GTK_CMCLIST_USE_DRAG_ICONS (clist);
+ GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_USE_DRAG_ICONS);
+ GTK_WIDGET_CLASS (parent_class)->drag_begin (widget, context);
+
+ if (use_icons)
+ {
+ GtkCMCTreeNode *node;
+
+ GTK_CMCLIST_SET_FLAG (clist, CMCLIST_USE_DRAG_ICONS);
+ node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list,
+ clist->click_cell.row));
+ if (node)
+ {
+ if (GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
+ {
+ gtk_drag_set_icon_pixmap
+ (context,
+ gtk_widget_get_colormap (widget),
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap,
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask,
+ -2, -2);
+ return;
+ }
+ }
+ gtk_drag_set_icon_default (context);
+ }
+}
+
+static gint
+gtk_cmctree_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time)
+{
+ GtkCMCList *clist;
+ GtkCMCTree *ctree;
+ GtkCMCListDestInfo new_info;
+ GtkCMCListDestInfo *dest_info;
+
+ g_return_val_if_fail (GTK_IS_CMCTREE (widget), FALSE);
+
+ clist = GTK_CMCLIST (widget);
+ ctree = GTK_CMCTREE (widget);
+
+ dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+
+ if (!dest_info)
+ {
+ dest_info = g_new (GtkCMCListDestInfo, 1);
+
+ dest_info->cell.row = -1;
+ dest_info->cell.column = -1;
+ dest_info->insert_pos = GTK_CMCLIST_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_CMCLIST_REORDERABLE (clist))
+ {
+ GList *list;
+ GdkAtom atom = gdk_atom_intern_static_string ("gtk-clist-drag-reorder");
+
+ list = context->targets;
+ while (list)
+ {
+ if (atom == GDK_POINTER_TO_ATOM (list->data))
+ break;
+ list = list->next;
+ }
+
+ if (list)
+ {
+ GtkCMCTreeNode *drag_source;
+ GtkCMCTreeNode *drag_target;
+
+ drag_source = GTK_CMCTREE_NODE (g_list_nth (clist->row_list,
+ clist->click_cell.row));
+ drag_target = GTK_CMCTREE_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_CMCLIST_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_CMCLIST_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_cmctree_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint32 time)
+{
+ GtkCMCTree *ctree;
+ GtkCMCList *clist;
+
+ g_return_if_fail (GTK_IS_CMCTREE (widget));
+ g_return_if_fail (context != NULL);
+ g_return_if_fail (selection_data != NULL);
+
+ ctree = GTK_CMCTREE (widget);
+ clist = GTK_CMCLIST (widget);
+
+ if (GTK_CMCLIST_REORDERABLE (clist) &&
+ gtk_drag_get_source_widget (context) == widget &&
+ selection_data->target ==
+ gdk_atom_intern_static_string ("gtk-clist-drag-reorder") &&
+ selection_data->format == 8 &&
+ selection_data->length == sizeof (GtkCMCListCellInfo))
+ {
+ GtkCMCListCellInfo *source_info;
+
+ source_info = (GtkCMCListCellInfo *)(selection_data->data);
+ if (source_info)
+ {
+ GtkCMCListDestInfo dest_info;
+ GtkCMCTreeNode *source_node;
+ GtkCMCTreeNode *dest_node;
+
+ drag_dest_cell (clist, x, y, &dest_info);
+
+ source_node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list,
+ source_info->row));
+ dest_node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list,
+ dest_info.cell.row));
+
+ if (!source_node || !dest_node)
+ return;
+
+ switch (dest_info.insert_pos)
+ {
+ case GTK_CMCLIST_DRAG_NONE:
+ break;
+ case GTK_CMCLIST_DRAG_INTO:
+ if (check_drag (ctree, source_node, dest_node,
+ dest_info.insert_pos))
+ gtk_cmctree_move (ctree, source_node, dest_node,
+ GTK_CMCTREE_ROW (dest_node)->children);
+ g_dataset_remove_data (context, "gtk-clist-drag-dest");
+ break;
+ case GTK_CMCLIST_DRAG_BEFORE:
+ if (check_drag (ctree, source_node, dest_node,
+ dest_info.insert_pos))
+ gtk_cmctree_move (ctree, source_node,
+ GTK_CMCTREE_ROW (dest_node)->parent, dest_node);
+ g_dataset_remove_data (context, "gtk-clist-drag-dest");
+ break;
+ case GTK_CMCLIST_DRAG_AFTER:
+ if (check_drag (ctree, source_node, dest_node,
+ dest_info.insert_pos))
+ gtk_cmctree_move (ctree, source_node,
+ GTK_CMCTREE_ROW (dest_node)->parent,
+ GTK_CMCTREE_ROW (dest_node)->sibling);
+ g_dataset_remove_data (context, "gtk-clist-drag-dest");
+ break;
+ }
+ }
+ }
+}
+
+GType
+gtk_cmctree_node_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ our_type = g_pointer_type_register_static ("GtkCMCTreeNode");
+
+ return our_type;
+}
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, Josh MacDonald
+ * Copyright (C) 1997-1998 Jay Painter <jpaint@serv.net><jpaint@gimp.org>
+ *
+ * GtkCMCTree widget for GTK+
+ * 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 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
+ * Lesser General Public License for more details.
+ *
+ * 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/.
+ */
+
+#ifndef __GTK_CMCTREE_H__
+#define __GTK_CMCTREE_H__
+
+#include "gtkcmclist.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CMCTREE (gtk_cmctree_get_type ())
+#define GTK_CMCTREE(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_CMCTREE, GtkCMCTree))
+#define GTK_CMCTREE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CMCTREE, GtkCMCTreeClass))
+#define GTK_IS_CMCTREE(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_CMCTREE))
+#define GTK_IS_CMCTREE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CMCTREE))
+#define GTK_CMCTREE_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_CMCTREE, GtkCMCTreeClass))
+
+#define GTK_CMCTREE_ROW(_node_) ((GtkCMCTreeRow *)(((GList *)(_node_))->data))
+#define GTK_CMCTREE_NODE(_node_) ((GtkCMCTreeNode *)((_node_)))
+#define GTK_CMCTREE_NODE_NEXT(_nnode_) ((GtkCMCTreeNode *)(((GList *)(_nnode_))->next))
+#define GTK_CMCTREE_NODE_PREV(_pnode_) ((GtkCMCTreeNode *)(((GList *)(_pnode_))->prev))
+#define GTK_CMCTREE_FUNC(_func_) ((GtkCMCTreeFunc)(_func_))
+
+#define GTK_TYPE_CMCTREE_NODE (gtk_cmctree_node_get_type ())
+
+GType gtk_cmctree_pos_get_type (void) G_GNUC_CONST;
+#define GTK_TYPE_CMCTREE_POS (gtk_cmctree_pos_get_type())
+GType gtk_cmctree_line_style_get_type (void) G_GNUC_CONST;
+#define GTK_TYPE_CMCTREE_LINE_STYLE (gtk_cmctree_line_style_get_type())
+GType gtk_cmctree_expander_style_get_type (void) G_GNUC_CONST;
+#define GTK_TYPE_CMCTREE_EXPANDER_STYLE (gtk_cmctree_expander_style_get_type())
+GType gtk_cmctree_expansion_type_get_type (void) G_GNUC_CONST;
+#define GTK_TYPE_CMCTREE_EXPANSION_TYPE (gtk_cmctree_expansion_type_get_type())
+
+typedef enum
+{
+ GTK_CMCTREE_POS_BEFORE,
+ GTK_CMCTREE_POS_AS_CHILD,
+ GTK_CMCTREE_POS_AFTER
+} GtkCMCTreePos;
+
+typedef enum
+{
+ GTK_CMCTREE_LINES_NONE,
+ GTK_CMCTREE_LINES_SOLID,
+ GTK_CMCTREE_LINES_DOTTED,
+ GTK_CMCTREE_LINES_TABBED
+} GtkCMCTreeLineStyle;
+
+typedef enum
+{
+ GTK_CMCTREE_EXPANDER_NONE,
+ GTK_CMCTREE_EXPANDER_SQUARE,
+ GTK_CMCTREE_EXPANDER_TRIANGLE,
+ GTK_CMCTREE_EXPANDER_CIRCULAR
+} GtkCMCTreeExpanderStyle;
+
+typedef enum
+{
+ GTK_CMCTREE_EXPANSION_EXPAND,
+ GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE,
+ GTK_CMCTREE_EXPANSION_COLLAPSE,
+ GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE,
+ GTK_CMCTREE_EXPANSION_TOGGLE,
+ GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE
+} GtkCMCTreeExpansionType;
+
+typedef struct _GtkCMCTree GtkCMCTree;
+typedef struct _GtkCMCTreeClass GtkCMCTreeClass;
+typedef struct _GtkCMCTreeRow GtkCMCTreeRow;
+typedef struct _GtkCMCTreeNode GtkCMCTreeNode;
+
+typedef void (*GtkCMCTreeFunc) (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+
+typedef gboolean (*GtkCMCTreeGNodeFunc) (GtkCMCTree *ctree,
+ guint depth,
+ GNode *gnode,
+ GtkCMCTreeNode *cnode,
+ gpointer data);
+
+typedef gboolean (*GtkCMCTreeCompareDragFunc) (GtkCMCTree *ctree,
+ GtkCMCTreeNode *source_node,
+ GtkCMCTreeNode *new_parent,
+ GtkCMCTreeNode *new_sibling);
+
+struct _GtkCMCTree
+{
+ GtkCMCList clist;
+
+ GdkGC *lines_gc;
+
+ gint tree_indent;
+ gint tree_spacing;
+ gint tree_column;
+
+ guint line_style : 2;
+ guint expander_style : 2;
+ guint show_stub : 1;
+
+ GtkCMCTreeCompareDragFunc drag_compare;
+};
+
+struct _GtkCMCTreeClass
+{
+ GtkCMCListClass parent_class;
+
+ void (*tree_select_row) (GtkCMCTree *ctree,
+ GtkCMCTreeNode *row,
+ gint column);
+ void (*tree_unselect_row) (GtkCMCTree *ctree,
+ GtkCMCTreeNode *row,
+ gint column);
+ void (*tree_expand) (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+ void (*tree_collapse) (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+ void (*tree_move) (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *new_parent,
+ GtkCMCTreeNode *new_sibling);
+ void (*change_focus_row_expansion) (GtkCMCTree *ctree,
+ GtkCMCTreeExpansionType action);
+};
+
+struct _GtkCMCTreeRow
+{
+ GtkCMCListRow row;
+
+ GtkCMCTreeNode *parent;
+ GtkCMCTreeNode *sibling;
+ GtkCMCTreeNode *children;
+
+ GdkPixmap *pixmap_closed;
+ GdkBitmap *mask_closed;
+ GdkPixmap *pixmap_opened;
+ GdkBitmap *mask_opened;
+
+ guint16 level;
+
+ guint is_leaf : 1;
+ guint expanded : 1;
+};
+
+struct _GtkCMCTreeNode {
+ GList list;
+};
+
+
+/***********************************************************
+ * Creation, insertion, deletion *
+ ***********************************************************/
+
+GType gtk_cmctree_get_type (void);
+GtkWidget * gtk_cmctree_new_with_titles (gint columns,
+ gint tree_column,
+ gchar *titles[]);
+GtkWidget * gtk_cmctree_new (gint columns,
+ gint tree_column);
+GtkCMCTreeNode * gtk_cmctree_insert_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *sibling,
+ gchar *text[],
+ guint8 spacing,
+ GdkPixmap *pixmap_closed,
+ GdkBitmap *mask_closed,
+ GdkPixmap *pixmap_opened,
+ GdkBitmap *mask_opened,
+ gboolean is_leaf,
+ gboolean expanded);
+void gtk_cmctree_remove_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+GtkCMCTreeNode * gtk_cmctree_insert_gnode (GtkCMCTree *ctree,
+ GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *sibling,
+ GNode *gnode,
+ GtkCMCTreeGNodeFunc func,
+ gpointer data);
+GNode * gtk_cmctree_export_to_gnode (GtkCMCTree *ctree,
+ GNode *parent,
+ GNode *sibling,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeGNodeFunc func,
+ gpointer data);
+
+/***********************************************************
+ * Generic recursive functions, querying / finding tree *
+ * information *
+ ***********************************************************/
+
+void gtk_cmctree_post_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeFunc func,
+ gpointer data);
+void gtk_cmctree_post_recursive_to_depth (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint depth,
+ GtkCMCTreeFunc func,
+ gpointer data);
+void gtk_cmctree_pre_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeFunc func,
+ gpointer data);
+void gtk_cmctree_pre_recursive_to_depth (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint depth,
+ GtkCMCTreeFunc func,
+ gpointer data);
+gboolean gtk_cmctree_is_viewable (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+GtkCMCTreeNode * gtk_cmctree_last (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+GtkCMCTreeNode * gtk_cmctree_find_node_ptr (GtkCMCTree *ctree,
+ GtkCMCTreeRow *ctree_row);
+GtkCMCTreeNode * gtk_cmctree_node_nth (GtkCMCTree *ctree,
+ guint row);
+gboolean gtk_cmctree_find (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *child);
+gboolean gtk_cmctree_is_ancestor (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *child);
+GtkCMCTreeNode * gtk_cmctree_find_by_row_data (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+/* returns a GList of all GtkCMCTreeNodes with row->data == data. */
+GList * gtk_cmctree_find_all_by_row_data (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+GtkCMCTreeNode * gtk_cmctree_find_by_row_data_custom (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data,
+ GCompareFunc func);
+/* returns a GList of all GtkCMCTreeNodes with row->data == data. */
+GList * gtk_cmctree_find_all_by_row_data_custom (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data,
+ GCompareFunc func);
+gboolean gtk_cmctree_is_hot_spot (GtkCMCTree *ctree,
+ gint x,
+ gint y);
+
+/***********************************************************
+ * Tree signals : move, expand, collapse, (un)select *
+ ***********************************************************/
+
+void gtk_cmctree_move (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *new_parent,
+ GtkCMCTreeNode *new_sibling);
+void gtk_cmctree_expand (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtk_cmctree_expand_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtk_cmctree_expand_to_depth (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint depth);
+void gtk_cmctree_collapse (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtk_cmctree_collapse_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtk_cmctree_collapse_to_depth (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint depth);
+void gtk_cmctree_toggle_expansion (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtk_cmctree_toggle_expansion_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtk_cmctree_select (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtk_cmctree_select_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtk_cmctree_unselect (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtk_cmctree_unselect_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtk_cmctree_real_select_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint state);
+
+/***********************************************************
+ * Analogons of GtkCMCList functions *
+ ***********************************************************/
+
+void gtk_cmctree_node_set_text (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ const gchar *text);
+void gtk_cmctree_node_set_pixmap (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask);
+void gtk_cmctree_node_set_pixtext (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask);
+void gtk_cmctree_set_node_info (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap_closed,
+ GdkBitmap *mask_closed,
+ GdkPixmap *pixmap_opened,
+ GdkBitmap *mask_opened,
+ gboolean is_leaf,
+ gboolean expanded);
+void gtk_cmctree_node_set_shift (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ gint vertical,
+ gint horizontal);
+void gtk_cmctree_node_set_selectable (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gboolean selectable);
+gboolean gtk_cmctree_node_get_selectable (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+GtkCMCellType gtk_cmctree_node_get_cell_type (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column);
+gboolean gtk_cmctree_node_get_text (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ gchar **text);
+gboolean gtk_cmctree_node_get_pixmap (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ GdkPixmap **pixmap,
+ GdkBitmap **mask);
+gboolean gtk_cmctree_node_get_pixtext (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ gchar **text,
+ guint8 *spacing,
+ GdkPixmap **pixmap,
+ GdkBitmap **mask);
+gboolean gtk_cmctree_get_node_info (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gchar **text,
+ guint8 *spacing,
+ GdkPixmap **pixmap_closed,
+ GdkBitmap **mask_closed,
+ GdkPixmap **pixmap_opened,
+ GdkBitmap **mask_opened,
+ gboolean *is_leaf,
+ gboolean *expanded);
+void gtk_cmctree_node_set_row_style (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkStyle *style);
+GtkStyle * gtk_cmctree_node_get_row_style (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtk_cmctree_node_set_cell_style (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ GtkStyle *style);
+GtkStyle * gtk_cmctree_node_get_cell_style (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column);
+void gtk_cmctree_node_set_foreground (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ const GdkColor *color);
+void gtk_cmctree_node_set_background (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ const GdkColor *color);
+void gtk_cmctree_node_set_row_data (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data);
+void gtk_cmctree_node_set_row_data_full (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer data,
+ GtkDestroyNotify destroy);
+gpointer gtk_cmctree_node_get_row_data (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtk_cmctree_node_moveto (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gint column,
+ gfloat row_align,
+ gfloat col_align);
+GtkVisibility gtk_cmctree_node_is_visible (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+
+/***********************************************************
+ * GtkCMCTree specific functions *
+ ***********************************************************/
+
+void gtk_cmctree_set_indent (GtkCMCTree *ctree,
+ gint indent);
+void gtk_cmctree_set_spacing (GtkCMCTree *ctree,
+ gint spacing);
+void gtk_cmctree_set_show_stub (GtkCMCTree *ctree,
+ gboolean show_stub);
+void gtk_cmctree_set_line_style (GtkCMCTree *ctree,
+ GtkCMCTreeLineStyle line_style);
+void gtk_cmctree_set_expander_style (GtkCMCTree *ctree,
+ GtkCMCTreeExpanderStyle expander_style);
+void gtk_cmctree_set_drag_compare_func (GtkCMCTree *ctree,
+ GtkCMCTreeCompareDragFunc cmp_func);
+
+/***********************************************************
+ * Tree sorting functions *
+ ***********************************************************/
+
+void gtk_cmctree_sort_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtk_cmctree_sort_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+
+
+#define gtk_cmctree_set_reorderable(t,r) gtk_cmclist_set_reorderable((GtkCMCList*) (t),(r))
+
+/* GType for the GtkCMCTreeNode. This is a boxed type, although it uses
+ * no-op's for the copy and free routines. It is defined in order to
+ * provide type information for the signal arguments
+ */
+GType gtk_cmctree_node_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GTK_CMCTREE_H__ */
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Jsh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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 <config.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "claws-marshal.h"
+#include "gtkcmoptionmenu.h"
+
+#define CHILD_LEFT_SPACING 4
+#define CHILD_RIGHT_SPACING 1
+#define CHILD_TOP_SPACING 1
+#define CHILD_BOTTOM_SPACING 1
+
+typedef struct _GtkCMOptionMenuProps GtkCMOptionMenuProps;
+
+struct _GtkCMOptionMenuProps
+{
+ gboolean interior_focus;
+ GtkRequisition indicator_size;
+ GtkBorder indicator_spacing;
+ gint focus_width;
+ gint focus_pad;
+};
+
+static const GtkCMOptionMenuProps default_props = {
+ TRUE,
+ { 7, 13 },
+ { 7, 5, 2, 2 }, /* Left, right, top, bottom */
+ 1,
+ 0
+};
+
+static void gtk_cmoption_menu_destroy (GtkObject *object);
+static void gtk_cmoption_menu_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_cmoption_menu_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gtk_cmoption_menu_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_cmoption_menu_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_cmoption_menu_paint (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_cmoption_menu_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_cmoption_menu_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_cmoption_menu_key_press (GtkWidget *widget,
+ GdkEventKey *event);
+static void gtk_cmoption_menu_selection_done (GtkMenuShell *menu_shell,
+ GtkCMOptionMenu *option_menu);
+static void gtk_cmoption_menu_update_contents (GtkCMOptionMenu *option_menu);
+static void gtk_cmoption_menu_remove_contents (GtkCMOptionMenu *option_menu);
+static void gtk_cmoption_menu_calc_size (GtkCMOptionMenu *option_menu);
+static void gtk_cmoption_menu_position (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gint *scroll_offet,
+ gpointer user_data);
+static void gtk_cmoption_menu_show_all (GtkWidget *widget);
+static void gtk_cmoption_menu_hide_all (GtkWidget *widget);
+static gboolean gtk_cmoption_menu_mnemonic_activate (GtkWidget *widget,
+ gboolean group_cycling);
+static GType gtk_cmoption_menu_child_type (GtkContainer *container);
+static gint gtk_cmoption_menu_scroll_event (GtkWidget *widget,
+ GdkEventScroll *event);
+
+enum
+{
+ CHANGED,
+ LAST_SIGNAL
+};
+
+enum
+{
+ PROP_0,
+ PROP_MENU,
+ LAST_PROP
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GtkCMOptionMenu, gtk_cmoption_menu, GTK_TYPE_BUTTON)
+
+static void
+gtk_cmoption_menu_class_init (GtkCMOptionMenuClass *class)
+{
+ GObjectClass *gobject_class;
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ gobject_class = (GObjectClass*) class;
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+ container_class = (GtkContainerClass*) class;
+
+ signals[CHANGED] =
+ g_signal_new (("changed"),
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkCMOptionMenuClass, changed),
+ NULL, NULL,
+ claws_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ gobject_class->set_property = gtk_cmoption_menu_set_property;
+ gobject_class->get_property = gtk_cmoption_menu_get_property;
+ object_class->destroy = gtk_cmoption_menu_destroy;
+
+ widget_class->size_request = gtk_cmoption_menu_size_request;
+ widget_class->size_allocate = gtk_cmoption_menu_size_allocate;
+ widget_class->expose_event = gtk_cmoption_menu_expose;
+ widget_class->button_press_event = gtk_cmoption_menu_button_press;
+ widget_class->key_press_event = gtk_cmoption_menu_key_press;
+ widget_class->scroll_event = gtk_cmoption_menu_scroll_event;
+ widget_class->show_all = gtk_cmoption_menu_show_all;
+ widget_class->hide_all = gtk_cmoption_menu_hide_all;
+ widget_class->mnemonic_activate = gtk_cmoption_menu_mnemonic_activate;
+
+ container_class->child_type = gtk_cmoption_menu_child_type;
+
+ g_object_class_install_property (gobject_class,
+ PROP_MENU,
+ g_param_spec_object ("menu",
+ ("Menu"),
+ ("The menu of options"),
+ GTK_TYPE_MENU,
+ G_PARAM_READWRITE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_boxed ("indicator-size",
+ ("Indicator Size"),
+ ("Size of dropdown indicator"),
+ GTK_TYPE_REQUISITION,
+ G_PARAM_READABLE));
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_boxed ("indicator-spacing",
+ ("Indicator Spacing"),
+ ("Spacing around indicator"),
+ GTK_TYPE_BORDER,
+ G_PARAM_READABLE));
+}
+
+static GType
+gtk_cmoption_menu_child_type (GtkContainer *container)
+{
+ return G_TYPE_NONE;
+}
+
+static void
+gtk_cmoption_menu_init (GtkCMOptionMenu *option_menu)
+{
+ GTK_WIDGET_SET_FLAGS (option_menu, GTK_CAN_FOCUS);
+ GTK_WIDGET_UNSET_FLAGS (option_menu, GTK_CAN_DEFAULT | GTK_RECEIVES_DEFAULT);
+
+ option_menu->menu = NULL;
+ option_menu->menu_item = NULL;
+ option_menu->width = 0;
+ option_menu->height = 0;
+}
+
+GtkWidget*
+gtk_cmoption_menu_new (void)
+{
+ return g_object_new (GTK_TYPE_CMOPTION_MENU, NULL);
+}
+
+GtkWidget*
+gtk_cmoption_menu_get_menu (GtkCMOptionMenu *option_menu)
+{
+ g_return_val_if_fail (GTK_IS_CMOPTION_MENU (option_menu), NULL);
+
+ return option_menu->menu;
+}
+
+static void
+gtk_cmoption_menu_detacher (GtkWidget *widget,
+ GtkMenu *menu)
+{
+ GtkCMOptionMenu *option_menu;
+
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (widget));
+
+ option_menu = GTK_CMOPTION_MENU (widget);
+ g_return_if_fail (option_menu->menu == (GtkWidget*) menu);
+
+ gtk_cmoption_menu_remove_contents (option_menu);
+ g_signal_handlers_disconnect_by_func (option_menu->menu,
+ gtk_cmoption_menu_selection_done,
+ option_menu);
+ g_signal_handlers_disconnect_by_func (option_menu->menu,
+ gtk_cmoption_menu_calc_size,
+ option_menu);
+
+ option_menu->menu = NULL;
+ g_object_notify (G_OBJECT (option_menu), "menu");
+}
+
+void
+gtk_cmoption_menu_set_menu (GtkCMOptionMenu *option_menu,
+ GtkWidget *menu)
+{
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+ g_return_if_fail (GTK_IS_MENU (menu));
+
+ if (option_menu->menu != menu)
+ {
+ gtk_cmoption_menu_remove_menu (option_menu);
+
+ option_menu->menu = menu;
+ gtk_menu_attach_to_widget (GTK_MENU (menu),
+ GTK_WIDGET (option_menu),
+ gtk_cmoption_menu_detacher);
+
+ gtk_cmoption_menu_calc_size (option_menu);
+
+ g_signal_connect_after (option_menu->menu, "selection-done",
+ G_CALLBACK (gtk_cmoption_menu_selection_done),
+ option_menu);
+ g_signal_connect_swapped (option_menu->menu, "size_request",
+ G_CALLBACK (gtk_cmoption_menu_calc_size),
+ option_menu);
+
+ if (GTK_WIDGET (option_menu)->parent)
+ gtk_widget_queue_resize (GTK_WIDGET (option_menu));
+
+ gtk_cmoption_menu_update_contents (option_menu);
+
+ g_object_notify (G_OBJECT (option_menu), "menu");
+ }
+}
+
+void
+gtk_cmoption_menu_remove_menu (GtkCMOptionMenu *option_menu)
+{
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+ if (option_menu->menu)
+ {
+ if (GTK_MENU_SHELL (option_menu->menu)->active)
+ gtk_menu_shell_cancel (GTK_MENU_SHELL (option_menu->menu));
+
+ gtk_menu_detach (GTK_MENU (option_menu->menu));
+ }
+}
+
+void
+gtk_cmoption_menu_set_history (GtkCMOptionMenu *option_menu,
+ guint index)
+{
+ GtkWidget *menu_item;
+
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+ if (option_menu->menu)
+ {
+ gtk_menu_set_active (GTK_MENU (option_menu->menu), index);
+ menu_item = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+
+ if (menu_item != option_menu->menu_item)
+ gtk_cmoption_menu_update_contents (option_menu);
+ }
+}
+
+/**
+ * gtk_cmoption_menu_get_history:
+ * @option_menu: a #GtkCMOptionMenu
+ *
+ * Retrieves the index of the currently selected menu item. The menu
+ * items are numbered from top to bottom, starting with 0.
+ *
+ * Return value: index of the selected menu item, or -1 if there are no menu items
+ * Deprecated: 2.4: Use #GtkComboBox instead.
+ **/
+gint
+gtk_cmoption_menu_get_history (GtkCMOptionMenu *option_menu)
+{
+ GtkWidget *active_widget;
+
+ g_return_val_if_fail (GTK_IS_CMOPTION_MENU (option_menu), -1);
+
+ if (option_menu->menu)
+ {
+ active_widget = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+
+ if (active_widget)
+ return g_list_index (GTK_MENU_SHELL (option_menu->menu)->children,
+ active_widget);
+ else
+ return -1;
+ }
+ else
+ return -1;
+}
+
+static void
+gtk_cmoption_menu_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkCMOptionMenu *option_menu = GTK_CMOPTION_MENU (object);
+
+ switch (prop_id)
+ {
+ case PROP_MENU:
+ gtk_cmoption_menu_set_menu (option_menu, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_cmoption_menu_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkCMOptionMenu *option_menu = GTK_CMOPTION_MENU (object);
+
+ switch (prop_id)
+ {
+ case PROP_MENU:
+ g_value_set_object (value, option_menu->menu);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_cmoption_menu_destroy (GtkObject *object)
+{
+ GtkCMOptionMenu *option_menu;
+
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (object));
+
+ option_menu = GTK_CMOPTION_MENU (object);
+
+ if (option_menu->menu)
+ gtk_widget_destroy (option_menu->menu);
+
+ if (GTK_OBJECT_CLASS (gtk_cmoption_menu_parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (gtk_cmoption_menu_parent_class)->destroy) (object);
+}
+
+static void
+gtk_cmoption_menu_get_props (GtkCMOptionMenu *option_menu,
+ GtkCMOptionMenuProps *props)
+{
+ GtkRequisition *indicator_size;
+ GtkBorder *indicator_spacing;
+
+ gtk_widget_style_get (GTK_WIDGET (option_menu),
+ "indicator-size", &indicator_size,
+ "indicator-spacing", &indicator_spacing,
+ "interior-focus", &props->interior_focus,
+ "focus-line-width", &props->focus_width,
+ "focus-padding", &props->focus_pad,
+ NULL);
+
+ if (indicator_size)
+ props->indicator_size = *indicator_size;
+ else
+ props->indicator_size = default_props.indicator_size;
+
+ if (indicator_spacing)
+ props->indicator_spacing = *indicator_spacing;
+ else
+ props->indicator_spacing = default_props.indicator_spacing;
+
+ gtk_requisition_free (indicator_size);
+ gtk_border_free (indicator_spacing);
+}
+
+static void
+gtk_cmoption_menu_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkCMOptionMenu *option_menu = GTK_CMOPTION_MENU (widget);
+ GtkCMOptionMenuProps props;
+ gint tmp;
+ GtkRequisition child_requisition = { 0, 0 };
+
+ gtk_cmoption_menu_get_props (option_menu, &props);
+
+ if (GTK_BIN (option_menu)->child && GTK_WIDGET_VISIBLE (GTK_BIN (option_menu)->child))
+ {
+ gtk_widget_size_request (GTK_BIN (option_menu)->child, &child_requisition);
+
+ requisition->width += child_requisition.width;
+ requisition->height += child_requisition.height;
+ }
+
+ requisition->width = ((GTK_CONTAINER (widget)->border_width +
+ GTK_WIDGET (widget)->style->xthickness + props.focus_pad) * 2 +
+ MAX (child_requisition.width, option_menu->width) +
+ props.indicator_size.width +
+ props.indicator_spacing.left + props.indicator_spacing.right +
+ CHILD_LEFT_SPACING + CHILD_RIGHT_SPACING + props.focus_width * 2);
+ requisition->height = ((GTK_CONTAINER (widget)->border_width +
+ GTK_WIDGET (widget)->style->ythickness + props.focus_pad) * 2 +
+ MAX (child_requisition.height, option_menu->height) +
+ CHILD_TOP_SPACING + CHILD_BOTTOM_SPACING + props.focus_width * 2);
+
+ tmp = (requisition->height - MAX (child_requisition.height, option_menu->height) +
+ props.indicator_size.height + props.indicator_spacing.top + props.indicator_spacing.bottom);
+ requisition->height = MAX (requisition->height, tmp);
+}
+
+static void
+gtk_cmoption_menu_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkWidget *child;
+ GtkButton *button = GTK_BUTTON (widget);
+ GtkAllocation child_allocation;
+ GtkCMOptionMenuProps props;
+ gint border_width;
+
+ gtk_cmoption_menu_get_props (GTK_CMOPTION_MENU (widget), &props);
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (button->event_window,
+ allocation->x + border_width, allocation->y + border_width,
+ allocation->width - border_width * 2, allocation->height - border_width * 2);
+
+ child = GTK_BIN (widget)->child;
+ if (child && GTK_WIDGET_VISIBLE (child))
+ {
+ gint xthickness = GTK_WIDGET (widget)->style->xthickness;
+ gint ythickness = GTK_WIDGET (widget)->style->ythickness;
+
+ child_allocation.x = widget->allocation.x + border_width + xthickness + props.focus_width + props.focus_pad + CHILD_LEFT_SPACING;
+ child_allocation.y = widget->allocation.y + border_width + ythickness + props.focus_width + props.focus_pad + CHILD_TOP_SPACING;
+ child_allocation.width = MAX (1, allocation->width - (border_width + xthickness + props.focus_width + props.focus_pad) * 2 -
+ props.indicator_size.width - props.indicator_spacing.left - props.indicator_spacing.right -
+ CHILD_LEFT_SPACING - CHILD_RIGHT_SPACING);
+ child_allocation.height = MAX (1, allocation->height - (border_width + ythickness + props.focus_width + props.focus_pad) * 2 -
+ CHILD_TOP_SPACING - CHILD_BOTTOM_SPACING);
+
+ if (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL)
+ child_allocation.x += props.indicator_size.width + props.indicator_spacing.left + props.indicator_spacing.right;
+
+ gtk_widget_size_allocate (child, &child_allocation);
+ }
+}
+
+static void
+gtk_cmoption_menu_paint (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GdkRectangle button_area;
+ GtkCMOptionMenuProps props;
+ gint border_width;
+ gint tab_x;
+
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ border_width = GTK_CONTAINER (widget)->border_width;
+ gtk_cmoption_menu_get_props (GTK_CMOPTION_MENU (widget), &props);
+
+ button_area.x = widget->allocation.x + border_width;
+ button_area.y = widget->allocation.y + border_width;
+ button_area.width = widget->allocation.width - 2 * border_width;
+ button_area.height = widget->allocation.height - 2 * border_width;
+
+ if (!props.interior_focus && GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ button_area.x += props.focus_width + props.focus_pad;
+ button_area.y += props.focus_width + props.focus_pad;
+ button_area.width -= 2 * (props.focus_width + props.focus_pad);
+ button_area.height -= 2 * (props.focus_width + props.focus_pad);
+ }
+
+ gtk_paint_box (widget->style, widget->window,
+ GTK_WIDGET_STATE (widget), GTK_SHADOW_OUT,
+ area, widget, "optionmenu",
+ button_area.x, button_area.y,
+ button_area.width, button_area.height);
+
+ if (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL)
+ tab_x = button_area.x + props.indicator_spacing.right +
+ widget->style->xthickness;
+ else
+ tab_x = button_area.x + button_area.width -
+ props.indicator_size.width - props.indicator_spacing.right -
+ widget->style->xthickness;
+
+ gtk_paint_tab (widget->style, widget->window,
+ GTK_WIDGET_STATE (widget), GTK_SHADOW_OUT,
+ area, widget, "optionmenutab",
+ tab_x,
+ button_area.y + (button_area.height - props.indicator_size.height) / 2,
+ props.indicator_size.width, props.indicator_size.height);
+
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ if (props.interior_focus)
+ {
+ button_area.x += widget->style->xthickness + props.focus_pad;
+ button_area.y += widget->style->ythickness + props.focus_pad;
+ button_area.width -= 2 * (widget->style->xthickness + props.focus_pad) +
+ props.indicator_spacing.left +
+ props.indicator_spacing.right +
+ props.indicator_size.width;
+ button_area.height -= 2 * (widget->style->ythickness + props.focus_pad);
+ if (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL)
+ button_area.x += props.indicator_spacing.left +
+ props.indicator_spacing.right +
+ props.indicator_size.width;
+ }
+ else
+ {
+ button_area.x -= props.focus_width + props.focus_pad;
+ button_area.y -= props.focus_width + props.focus_pad;
+ button_area.width += 2 * (props.focus_width + props.focus_pad);
+ button_area.height += 2 * (props.focus_width + props.focus_pad);
+ }
+
+ gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
+ area, widget, "button",
+ button_area.x,
+ button_area.y,
+ button_area.width,
+ button_area.height);
+ }
+ }
+}
+
+static gint
+gtk_cmoption_menu_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ g_return_val_if_fail (GTK_IS_CMOPTION_MENU (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ gtk_cmoption_menu_paint (widget, &event->area);
+
+
+ /* The following code tries to draw the child in two places at
+ * once. It fails miserably for several reasons
+ *
+ * - If the child is not no-window, removing generates
+ * more expose events. Bad, bad, bad.
+ *
+ * - Even if the child is no-window, removing it now (properly)
+ * clears the space where it was, so it does no good
+ */
+
+#if 0
+ remove_child = FALSE;
+ child = GTK_BUTTON (widget)->child;
+
+ if (!child)
+ {
+ if (!GTK_CMOPTION_MENU (widget)->menu)
+ return FALSE;
+ gtk_cmoption_menu_update_contents (GTK_CMOPTION_MENU (widget));
+ child = GTK_BUTTON (widget)->child;
+ if (!child)
+ return FALSE;
+ remove_child = TRUE;
+ }
+
+ child_event = *event;
+
+ if (GTK_WIDGET_NO_WINDOW (child) &&
+ gtk_widget_intersect (child, &event->area, &child_event.area))
+ gtk_widget_event (child, (GdkEvent*) &child_event);
+
+ if (remove_child)
+ gtk_cmoption_menu_remove_contents (GTK_CMOPTION_MENU (widget));
+#else
+ if (GTK_BIN (widget)->child)
+ gtk_container_propagate_expose (GTK_CONTAINER (widget),
+ GTK_BIN (widget)->child,
+ event);
+#endif /* 0 */
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_cmoption_menu_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkCMOptionMenu *option_menu;
+ GtkWidget *menu_item;
+
+ g_return_val_if_fail (GTK_IS_CMOPTION_MENU (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ option_menu = GTK_CMOPTION_MENU (widget);
+
+ if ((event->type == GDK_BUTTON_PRESS) &&
+ (event->button == 1))
+ {
+ gtk_cmoption_menu_remove_contents (option_menu);
+ gtk_menu_popup (GTK_MENU (option_menu->menu), NULL, NULL,
+ gtk_cmoption_menu_position, option_menu,
+ event->button, event->time);
+ menu_item = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+ if (menu_item)
+ gtk_menu_shell_select_item (GTK_MENU_SHELL (option_menu->menu), menu_item);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_cmoption_menu_key_press (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ GtkCMOptionMenu *option_menu;
+ GtkWidget *menu_item;
+
+ g_return_val_if_fail (GTK_IS_CMOPTION_MENU (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ option_menu = GTK_CMOPTION_MENU (widget);
+
+ switch (event->keyval)
+ {
+ case GDK_KP_Space:
+ case GDK_space:
+ gtk_cmoption_menu_remove_contents (option_menu);
+ gtk_menu_popup (GTK_MENU (option_menu->menu), NULL, NULL,
+ gtk_cmoption_menu_position, option_menu,
+ 0, event->time);
+ menu_item = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+ if (menu_item)
+ gtk_menu_shell_select_item (GTK_MENU_SHELL (option_menu->menu), menu_item);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_cmoption_menu_selection_done (GtkMenuShell *menu_shell,
+ GtkCMOptionMenu *option_menu)
+{
+ g_return_if_fail (menu_shell != NULL);
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+ gtk_cmoption_menu_update_contents (option_menu);
+}
+
+static void
+gtk_cmoption_menu_changed (GtkCMOptionMenu *option_menu)
+{
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+ g_signal_emit (option_menu, signals[CHANGED], 0);
+}
+
+static void
+gtk_cmoption_menu_select_first_sensitive (GtkCMOptionMenu *option_menu)
+{
+ if (option_menu->menu)
+ {
+ GList *children = GTK_MENU_SHELL (option_menu->menu)->children;
+ gint index = 0;
+
+ while (children)
+ {
+ if (GTK_WIDGET_SENSITIVE (children->data))
+ {
+ gtk_cmoption_menu_set_history (option_menu, index);
+ return;
+ }
+
+ children = children->next;
+ index++;
+ }
+ }
+}
+
+static void
+gtk_cmoption_menu_item_state_changed_cb (GtkWidget *widget,
+ GtkStateType previous_state,
+ GtkCMOptionMenu *option_menu)
+{
+ GtkWidget *child = GTK_BIN (option_menu)->child;
+
+ if (child && GTK_WIDGET_SENSITIVE (child) != GTK_WIDGET_IS_SENSITIVE (widget))
+ gtk_widget_set_sensitive (child, GTK_WIDGET_IS_SENSITIVE (widget));
+}
+
+static void
+gtk_cmoption_menu_item_destroy_cb (GtkWidget *widget,
+ GtkCMOptionMenu *option_menu)
+{
+ GtkWidget *child = GTK_BIN (option_menu)->child;
+
+ if (child)
+ {
+ g_object_ref (child);
+ gtk_cmoption_menu_remove_contents (option_menu);
+ gtk_widget_destroy (child);
+ g_object_unref (child);
+
+ gtk_cmoption_menu_select_first_sensitive (option_menu);
+ }
+}
+
+static void
+gtk_cmoption_menu_update_contents (GtkCMOptionMenu *option_menu)
+{
+ GtkWidget *child;
+ GtkRequisition child_requisition;
+
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+ if (option_menu->menu)
+ {
+ GtkWidget *old_item = option_menu->menu_item;
+
+ gtk_cmoption_menu_remove_contents (option_menu);
+
+ option_menu->menu_item = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+ if (option_menu->menu_item)
+ {
+ g_object_ref (option_menu->menu_item);
+ child = GTK_BIN (option_menu->menu_item)->child;
+ if (child)
+ {
+ if (!GTK_WIDGET_IS_SENSITIVE (option_menu->menu_item))
+ gtk_widget_set_sensitive (child, FALSE);
+ gtk_widget_reparent (child, GTK_WIDGET (option_menu));
+ }
+
+ g_signal_connect (option_menu->menu_item, "state_changed",
+ G_CALLBACK (gtk_cmoption_menu_item_state_changed_cb), option_menu);
+ g_signal_connect (option_menu->menu_item, "destroy",
+ G_CALLBACK (gtk_cmoption_menu_item_destroy_cb), option_menu);
+
+ gtk_widget_size_request (child, &child_requisition);
+ gtk_widget_size_allocate (GTK_WIDGET (option_menu),
+ &(GTK_WIDGET (option_menu)->allocation));
+
+ if (GTK_WIDGET_DRAWABLE (option_menu))
+ gtk_widget_queue_draw (GTK_WIDGET (option_menu));
+ }
+
+ if (old_item != option_menu->menu_item)
+ gtk_cmoption_menu_changed (option_menu);
+ }
+}
+
+static void
+gtk_cmoption_menu_remove_contents (GtkCMOptionMenu *option_menu)
+{
+ GtkWidget *child;
+
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+ if (option_menu->menu_item)
+ {
+ child = GTK_BIN (option_menu)->child;
+
+ if (child)
+ {
+ gtk_widget_set_sensitive (child, TRUE);
+ gtk_widget_set_state (child, GTK_STATE_NORMAL);
+ gtk_widget_reparent (child, option_menu->menu_item);
+ }
+
+ g_signal_handlers_disconnect_by_func (option_menu->menu_item,
+ gtk_cmoption_menu_item_state_changed_cb,
+ option_menu);
+ g_signal_handlers_disconnect_by_func (option_menu->menu_item,
+ gtk_cmoption_menu_item_destroy_cb,
+ option_menu);
+
+ g_object_unref (option_menu->menu_item);
+ option_menu->menu_item = NULL;
+ }
+}
+
+static void
+gtk_cmoption_menu_calc_size (GtkCMOptionMenu *option_menu)
+{
+ GtkWidget *child;
+ GList *children;
+ GtkRequisition child_requisition;
+ gint old_width = option_menu->width;
+ gint old_height = option_menu->height;
+
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+ option_menu->width = 0;
+ option_menu->height = 0;
+
+ if (option_menu->menu)
+ {
+ children = GTK_MENU_SHELL (option_menu->menu)->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child))
+ {
+ GtkWidget *inner = GTK_BIN (child)->child;
+
+ if (inner)
+ {
+ gtk_widget_size_request (inner, &child_requisition);
+
+ option_menu->width = MAX (option_menu->width, child_requisition.width);
+ option_menu->height = MAX (option_menu->height, child_requisition.height);
+ }
+ }
+ }
+ }
+
+ if (old_width != option_menu->width || old_height != option_menu->height)
+ gtk_widget_queue_resize (GTK_WIDGET (option_menu));
+}
+
+static void
+gtk_cmoption_menu_position (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gboolean *push_in,
+ gpointer user_data)
+{
+ GtkCMOptionMenu *option_menu;
+ GtkWidget *active;
+ GtkWidget *child;
+ GtkWidget *widget;
+ GtkRequisition requisition;
+ GList *children;
+ gint screen_width;
+ gint menu_xpos;
+ gint menu_ypos;
+ gint menu_width;
+
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (user_data));
+
+ option_menu = GTK_CMOPTION_MENU (user_data);
+ widget = GTK_WIDGET (option_menu);
+
+ gtk_widget_get_child_requisition (GTK_WIDGET (menu), &requisition);
+ menu_width = requisition.width;
+
+ active = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+ gdk_window_get_origin (widget->window, &menu_xpos, &menu_ypos);
+
+ menu_xpos += widget->allocation.x;
+ menu_ypos += widget->allocation.y + widget->allocation.height / 2 - 2;
+
+ if (active != NULL)
+ {
+ gtk_widget_get_child_requisition (active, &requisition);
+ menu_ypos -= requisition.height / 2;
+ }
+
+ children = GTK_MENU_SHELL (option_menu->menu)->children;
+ while (children)
+ {
+ child = children->data;
+
+ if (active == child)
+ break;
+
+ if (GTK_WIDGET_VISIBLE (child))
+ {
+ gtk_widget_get_child_requisition (child, &requisition);
+ menu_ypos -= requisition.height;
+ }
+
+ children = children->next;
+ }
+
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+ menu_xpos = menu_xpos + widget->allocation.width - menu_width;
+
+ /* Clamp the position on screen */
+ screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget));
+
+ if (menu_xpos < 0)
+ menu_xpos = 0;
+ else if ((menu_xpos + menu_width) > screen_width)
+ menu_xpos -= ((menu_xpos + menu_width) - screen_width);
+
+ *x = menu_xpos;
+ *y = menu_ypos;
+ *push_in = TRUE;
+}
+
+
+static void
+gtk_cmoption_menu_show_all (GtkWidget *widget)
+{
+ GtkContainer *container;
+ GtkCMOptionMenu *option_menu;
+
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (widget));
+ container = GTK_CONTAINER (widget);
+ option_menu = GTK_CMOPTION_MENU (widget);
+
+ gtk_widget_show (widget);
+ gtk_container_foreach (container, (GtkCallback) gtk_widget_show_all, NULL);
+ if (option_menu->menu)
+ gtk_widget_show_all (option_menu->menu);
+ if (option_menu->menu_item)
+ gtk_widget_show_all (option_menu->menu_item);
+}
+
+
+static void
+gtk_cmoption_menu_hide_all (GtkWidget *widget)
+{
+ GtkContainer *container;
+
+ g_return_if_fail (GTK_IS_CMOPTION_MENU (widget));
+ container = GTK_CONTAINER (widget);
+
+ gtk_widget_hide (widget);
+ gtk_container_foreach (container, (GtkCallback) gtk_widget_hide_all, NULL);
+}
+
+static gboolean
+gtk_cmoption_menu_mnemonic_activate (GtkWidget *widget,
+ gboolean group_cycling)
+{
+ gtk_widget_grab_focus (widget);
+ return TRUE;
+}
+
+static gint
+gtk_cmoption_menu_scroll_event (GtkWidget *widget,
+ GdkEventScroll *event)
+{
+ GtkCMOptionMenu *option_menu = GTK_CMOPTION_MENU (widget);
+ gint index;
+ gint n_children;
+ gint index_dir;
+ GList *l;
+ GtkMenuItem *item;
+
+ index = gtk_cmoption_menu_get_history (option_menu);
+
+ if (index != -1)
+ {
+ n_children = g_list_length (GTK_MENU_SHELL (option_menu->menu)->children);
+
+ if (event->direction == GDK_SCROLL_UP)
+ index_dir = -1;
+ else
+ index_dir = 1;
+
+
+ while (TRUE)
+ {
+ index += index_dir;
+
+ if (index < 0)
+ break;
+ if (index >= n_children)
+ break;
+
+ l = g_list_nth (GTK_MENU_SHELL (option_menu->menu)->children, index);
+ item = GTK_MENU_ITEM (l->data);
+ if (GTK_WIDGET_VISIBLE (item) && GTK_WIDGET_IS_SENSITIVE (item))
+ {
+ gtk_cmoption_menu_set_history (option_menu, index);
+ gtk_menu_item_activate (GTK_MENU_ITEM (item));
+ break;
+ }
+
+ }
+ }
+
+ return TRUE;
+}
+
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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/.
+ */
+
+#ifndef __GTK_CMOPTION_MENU_H__
+#define __GTK_CMOPTION_MENU_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkbutton.h>
+
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CMOPTION_MENU (gtk_cmoption_menu_get_type ())
+#define GTK_CMOPTION_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CMOPTION_MENU, GtkCMOptionMenu))
+#define GTK_CMOPTION_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CMOPTION_MENU, GtkCMOptionMenuClass))
+#define GTK_IS_CMOPTION_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CMOPTION_MENU))
+#define GTK_IS_CMOPTION_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CMOPTION_MENU))
+#define GTK_CMOPTION_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CMOPTION_MENU, GtkCMOptionMenuClass))
+
+
+typedef struct _GtkCMOptionMenu GtkCMOptionMenu;
+typedef struct _GtkCMOptionMenuClass GtkCMOptionMenuClass;
+
+struct _GtkCMOptionMenu
+{
+ GtkButton button;
+
+ GtkWidget *menu;
+ GtkWidget *menu_item;
+
+ guint16 width;
+ guint16 height;
+};
+
+struct _GtkCMOptionMenuClass
+{
+ GtkButtonClass parent_class;
+
+ void (*changed) (GtkCMOptionMenu *option_menu);
+
+ /* Padding for future expansion */
+ void (*_gtk_reserved1) (void);
+ void (*_gtk_reserved2) (void);
+ void (*_gtk_reserved3) (void);
+ void (*_gtk_reserved4) (void);
+};
+
+
+GType gtk_cmoption_menu_get_type (void) G_GNUC_CONST;
+GtkWidget* gtk_cmoption_menu_new (void);
+GtkWidget* gtk_cmoption_menu_get_menu (GtkCMOptionMenu *option_menu);
+void gtk_cmoption_menu_set_menu (GtkCMOptionMenu *option_menu,
+ GtkWidget *menu);
+void gtk_cmoption_menu_remove_menu (GtkCMOptionMenu *option_menu);
+gint gtk_cmoption_menu_get_history (GtkCMOptionMenu *option_menu);
+void gtk_cmoption_menu_set_history (GtkCMOptionMenu *option_menu,
+ guint index_);
+
+
+G_END_DECLS
+
+#endif /* __GTK_CMOPTION_MENU_H__ */
#include "prefs_common.h"
#include "utils.h"
-#define CLIST_UNFROZEN(clist) (((GtkCList*) (clist))->freeze_count == 0)
+#define CLIST_UNFROZEN(clist) (((GtkCMCList*) (clist))->freeze_count == 0)
#define CLIST_REFRESH(clist) G_STMT_START { \
if (CLIST_UNFROZEN (clist)) \
- GTK_CLIST_GET_CLASS (clist)->refresh ((GtkCList*) (clist)); \
+ GTK_CMCLIST_GET_CLASS (clist)->refresh ((GtkCMCList*) (clist)); \
} G_STMT_END
#define CELL_SPACING 1
#define CLIST_OPTIMUM_SIZE 64
gint x, gint y, GtkSelectionData *data,
guint info, guint time);
-static void gtk_sctree_clear (GtkCList *clist);
-static void gtk_sctree_real_unselect_all (GtkCList *clist);
-static void gtk_sctree_collapse (GtkCTree *ctree, GtkCTreeNode *node);
+static void gtk_sctree_clear (GtkCMCList *clist);
+static void gtk_sctree_real_unselect_all (GtkCMCList *clist);
+static void gtk_sctree_collapse (GtkCMCTree *ctree, GtkCMCTreeNode *node);
-static void stree_sort (GtkCTree *ctree, GtkCTreeNode *node, gpointer data);
-void gtk_sctree_sort_node (GtkCTree *ctree, GtkCTreeNode *node);
-void gtk_sctree_sort_recursive (GtkCTree *ctree, GtkCTreeNode *node);
-
-static void gtk_sctree_link (GtkCTree *ctree,
- GtkCTreeNode *node,
- GtkCTreeNode *parent,
- GtkCTreeNode *sibling,
+static void stree_sort (GtkCMCTree *ctree, GtkCMCTreeNode *node, gpointer data);
+void gtk_sctree_sort_node (GtkCMCTree *ctree, GtkCMCTreeNode *node);
+void gtk_sctree_sort_recursive (GtkCMCTree *ctree, GtkCMCTreeNode *node);
+
+static void gtk_sctree_link (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *sibling,
gboolean update_focus_row);
-static void gtk_sctree_unlink (GtkCTree *ctree,
- GtkCTreeNode *node,
+static void gtk_sctree_unlink (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
gboolean update_focus_row);
-static void stree_update_level (GtkCTree *ctree,
- GtkCTreeNode *node,
+static void stree_update_level (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
gpointer data);
-static GtkCTreeNode * gtk_sctree_last_visible (GtkCTree *ctree,
- GtkCTreeNode *node);
-static void gtk_sctree_real_tree_expand (GtkCTree *ctree,
- GtkCTreeNode *node);
+static GtkCMCTreeNode * gtk_sctree_last_visible (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+static void gtk_sctree_real_tree_expand (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
static void
-sreal_tree_move (GtkCTree *ctree,
- GtkCTreeNode *node,
- GtkCTreeNode *new_parent,
- GtkCTreeNode *new_sibling);
+sreal_tree_move (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *new_parent,
+ GtkCMCTreeNode *new_sibling);
-static GtkCTreeClass *parent_class;
+static GtkCMCTreeClass *parent_class;
static guint sctree_signals[LAST_SIGNAL];
(GInstanceInitFunc) gtk_sctree_init,
};
- sctree_type = g_type_register_static (GTK_TYPE_CTREE, "GtkSCTree", &sctree_info, (GTypeFlags)0);
+ sctree_type = g_type_register_static (GTK_TYPE_CMCTREE, "GtkSCTree", &sctree_info, (GTypeFlags)0);
}
return sctree_type;
height = clip_rectangle->y + clip_rectangle->height - y;
if (width > 0 && height > 0)
- gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
+ gdk_draw_drawable (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
if (mask)
{
}
static void
-gtk_sctree_get_cell_style (GtkCList *clist,
- GtkCListRow *clist_row,
+gtk_sctree_get_cell_style (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
gint state,
gint row,
gint column,
}
static gint
-gtk_sctree_draw_expander (GtkCTree *ctree,
- GtkCTreeRow *ctree_row,
+gtk_sctree_draw_expander (GtkCMCTree *ctree,
+ GtkCMCTreeRow *ctree_row,
GtkStyle *style,
GdkRectangle *clip_rectangle,
gint x)
{
- GtkCList *clist;
+ GtkCMCList *clist;
GdkPoint points[3];
gint justification_factor;
gint y;
- if (ctree->expander_style == GTK_CTREE_EXPANDER_NONE)
+ if (ctree->expander_style == GTK_CMCTREE_EXPANDER_NONE)
return x;
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
justification_factor = -1;
else
justification_factor = 1;
- if (!GTK_CLIST_ROW_HEIGHT_SET(GTK_CLIST(clist)))
+ if (!GTK_CMCLIST_ROW_HEIGHT_SET(GTK_CMCLIST(clist)))
y = (clip_rectangle->y + (clip_rectangle->height - PM_SIZE) / 2 -
(clip_rectangle->height + 1) % 2);
else
{
switch (ctree->expander_style)
{
- case GTK_CTREE_EXPANDER_NONE:
+ case GTK_CMCTREE_EXPANDER_NONE:
return x;
- case GTK_CTREE_EXPANDER_TRIANGLE:
+ case GTK_CMCTREE_EXPANDER_TRIANGLE:
return x + justification_factor * (PM_SIZE + 3);
- case GTK_CTREE_EXPANDER_SQUARE:
- case GTK_CTREE_EXPANDER_CIRCULAR:
+ case GTK_CMCTREE_EXPANDER_SQUARE:
+ case GTK_CMCTREE_EXPANDER_CIRCULAR:
return x + justification_factor * (PM_SIZE + 1);
}
}
switch (ctree->expander_style)
{
- case GTK_CTREE_EXPANDER_NONE:
+ case GTK_CMCTREE_EXPANDER_NONE:
break;
- case GTK_CTREE_EXPANDER_TRIANGLE:
+ case GTK_CMCTREE_EXPANDER_TRIANGLE:
if (ctree_row->expanded)
{
points[0].x = x;
x += justification_factor * (PM_SIZE + 3);
break;
- case GTK_CTREE_EXPANDER_SQUARE:
- case GTK_CTREE_EXPANDER_CIRCULAR:
+ case GTK_CMCTREE_EXPANDER_SQUARE:
+ case GTK_CMCTREE_EXPANDER_CIRCULAR:
if (justification_factor == -1)
x += justification_factor * (PM_SIZE + 1);
- if (ctree->expander_style == GTK_CTREE_EXPANDER_CIRCULAR)
+ if (ctree->expander_style == GTK_CMCTREE_EXPANDER_CIRCULAR)
{
gdk_draw_arc (clist->clist_window, style->base_gc[GTK_STATE_NORMAL],
TRUE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64);
}
static gint
-gtk_sctree_draw_lines (GtkCTree *ctree,
- GtkCTreeRow *ctree_row,
+gtk_sctree_draw_lines (GtkCMCTree *ctree,
+ GtkCMCTreeRow *ctree_row,
gint row,
gint column,
gint state,
GdkRectangle *area,
GtkStyle *style)
{
- GtkCList *clist;
- GtkCTreeNode *node;
- GtkCTreeNode *parent;
+ GtkCMCList *clist;
+ GtkCMCTreeNode *node;
+ GtkCMCTreeNode *parent;
GdkRectangle tree_rectangle;
GdkRectangle tc_rectangle;
GdkGC *bg_gc;
gint justify_right;
gint justification_factor;
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
ycenter = clip_rectangle->y + (clip_rectangle->height / 2);
justify_right = (clist->column[column].justification == GTK_JUSTIFY_RIGHT);
switch (ctree->line_style)
{
- case GTK_CTREE_LINES_NONE:
+ case GTK_CMCTREE_LINES_NONE:
break;
- case GTK_CTREE_LINES_TABBED:
+ case GTK_CMCTREE_LINES_TABBED:
xcenter = offset + justification_factor * TAB_SIZE;
column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
if (!ctree_row->sibling || (ctree_row->children && ctree_row->expanded))
{
- 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;
+ node = gtk_cmctree_find_node_ptr (ctree, ctree_row);
+ if (GTK_CMCTREE_NODE_NEXT (node))
+ next_level = GTK_CMCTREE_ROW (GTK_CMCTREE_NODE_NEXT (node))->level;
else
next_level = 0;
}
if ((justify_right && xcenter < column_left) ||
(!justify_right && xcenter > column_right))
{
- node = GTK_CTREE_ROW (node)->parent;
+ node = GTK_CMCTREE_ROW (node)->parent;
continue;
}
if (!area || gdk_rectangle_intersect (area, &tree_rectangle,
&tc_rectangle))
{
- gtk_sctree_get_cell_style (clist, >K_CTREE_ROW (node)->row,
+ gtk_sctree_get_cell_style (clist, >K_CMCTREE_ROW (node)->row,
state, row, 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->bg_gc, >K_CMCTREE_ROW (node)->row.background);
if (!area)
gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
tc_rectangle.width,
tc_rectangle.height);
}
- if (next_level > GTK_CTREE_ROW (node)->level)
+ if (next_level > GTK_CMCTREE_ROW (node)->level)
gdk_draw_line (clist->clist_window, ctree->lines_gc,
xcenter, crect->y,
xcenter, crect->y + crect->height);
offset_x = MIN (ctree->tree_indent, 2 * TAB_SIZE);
width = offset_x / 2 + offset_x % 2;
- parent = GTK_CTREE_ROW (node)->parent;
+ parent = GTK_CMCTREE_ROW (node)->parent;
tree_rectangle.y = ycenter;
tree_rectangle.height = (cell_rectangle->y - ycenter +
{
if (parent)
{
- gtk_sctree_get_cell_style (clist, >K_CTREE_ROW (parent)->row,
+ gtk_sctree_get_cell_style (clist, >K_CMCTREE_ROW (parent)->row,
state, row, column, NULL, NULL, &bg_gc);
if (bg_gc == clist->bg_gc)
gdk_gc_set_foreground
(clist->bg_gc,
- >K_CTREE_ROW (parent)->row.background);
+ >K_CMCTREE_ROW (parent)->row.background);
}
else if (state == GTK_STATE_SELECTED)
bg_gc = style->base_gc[state];
tc_rectangle.height);
}
- gtk_sctree_get_cell_style (clist, >K_CTREE_ROW (node)->row,
+ gtk_sctree_get_cell_style (clist, >K_CMCTREE_ROW (node)->row,
state, row, 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->bg_gc, >K_CMCTREE_ROW (node)->row.background);
gdk_gc_set_clip_rectangle (bg_gc, crect);
gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
offset_x, clist->row_height,
180 * 64, 90 * 64);
}
- node = GTK_CTREE_ROW (node)->parent;
+ node = GTK_CMCTREE_ROW (node)->parent;
}
}
offset_x = 1;
offset_y = 0;
- if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
+ if (ctree->line_style == GTK_CMCTREE_LINES_DOTTED)
{
offset_x += abs((clip_rectangle->x + clist->hoffset) % 2);
offset_y = abs((cell_rectangle->y + clist->voffset) % 2);
{
xcenter -= (justification_factor * ctree->tree_indent);
- if (GTK_CTREE_ROW (node)->sibling)
+ if (GTK_CMCTREE_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;
+ node = GTK_CMCTREE_ROW (node)->parent;
}
gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
clip_rectangle->y++;
}
static PangoLayout *
-sc_gtk_clist_create_cell_layout (GtkCList *clist,
- GtkCListRow *clist_row,
+sc_gtk_cmclist_create_cell_layout (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
gint column)
{
PangoLayout *layout;
GtkStyle *style;
- GtkCell *cell;
+ GtkCMCell *cell;
gchar *text;
gtk_sctree_get_cell_style (clist, clist_row, GTK_STATE_NORMAL, 0, column, &style,
cell = &clist_row->cell[column];
switch (cell->type)
{
- case GTK_CELL_TEXT:
- case GTK_CELL_PIXTEXT:
- text = ((cell->type == GTK_CELL_PIXTEXT) ?
- GTK_CELL_PIXTEXT (*cell)->text :
- GTK_CELL_TEXT (*cell)->text);
+ case GTK_CMCELL_TEXT:
+ case GTK_CMCELL_PIXTEXT:
+ text = ((cell->type == GTK_CMCELL_PIXTEXT) ?
+ GTK_CMCELL_PIXTEXT (*cell)->text :
+ GTK_CMCELL_TEXT (*cell)->text);
if (!text)
return NULL;
if (!GTK_SCTREE(clist)->use_markup[column]) {
layout = gtk_widget_create_pango_layout (GTK_WIDGET (clist),
- ((cell->type == GTK_CELL_PIXTEXT) ?
- GTK_CELL_PIXTEXT (*cell)->text :
- GTK_CELL_TEXT (*cell)->text));
+ ((cell->type == GTK_CMCELL_PIXTEXT) ?
+ GTK_CMCELL_PIXTEXT (*cell)->text :
+ GTK_CMCELL_TEXT (*cell)->text));
pango_layout_set_font_description (layout, style->font_desc);
} else {
PangoContext *context = gtk_widget_get_pango_context (GTK_WIDGET(clist));
}
static void
-gtk_sctree_draw_row (GtkCList *clist,
+gtk_sctree_draw_row (GtkCMCList *clist,
GdkRectangle *area,
gint row,
- GtkCListRow *clist_row)
+ GtkCMCListRow *clist_row)
{
GtkWidget *widget;
- GtkCTree *ctree;
+ GtkCMCTree *ctree;
GdkRectangle *rect;
GdkRectangle *crect;
GdkRectangle row_rectangle;
return;
widget = GTK_WIDGET (clist);
- ctree = GTK_CTREE (clist);
+ ctree = GTK_CMCTREE (clist);
/* if the function is passed the pointer to the row instead of null,
* it avoids this expensive lookup */
}
/* horizontal black lines */
- if (ctree->line_style == GTK_CTREE_LINES_TABBED)
+ if (ctree->line_style == GTK_CMCTREE_LINES_TABBED)
{
column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
case GTK_JUSTIFY_FILL:
case GTK_JUSTIFY_LEFT:
offset = (column_left + ctree->tree_indent *
- (((GtkCTreeRow *)clist_row)->level - 1));
+ (((GtkCMCTreeRow *)clist_row)->level - 1));
gdk_draw_line (clist->clist_window, ctree->lines_gc,
MIN (offset + TAB_SIZE, column_right),
break;
case GTK_JUSTIFY_RIGHT:
offset = (column_right - 1 - ctree->tree_indent *
- (((GtkCTreeRow *)clist_row)->level - 1));
+ (((GtkCMCTreeRow *)clist_row)->level - 1));
gdk_draw_line (clist->clist_window, ctree->lines_gc,
-1, cell_rectangle.y,
crect->x, crect->y, crect->width, crect->height);
/* horizontal black lines */
- if (ctree->line_style == GTK_CTREE_LINES_TABBED)
+ if (ctree->line_style == GTK_CMCTREE_LINES_TABBED)
{
switch (clist->column[ctree->tree_column].justification)
{
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) *
+ (((GtkCMCTreeRow *)clist_row)->level > 1) *
MIN (ctree->tree_indent / 2, TAB_SIZE),
column_right),
cell_rectangle.y,
-1, cell_rectangle.y,
MAX (column_right - TAB_SIZE - 1 -
COLUMN_INSET -
- (((GtkCTreeRow *)clist_row)->level > 1) *
+ (((GtkCMCTreeRow *)clist_row)->level > 1) *
MIN (ctree->tree_indent / 2, TAB_SIZE),
column_left - 1), cell_rectangle.y);
break;
crect->x, crect->y, crect->width, crect->height);
- layout = sc_gtk_clist_create_cell_layout (clist, clist_row, i);
+ layout = sc_gtk_cmclist_create_cell_layout (clist, clist_row, i);
if (layout)
{
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
switch (clist_row->cell[i].type)
{
- case GTK_CELL_PIXMAP:
- gdk_window_get_size
- (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &pixmap_width,
+ case GTK_CMCELL_PIXMAP:
+ gdk_drawable_get_size
+ (GTK_CMCELL_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)
+ case GTK_CMCELL_PIXTEXT:
+ if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
{
- gdk_window_get_size
- (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
+ gdk_drawable_get_size
+ (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
&pixmap_width, &height);
width += pixmap_width;
}
- 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;
+ if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->text &&
+ GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+ width += GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
if (i == ctree->tree_column)
width += (ctree->tree_indent *
- ((GtkCTreeRow *)clist_row)->level);
+ ((GtkCMCTreeRow *)clist_row)->level);
break;
default:
break;
if (i != ctree->tree_column)
{
int start_y = (clip_rectangle.height - height) / 2;
- if (GTK_CLIST_ROW_HEIGHT_SET(GTK_CLIST(clist)))
+ if (GTK_CMCLIST_ROW_HEIGHT_SET(GTK_CMCLIST(clist)))
start_y = (clip_rectangle.height/2 - height) / 2;
offset += clist_row->cell[i].horizontal;
switch (clist_row->cell[i].type)
{
- case GTK_CELL_PIXMAP:
+ case GTK_CMCELL_PIXMAP:
gtk_sctree_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,
+ GTK_CMCELL_PIXMAP (clist_row->cell[i])->pixmap,
+ GTK_CMCELL_PIXMAP (clist_row->cell[i])->mask,
offset,
clip_rectangle.y + clist_row->cell[i].vertical +
start_y,
pixmap_width, height);
break;
- case GTK_CELL_PIXTEXT:
+ case GTK_CMCELL_PIXTEXT:
offset = gtk_sctree_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,
+ GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+ GTK_CMCELL_PIXTEXT (clist_row->cell[i])->mask,
offset,
clip_rectangle.y + clist_row->cell[i].vertical +
start_y,
pixmap_width, height);
- offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
+ offset += GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
/* Fall through */
- case GTK_CELL_TEXT:
+ case GTK_CMCELL_TEXT:
if (layout)
{
gint row_center_offset = (clist->row_height - logical_rect.height) / 2;
}
/* draw lines */
- offset = gtk_sctree_draw_lines (ctree, (GtkCTreeRow *)clist_row, row, i,
+ offset = gtk_sctree_draw_lines (ctree, (GtkCMCTreeRow *)clist_row, row, i,
state, &clip_rectangle, &cell_rectangle,
crect, area, style);
/* draw expander */
- offset = gtk_sctree_draw_expander (ctree, (GtkCTreeRow *)clist_row,
+ offset = gtk_sctree_draw_expander (ctree, (GtkCMCTreeRow *)clist_row,
style, &clip_rectangle, offset);
if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
old_offset = offset;
offset = gtk_sctree_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,
+ GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+ GTK_CMCELL_PIXTEXT (clist_row->cell[i])->mask,
offset,
clip_rectangle.y + clist_row->cell[i].vertical
+ (clip_rectangle.height - height) / 2,
if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
{
offset = (old_offset - string_width);
- if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
- offset -= GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
+ if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+ offset -= GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
}
else
{
- if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
- offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
+ if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+ offset += GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
}
gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
}
static void
-gtk_sctree_change_focus_row_expansion (GtkCTree *ctree,
- GtkCTreeExpansionType action)
+gtk_sctree_change_focus_row_expansion (GtkCMCTree *ctree,
+ GtkCMCTreeExpansionType action)
{
- GtkCList *clist;
- GtkCTreeNode *node;
+ GtkCMCList *clist;
+ GtkCMCTreeNode *node;
- g_return_if_fail (GTK_IS_CTREE (ctree));
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (ctree))) &&
GTK_WIDGET_HAS_GRAB (ctree))
return;
if (!(node =
- GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row))) ||
- GTK_CTREE_ROW (node)->is_leaf || !(GTK_CTREE_ROW (node)->children))
+ GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row))) ||
+ GTK_CMCTREE_ROW (node)->is_leaf || !(GTK_CMCTREE_ROW (node)->children))
return;
switch (action)
{
- case GTK_CTREE_EXPANSION_EXPAND:
+ case GTK_CMCTREE_EXPANSION_EXPAND:
if (GTK_SCTREE(ctree)->always_expand_recursively)
- gtk_ctree_expand_recursive (ctree, node);
+ gtk_cmctree_expand_recursive (ctree, node);
else
- gtk_ctree_expand (ctree, node);
+ gtk_cmctree_expand (ctree, node);
break;
- case GTK_CTREE_EXPANSION_EXPAND_RECURSIVE:
- gtk_ctree_expand_recursive (ctree, node);
+ case GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE:
+ gtk_cmctree_expand_recursive (ctree, node);
break;
- case GTK_CTREE_EXPANSION_COLLAPSE:
- gtk_ctree_collapse (ctree, node);
+ case GTK_CMCTREE_EXPANSION_COLLAPSE:
+ gtk_cmctree_collapse (ctree, node);
break;
- case GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE:
- gtk_ctree_collapse_recursive (ctree, node);
+ case GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE:
+ gtk_cmctree_collapse_recursive (ctree, node);
break;
- case GTK_CTREE_EXPANSION_TOGGLE:
+ case GTK_CMCTREE_EXPANSION_TOGGLE:
if (GTK_SCTREE(ctree)->always_expand_recursively)
- gtk_ctree_toggle_expansion_recursive (ctree, node);
+ gtk_cmctree_toggle_expansion_recursive (ctree, node);
else
- gtk_ctree_toggle_expansion (ctree, node);
+ gtk_cmctree_toggle_expansion (ctree, node);
break;
- case GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE:
- gtk_ctree_toggle_expansion_recursive (ctree, node);
+ case GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE:
+ gtk_cmctree_toggle_expansion_recursive (ctree, node);
break;
}
}
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
- GtkCListClass *clist_class;
- GtkCTreeClass *ctree_class;
+ GtkCMCListClass *clist_class;
+ GtkCMCTreeClass *ctree_class;
object_class = (GtkObjectClass *) klass;
widget_class = (GtkWidgetClass *) klass;
- clist_class = (GtkCListClass *) klass;
- ctree_class = (GtkCTreeClass *) klass;
+ clist_class = (GtkCMCListClass *) klass;
+ ctree_class = (GtkCMCTreeClass *) klass;
- parent_class = gtk_type_class (gtk_ctree_get_type ());
+ parent_class = gtk_type_class (gtk_cmctree_get_type ());
sctree_signals[ROW_POPUP_MENU] =
g_signal_new ("row_popup_menu",
{
sctree->anchor_row = NULL;
- /* GtkCTree does not specify pointer motion by default */
+ /* GtkCMCTree does not specify pointer motion by default */
gtk_widget_add_events (GTK_WIDGET (sctree), GDK_POINTER_MOTION_MASK);
gtk_widget_add_events (GTK_WIDGET (sctree), GDK_POINTER_MOTION_MASK);
}
static gboolean
row_is_selected(GtkSCTree *sctree, gint row)
{
- GtkCListRow *clist_row;
- clist_row = g_list_nth (GTK_CLIST(sctree)->row_list, row)->data;
+ GtkCMCListRow *clist_row;
+ clist_row = g_list_nth (GTK_CMCLIST(sctree)->row_list, row)->data;
return clist_row ? clist_row->state == GTK_STATE_SELECTED : FALSE;
}
GList *node;
if (sctree->anchor_row == NULL) {
prev_row = row;
- sctree->anchor_row = gtk_ctree_node_nth(GTK_CTREE(sctree), row);
+ sctree->anchor_row = gtk_cmctree_node_nth(GTK_CMCTREE(sctree), row);
} else
- prev_row = g_list_position(GTK_CLIST(sctree)->row_list,
+ prev_row = g_list_position(GTK_CMCLIST(sctree)->row_list,
(GList *)sctree->anchor_row);
if (row < prev_row) {
min = row;
max = prev_row;
- GTK_CLIST(sctree)->focus_row = max;
+ GTK_CMCLIST(sctree)->focus_row = max;
} else {
min = prev_row;
max = row;
}
if (max - min > 10)
- gtk_clist_freeze(GTK_CLIST(sctree));
+ gtk_cmclist_freeze(GTK_CMCLIST(sctree));
- node = g_list_nth((GTK_CLIST(sctree))->row_list, min);
+ node = g_list_nth((GTK_CMCLIST(sctree))->row_list, min);
for (i = min; i < max; i++) {
- if (node && GTK_CTREE_ROW (node)->row.selectable) {
+ if (node && GTK_CMCTREE_ROW (node)->row.selectable) {
g_signal_emit_by_name(G_OBJECT(sctree), "tree_select_row",
node, -1);
}
node = node->next;
}
if (max - min > 10)
- gtk_clist_thaw(GTK_CLIST(sctree));
+ gtk_cmclist_thaw(GTK_CMCLIST(sctree));
sctree->selecting_range--;
- gtk_clist_select_row (GTK_CLIST (sctree), max, -1);
+ gtk_cmclist_select_row (GTK_CMCLIST (sctree), max, -1);
}
/* Handles row selection according to the specified modifier state */
-/* in certain cases, we arrive here from a function knowing the GtkCTreeNode, and having
+/* in certain cases, we arrive here from a function knowing the GtkCMCTreeNode, and having
* already slowly found row using g_list_position. In which case, _node will be non-NULL
* to avoid this function having to slowly find it with g_list_nth. */
static void
-select_row (GtkSCTree *sctree, gint row, gint col, guint state, GtkCTreeNode *_node)
+select_row (GtkSCTree *sctree, gint row, gint col, guint state, GtkCMCTreeNode *_node)
{
gboolean range, additive;
g_return_if_fail (sctree != NULL);
g_return_if_fail (GTK_IS_SCTREE (sctree));
range = ((state & GDK_SHIFT_MASK) != 0) &&
- (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_SINGLE) &&
- (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_BROWSE);
+ (GTK_CMCLIST(sctree)->selection_mode != GTK_SELECTION_SINGLE) &&
+ (GTK_CMCLIST(sctree)->selection_mode != GTK_SELECTION_BROWSE);
additive = ((state & GDK_CONTROL_MASK) != 0) &&
- (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_SINGLE) &&
- (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_BROWSE);
+ (GTK_CMCLIST(sctree)->selection_mode != GTK_SELECTION_SINGLE) &&
+ (GTK_CMCLIST(sctree)->selection_mode != GTK_SELECTION_BROWSE);
if (!range && !additive && sctree->force_additive_sel)
additive = TRUE;
- GTK_CLIST(sctree)->focus_row = row;
+ GTK_CMCLIST(sctree)->focus_row = row;
if (!additive) {
- gtk_clist_unselect_all (GTK_CLIST (sctree));
+ gtk_cmclist_unselect_all (GTK_CMCLIST (sctree));
}
if (!range) {
- GtkCTreeNode *node;
+ GtkCMCTreeNode *node;
- node = _node ? _node : gtk_ctree_node_nth (GTK_CTREE(sctree), row);
+ node = _node ? _node : gtk_cmctree_node_nth (GTK_CMCTREE(sctree), row);
/*No need to manage overlapped list*/
if (additive) {
if (row_is_selected(sctree, row))
- gtk_clist_unselect_row (GTK_CLIST (sctree), row, col);
+ gtk_cmclist_unselect_row (GTK_CMCLIST (sctree), row, col);
else
g_signal_emit_by_name
(G_OBJECT (sctree),
static gboolean
sctree_is_hot_spot (GtkSCTree *sctree,
- GtkCTreeNode *node,
+ GtkCMCTreeNode *node,
gint row,
gint x,
gint y)
{
- GtkCTreeRow *tree_row;
- GtkCList *clist;
- GtkCTree *ctree;
- GtkCellPixText *cell;
+ GtkCMCTreeRow *tree_row;
+ GtkCMCList *clist;
+ GtkCMCTree *ctree;
+ GtkCMCellPixText *cell;
gint xl, xmax;
gint yu;
g_return_val_if_fail (GTK_IS_SCTREE (sctree), FALSE);
g_return_val_if_fail (node != NULL, FALSE);
- clist = GTK_CLIST (sctree);
- ctree = GTK_CTREE (sctree);
+ clist = GTK_CMCLIST (sctree);
+ ctree = GTK_CMCTREE (sctree);
if (!clist->column[ctree->tree_column].visible ||
- ctree->expander_style == GTK_CTREE_EXPANDER_NONE)
+ ctree->expander_style == GTK_CMCTREE_EXPANDER_NONE)
return FALSE;
- tree_row = GTK_CTREE_ROW (node);
+ tree_row = GTK_CMCTREE_ROW (node);
- cell = GTK_CELL_PIXTEXT (tree_row->row.cell[ctree->tree_column]);
+ cell = GTK_CMCELL_PIXTEXT (tree_row->row.cell[ctree->tree_column]);
- if (!GTK_CLIST_ROW_HEIGHT_SET(GTK_CLIST(clist)))
+ if (!GTK_CMCLIST_ROW_HEIGHT_SET(GTK_CMCLIST(clist)))
yu = (ROW_TOP_YPIXEL (clist, row) + (clist->row_height - PM_SIZE) / 2 -
(clist->row_height - 1) % 2);
else
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);
+ (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
else
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);
+ (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
xmax = xl + PM_SIZE;
#else
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);
+ (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
xmax = xl + PM_SIZE;
} else if (ctree->tree_column == 0) {
xl = (clist->column[ctree->tree_column].area.x + clist->hoffset +
- (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
+ (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
xmax = (clist->column[ctree->tree_column].area.x + clist->hoffset +
(tree_row->level - 1) * ctree->tree_indent +
- (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3) +
+ (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3) +
PM_SIZE;
} else {
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);
+ (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
xmax = xl + PM_SIZE;
}
#endif
gint x,
gint y)
{
- GtkCTreeNode *node;
+ GtkCMCTreeNode *node;
gint column;
gint row;
g_return_val_if_fail (GTK_IS_SCTREE (ctree), FALSE);
- if (gtk_clist_get_selection_info (GTK_CLIST (ctree), x, y, &row, &column))
- if ((node = GTK_CTREE_NODE(g_list_nth (GTK_CLIST (ctree)->row_list, row))))
+ if (gtk_cmclist_get_selection_info (GTK_CMCLIST (ctree), x, y, &row, &column))
+ if ((node = GTK_CMCTREE_NODE(g_list_nth (GTK_CMCLIST (ctree)->row_list, row))))
return sctree_is_hot_spot (ctree, node, row, x, y);
return FALSE;
}
-/* Our handler for button_press events. We override all of GtkCList's broken
+/* Our handler for button_press events. We override all of GtkCMCList's broken
* behavior.
*/
static gint
gtk_sctree_button_press (GtkWidget *widget, GdkEventButton *event)
{
GtkSCTree *sctree;
- GtkCList *clist;
+ GtkCMCList *clist;
gboolean on_row;
gint row;
gint col;
g_return_val_if_fail (event != NULL, FALSE);
sctree = GTK_SCTREE (widget);
- clist = GTK_CLIST (widget);
+ clist = GTK_CMCLIST (widget);
retval = FALSE;
if (event->window != clist->clist_window)
return (* GTK_WIDGET_CLASS (parent_class)->button_press_event) (widget, event);
- on_row = gtk_clist_get_selection_info (clist, event->x, event->y, &row, &col);
+ on_row = gtk_cmclist_get_selection_info (clist, event->x, event->y, &row, &col);
if (on_row && !GTK_WIDGET_HAS_FOCUS(widget))
gtk_widget_grab_focus (widget);
if (gtk_sctree_is_hot_spot (GTK_SCTREE(sctree), event->x, event->y)) {
- GtkCTreeNode *node = gtk_ctree_node_nth(GTK_CTREE(sctree), row);
- if (GTK_CTREE_ROW (node)->expanded)
- gtk_ctree_collapse(GTK_CTREE(sctree), node);
+ GtkCMCTreeNode *node = gtk_cmctree_node_nth(GTK_CMCTREE(sctree), row);
+ if (GTK_CMCTREE_ROW (node)->expanded)
+ gtk_cmctree_collapse(GTK_CMCTREE(sctree), node);
else if (GTK_SCTREE(sctree)->always_expand_recursively)
- gtk_ctree_expand_recursive (GTK_CTREE(sctree), node);
+ gtk_cmctree_expand_recursive (GTK_CMCTREE(sctree), node);
else
- gtk_ctree_expand(GTK_CTREE(sctree), node);
+ gtk_cmctree_expand(GTK_CMCTREE(sctree), node);
return TRUE;
}
select_row (sctree, row, col, event->state, NULL);
}
} else {
- gtk_clist_unselect_all (clist);
+ gtk_cmclist_unselect_all (clist);
}
retval = TRUE;
sctree_signals[ROW_POPUP_MENU],
0, event);
} else {
- gtk_clist_unselect_all(clist);
+ gtk_cmclist_unselect_all(clist);
g_signal_emit (G_OBJECT (sctree),
sctree_signals[EMPTY_POPUP_MENU],
0, event);
return retval;
}
-/* Our handler for button_release events. We override all of GtkCList's broken
+/* Our handler for button_release events. We override all of GtkCMCList's broken
* behavior.
*/
static gint
gtk_sctree_button_release (GtkWidget *widget, GdkEventButton *event)
{
GtkSCTree *sctree;
- GtkCList *clist;
+ GtkCMCList *clist;
gint on_row;
gint row, col;
gint retval;
g_return_val_if_fail (event != NULL, FALSE);
sctree = GTK_SCTREE (widget);
- clist = GTK_CLIST (widget);
+ clist = GTK_CMCLIST (widget);
retval = FALSE;
if (event->window != clist->clist_window)
return (* GTK_WIDGET_CLASS (parent_class)->button_release_event) (widget, event);
- on_row = gtk_clist_get_selection_info (clist, event->x, event->y, &row, &col);
+ on_row = gtk_cmclist_get_selection_info (clist, event->x, event->y, &row, &col);
if (!(event->button == 1 || event->button == 2))
return FALSE;
return retval;
}
-/* Our handler for motion_notify events. We override all of GtkCList's broken
+/* Our handler for motion_notify events. We override all of GtkCMCList's broken
* behavior.
*/
static gint
gtk_sctree_motion (GtkWidget *widget, GdkEventMotion *event)
{
GtkSCTree *sctree;
- GtkCList *clist;
+ GtkCMCList *clist;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_SCTREE (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
sctree = GTK_SCTREE (widget);
- clist = GTK_CLIST (widget);
+ clist = GTK_CMCLIST (widget);
if (event->window != clist->clist_window)
return (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) (widget, event);
* to null.
*/
static void
-gtk_sctree_clear (GtkCList *clist)
+gtk_sctree_clear (GtkCMCList *clist)
{
GtkSCTree *sctree;
sctree = GTK_SCTREE (clist);
sctree->anchor_row = NULL;
- if (((GtkCListClass *)parent_class)->clear)
- (* ((GtkCListClass *)parent_class)->clear) (clist);
+ if (((GtkCMCListClass *)parent_class)->clear)
+ (* ((GtkCMCListClass *)parent_class)->clear) (clist);
}
static void
-gtk_sctree_real_unselect_all (GtkCList *clist)
+gtk_sctree_real_unselect_all (GtkCMCList *clist)
{
GtkSCTree *sctree;
gboolean should_freeze = FALSE;
sctree = GTK_SCTREE (clist);
- if (sc_g_list_bigger(GTK_CLIST(sctree)->selection, 10)) {
+ if (sc_g_list_bigger(GTK_CMCLIST(sctree)->selection, 10)) {
should_freeze = TRUE;
sctree->selecting_range++;
- gtk_clist_freeze (GTK_CLIST (sctree));
+ gtk_cmclist_freeze (GTK_CMCLIST (sctree));
}
- if (((GtkCListClass *)parent_class)->unselect_all)
- (* ((GtkCListClass *)parent_class)->unselect_all) (clist);
+ if (((GtkCMCListClass *)parent_class)->unselect_all)
+ (* ((GtkCMCListClass *)parent_class)->unselect_all) (clist);
if (should_freeze) {
- gtk_clist_thaw (GTK_CLIST (sctree));
+ gtk_cmclist_thaw (GTK_CMCLIST (sctree));
sctree->selecting_range--;
}
}
We have to set the anchor to parent visible node.
*/
static void
-gtk_sctree_collapse (GtkCTree *ctree, GtkCTreeNode *node)
+gtk_sctree_collapse (GtkCMCTree *ctree, GtkCMCTreeNode *node)
{
g_return_if_fail (ctree != NULL);
g_return_if_fail (GTK_IS_SCTREE (ctree));
(* parent_class->tree_collapse) (ctree, node);
GTK_SCTREE(ctree)->anchor_row =
- gtk_ctree_node_nth(ctree, GTK_CLIST(ctree)->focus_row);
+ gtk_cmctree_node_nth(ctree, GTK_CMCLIST(ctree)->focus_row);
}
GtkWidget *gtk_sctree_new_with_titles (gint columns, gint tree_column,
"tree_column", tree_column,
NULL);
if (titles) {
- GtkCList *clist = GTK_CLIST (widget);
+ GtkCMCList *clist = GTK_CMCLIST (widget);
guint i;
for (i = 0; i < columns; i++)
- gtk_clist_set_column_title (clist, i, titles[i]);
- gtk_clist_column_titles_show (clist);
+ gtk_cmclist_set_column_title (clist, i, titles[i]);
+ gtk_cmclist_column_titles_show (clist);
}
GTK_SCTREE(widget)->show_stripes = TRUE;
sctree->use_markup[column] = markup;
}
-void gtk_sctree_select (GtkSCTree *sctree, GtkCTreeNode *node)
+void gtk_sctree_select (GtkSCTree *sctree, GtkCMCTreeNode *node)
{
select_row(sctree,
- g_list_position(GTK_CLIST(sctree)->row_list, (GList *)node),
+ g_list_position(GTK_CMCLIST(sctree)->row_list, (GList *)node),
-1, 0, node);
}
-void gtk_sctree_select_with_state (GtkSCTree *sctree, GtkCTreeNode *node, int state)
+void gtk_sctree_select_with_state (GtkSCTree *sctree, GtkCMCTreeNode *node, int state)
{
select_row(sctree,
- g_list_position(GTK_CLIST(sctree)->row_list, (GList *)node),
+ g_list_position(GTK_CMCLIST(sctree)->row_list, (GList *)node),
-1, state, node);
}
void gtk_sctree_unselect_all (GtkSCTree *sctree)
{
- gtk_clist_unselect_all(GTK_CLIST(sctree));
+ gtk_cmclist_unselect_all(GTK_CMCLIST(sctree));
sctree->anchor_row = NULL;
}
-void gtk_sctree_set_anchor_row (GtkSCTree *sctree, GtkCTreeNode *node)
+void gtk_sctree_set_anchor_row (GtkSCTree *sctree, GtkCMCTreeNode *node)
{
sctree->anchor_row = node;
}
-void gtk_sctree_remove_node (GtkSCTree *sctree, GtkCTreeNode *node)
+void gtk_sctree_remove_node (GtkSCTree *sctree, GtkCMCTreeNode *node)
{
if (sctree->anchor_row == node)
sctree->anchor_row = NULL;
- gtk_ctree_remove_node(GTK_CTREE(sctree), node);
+ gtk_cmctree_remove_node(GTK_CMCTREE(sctree), node);
}
void gtk_sctree_set_stripes(GtkSCTree *sctree, gboolean show_stripes)
* Tree sorting functions *
***********************************************************/
-static void sink(GtkCList *clist, GPtrArray *numbers, gint root, gint bottom)
+static void sink(GtkCMCList *clist, GPtrArray *numbers, gint root, gint bottom)
{
gint j, k ;
- GtkCTreeNode *temp;
+ GtkCMCTreeNode *temp;
j = 2 * root;
k = j + 1;
/* find the maximum element of numbers[root],
numbers[2*root] and numbers[2*root+1] */
if (j <= bottom) {
- if (clist->compare( clist, GTK_CTREE_ROW (g_ptr_array_index(numbers, root)),
- GTK_CTREE_ROW(g_ptr_array_index( numbers, j))) >= 0)
+ if (clist->compare( clist, GTK_CMCTREE_ROW (g_ptr_array_index(numbers, root)),
+ GTK_CMCTREE_ROW(g_ptr_array_index( numbers, j))) >= 0)
j = root;
if (k <= bottom)
- if (clist->compare( clist, GTK_CTREE_ROW (g_ptr_array_index(numbers, k)),
- GTK_CTREE_ROW (g_ptr_array_index( numbers, j))) > 0)
+ if (clist->compare( clist, GTK_CMCTREE_ROW (g_ptr_array_index(numbers, k)),
+ GTK_CMCTREE_ROW (g_ptr_array_index( numbers, j))) > 0)
j = k;
/* if numbers[root] wasn't the maximum element then
sink again */
}
}
-static void heap_sort(GtkCList *clist, GPtrArray *numbers, gint array_size)
+static void heap_sort(GtkCMCList *clist, GPtrArray *numbers, gint array_size)
{
gint i;
- GtkCTreeNode *temp;
+ GtkCMCTreeNode *temp;
/* build the Heap */
for (i = (array_size / 2); i >= 1; i--)
}
static void
-stree_sort (GtkCTree *ctree,
- GtkCTreeNode *node,
+stree_sort (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
gpointer data)
{
- GtkCTreeNode *list_start, *work, *next;
+ GtkCMCTreeNode *list_start, *work, *next;
GPtrArray *row_array, *viewable_array;
- GtkCList *clist;
+ GtkCMCList *clist;
gint i;
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
if (node)
- work = GTK_CTREE_ROW (node)->children;
+ work = GTK_CMCTREE_ROW (node)->children;
else
- work = GTK_CTREE_NODE (clist->row_list);
+ work = GTK_CMCTREE_NODE (clist->row_list);
row_array = g_ptr_array_new();
viewable_array = g_ptr_array_new();
while (work) {
/* add all rows to row_array */
g_ptr_array_add( row_array, work);
- if (GTK_CTREE_ROW (work)->parent && gtk_ctree_is_viewable( ctree, work))
- g_ptr_array_add( viewable_array, GTK_CTREE_ROW (work)->parent);
- next = GTK_CTREE_ROW (work)->sibling;
+ if (GTK_CMCTREE_ROW (work)->parent && gtk_cmctree_is_viewable( ctree, work))
+ g_ptr_array_add( viewable_array, GTK_CMCTREE_ROW (work)->parent);
+ next = GTK_CMCTREE_ROW (work)->sibling;
gtk_sctree_unlink( ctree, work, FALSE);
work = next;
}
heap_sort( clist, row_array, (row_array->len)-1);
if (node)
- list_start = GTK_CTREE_ROW (node)->children;
+ list_start = GTK_CMCTREE_ROW (node)->children;
else
- list_start = GTK_CTREE_NODE (clist->row_list);
+ list_start = GTK_CMCTREE_NODE (clist->row_list);
if (clist->sort_type == GTK_SORT_ASCENDING) {
for (i=(row_array->len)-1; i>=1; i--) {
}
for (i=0; i<viewable_array->len; i++) {
- gtk_ctree_expand( ctree, g_ptr_array_index( viewable_array, i));
+ gtk_cmctree_expand( ctree, g_ptr_array_index( viewable_array, i));
}
}
}
void
-gtk_sctree_sort_recursive (GtkCTree *ctree,
- GtkCTreeNode *node)
+gtk_sctree_sort_recursive (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
{
- GtkCList *clist;
- GtkCTreeNode *focus_node = NULL;
+ GtkCMCList *clist;
+ GtkCMCTreeNode *focus_node = NULL;
g_return_if_fail (ctree != NULL);
- g_return_if_fail (GTK_IS_CTREE (ctree));
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
- gtk_clist_freeze (clist);
+ gtk_cmclist_freeze (clist);
if (clist->selection_mode == GTK_SELECTION_EXTENDED) {
- GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
g_list_free (clist->undo_selection);
g_list_free (clist->undo_unselection);
clist->undo_unselection = NULL;
}
- if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
- focus_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
+ if (!node || (node && gtk_cmctree_is_viewable (ctree, node)))
+ focus_node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
GTK_SCTREE(ctree)->sorting = TRUE;
- gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (stree_sort), NULL);
+ gtk_cmctree_post_recursive (ctree, node, GTK_CMCTREE_FUNC (stree_sort), NULL);
if (!node)
stree_sort (ctree, NULL, NULL);
clist->undo_anchor = clist->focus_row;
}
- gtk_clist_thaw (clist);
+ gtk_cmclist_thaw (clist);
}
void
-gtk_sctree_sort_node (GtkCTree *ctree,
- GtkCTreeNode *node)
+gtk_sctree_sort_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
{
- GtkCList *clist;
- GtkCTreeNode *focus_node = NULL;
+ GtkCMCList *clist;
+ GtkCMCTreeNode *focus_node = NULL;
g_return_if_fail (ctree != NULL);
- g_return_if_fail (GTK_IS_CTREE (ctree));
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
- gtk_clist_freeze (clist);
+ gtk_cmclist_freeze (clist);
if (clist->selection_mode == GTK_SELECTION_EXTENDED) {
- GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
g_list_free (clist->undo_selection);
g_list_free (clist->undo_unselection);
clist->undo_unselection = NULL;
}
- if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
- focus_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
+ if (!node || (node && gtk_cmctree_is_viewable (ctree, node)))
+ focus_node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
GTK_SCTREE(ctree)->sorting = TRUE;
clist->undo_anchor = clist->focus_row;
}
- gtk_clist_thaw (clist);
+ gtk_cmclist_thaw (clist);
}
/************************************************************************/
static void
-gtk_sctree_unlink (GtkCTree *ctree,
- GtkCTreeNode *node,
+gtk_sctree_unlink (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
gboolean update_focus_row)
{
- GtkCList *clist;
+ GtkCMCList *clist;
gint rows;
gint level;
gint visible;
- GtkCTreeNode *work;
- GtkCTreeNode *parent;
+ GtkCMCTreeNode *work;
+ GtkCMCTreeNode *parent;
GList *list;
g_return_if_fail (ctree != NULL);
- g_return_if_fail (GTK_IS_CTREE (ctree));
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
g_return_if_fail (node != NULL);
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED) {
- GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
g_list_free (clist->undo_selection);
g_list_free (clist->undo_unselection);
clist->undo_unselection = NULL;
}
- visible = gtk_ctree_is_viewable (ctree, node);
+ visible = gtk_cmctree_is_viewable (ctree, node);
/* clist->row_list_end unlinked ? */
- if (visible && (GTK_CTREE_NODE_NEXT (node) == NULL ||
- (GTK_CTREE_ROW (node)->children && gtk_ctree_is_ancestor (ctree, node,
- GTK_CTREE_NODE (clist->row_list_end)))))
- clist->row_list_end = (GList *) (GTK_CTREE_NODE_PREV (node));
+ if (visible && (GTK_CMCTREE_NODE_NEXT (node) == NULL ||
+ (GTK_CMCTREE_ROW (node)->children && gtk_cmctree_is_ancestor (ctree, node,
+ GTK_CMCTREE_NODE (clist->row_list_end)))))
+ clist->row_list_end = (GList *) (GTK_CMCTREE_NODE_PREV (node));
/* update list */
rows = 0;
- level = GTK_CTREE_ROW (node)->level;
- work = GTK_CTREE_NODE_NEXT (node);
- while (work && GTK_CTREE_ROW (work)->level > level) {
- work = GTK_CTREE_NODE_NEXT (work);
+ level = GTK_CMCTREE_ROW (node)->level;
+ work = GTK_CMCTREE_NODE_NEXT (node);
+ while (work && GTK_CMCTREE_ROW (work)->level > level) {
+ work = GTK_CMCTREE_NODE_NEXT (work);
rows++;
}
if (pos + rows < clist->focus_row)
clist->focus_row -= (rows + 1);
else if (pos <= clist->focus_row) {
- if (!GTK_CTREE_ROW (node)->sibling)
+ if (!GTK_CMCTREE_ROW (node)->sibling)
clist->focus_row = MAX (pos - 1, 0);
else
clist->focus_row = pos;
}
if (work) {
- list = (GList *)GTK_CTREE_NODE_PREV (work);
+ list = (GList *)GTK_CMCTREE_NODE_PREV (work);
list->next = NULL;
list = (GList *)work;
- list->prev = (GList *)GTK_CTREE_NODE_PREV (node);
+ list->prev = (GList *)GTK_CMCTREE_NODE_PREV (node);
}
- if (GTK_CTREE_NODE_PREV (node) &&
- GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) == node) {
- list = (GList *)GTK_CTREE_NODE_PREV (node);
+ if (GTK_CMCTREE_NODE_PREV (node) &&
+ GTK_CMCTREE_NODE_NEXT (GTK_CMCTREE_NODE_PREV (node)) == node) {
+ list = (GList *)GTK_CMCTREE_NODE_PREV (node);
list->next = (GList *)work;
}
/* update tree */
- parent = GTK_CTREE_ROW (node)->parent;
+ parent = GTK_CMCTREE_ROW (node)->parent;
if (parent) {
- if (GTK_CTREE_ROW (parent)->children == node) {
- GTK_CTREE_ROW (parent)->children = GTK_CTREE_ROW (node)->sibling;
+ if (GTK_CMCTREE_ROW (parent)->children == node) {
+ GTK_CMCTREE_ROW (parent)->children = GTK_CMCTREE_ROW (node)->sibling;
}
else {
- GtkCTreeNode *sibling;
+ GtkCMCTreeNode *sibling;
- sibling = GTK_CTREE_ROW (parent)->children;
- while (GTK_CTREE_ROW (sibling)->sibling != node)
- sibling = GTK_CTREE_ROW (sibling)->sibling;
- GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
+ sibling = GTK_CMCTREE_ROW (parent)->children;
+ while (GTK_CMCTREE_ROW (sibling)->sibling != node)
+ sibling = GTK_CMCTREE_ROW (sibling)->sibling;
+ GTK_CMCTREE_ROW (sibling)->sibling = GTK_CMCTREE_ROW (node)->sibling;
}
}
else {
if (clist->row_list == (GList *)node)
- clist->row_list = (GList *) (GTK_CTREE_ROW (node)->sibling);
+ clist->row_list = (GList *) (GTK_CMCTREE_ROW (node)->sibling);
else {
- GtkCTreeNode *sibling;
+ GtkCMCTreeNode *sibling;
- sibling = GTK_CTREE_NODE (clist->row_list);
- while (GTK_CTREE_ROW (sibling)->sibling != node)
- sibling = GTK_CTREE_ROW (sibling)->sibling;
- GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
+ sibling = GTK_CMCTREE_NODE (clist->row_list);
+ while (GTK_CMCTREE_ROW (sibling)->sibling != node)
+ sibling = GTK_CMCTREE_ROW (sibling)->sibling;
+ GTK_CMCTREE_ROW (sibling)->sibling = GTK_CMCTREE_ROW (node)->sibling;
}
}
}
static void
-gtk_sctree_link (GtkCTree *ctree,
- GtkCTreeNode *node,
- GtkCTreeNode *parent,
- GtkCTreeNode *sibling,
+gtk_sctree_link (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *sibling,
gboolean update_focus_row)
{
- GtkCList *clist;
+ GtkCMCList *clist;
GList *list_end;
GList *list;
GList *work;
gint rows = 0;
if (sibling)
- g_return_if_fail (GTK_CTREE_ROW (sibling)->parent == parent);
+ g_return_if_fail (GTK_CMCTREE_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);
+ clist = GTK_CMCLIST (ctree);
if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED) {
- GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
g_list_free (clist->undo_selection);
g_list_free (clist->undo_unselection);
list_end = list_end->next)
rows++;
- GTK_CTREE_ROW (node)->parent = parent;
- GTK_CTREE_ROW (node)->sibling = sibling;
+ GTK_CMCTREE_ROW (node)->parent = parent;
+ GTK_CMCTREE_ROW (node)->sibling = sibling;
- if (!parent || (parent && (gtk_ctree_is_viewable (ctree, parent) &&
- GTK_CTREE_ROW (parent)->expanded))) {
+ if (!parent || (parent && (gtk_cmctree_is_viewable (ctree, parent) &&
+ GTK_CMCTREE_ROW (parent)->expanded))) {
visible = TRUE;
clist->rows += rows;
}
if (parent)
- work = (GList *)(GTK_CTREE_ROW (parent)->children);
+ work = (GList *)(GTK_CMCTREE_ROW (parent)->children);
else
work = clist->row_list;
if (sibling) {
if (work != (GList *)sibling) {
- while (GTK_CTREE_ROW (work)->sibling != sibling)
- work = (GList *)(GTK_CTREE_ROW (work)->sibling);
- GTK_CTREE_ROW (work)->sibling = node;
+ while (GTK_CMCTREE_ROW (work)->sibling != sibling)
+ work = (GList *)(GTK_CMCTREE_ROW (work)->sibling);
+ GTK_CMCTREE_ROW (work)->sibling = node;
}
- if (sibling == GTK_CTREE_NODE (clist->row_list))
+ if (sibling == GTK_CMCTREE_NODE (clist->row_list))
clist->row_list = (GList *) node;
- if (GTK_CTREE_NODE_PREV (sibling) &&
- GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) == sibling) {
- list = (GList *)GTK_CTREE_NODE_PREV (sibling);
+ if (GTK_CMCTREE_NODE_PREV (sibling) &&
+ GTK_CMCTREE_NODE_NEXT (GTK_CMCTREE_NODE_PREV (sibling)) == sibling) {
+ list = (GList *)GTK_CMCTREE_NODE_PREV (sibling);
list->next = (GList *)node;
}
list = (GList *)node;
- list->prev = (GList *)GTK_CTREE_NODE_PREV (sibling);
+ list->prev = (GList *)GTK_CMCTREE_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;
+ if (parent && GTK_CMCTREE_ROW (parent)->children == sibling)
+ GTK_CMCTREE_ROW (parent)->children = node;
}
else {
if (work) {
/* find sibling */
- while (GTK_CTREE_ROW (work)->sibling)
- work = (GList *)(GTK_CTREE_ROW (work)->sibling);
- GTK_CTREE_ROW (work)->sibling = node;
+ while (GTK_CMCTREE_ROW (work)->sibling)
+ work = (GList *)(GTK_CMCTREE_ROW (work)->sibling);
+ GTK_CMCTREE_ROW (work)->sibling = node;
/* find last visible child of sibling */
work = (GList *) gtk_sctree_last_visible (ctree,
- GTK_CTREE_NODE (work));
+ GTK_CMCTREE_NODE (work));
list_end->next = work->next;
if (work->next)
}
else {
if (parent) {
- GTK_CTREE_ROW (parent)->children = node;
+ GTK_CMCTREE_ROW (parent)->children = node;
list = (GList *)node;
list->prev = (GList *)parent;
- if (GTK_CTREE_ROW (parent)->expanded) {
- list_end->next = (GList *)GTK_CTREE_NODE_NEXT (parent);
- if (GTK_CTREE_NODE_NEXT(parent)) {
- list = (GList *)GTK_CTREE_NODE_NEXT (parent);
+ if (GTK_CMCTREE_ROW (parent)->expanded) {
+ list_end->next = (GList *)GTK_CMCTREE_NODE_NEXT (parent);
+ if (GTK_CMCTREE_NODE_NEXT(parent)) {
+ list = (GList *)GTK_CMCTREE_NODE_NEXT (parent);
list->prev = list_end;
}
list = (GList *)parent;
}
}
- gtk_ctree_pre_recursive (ctree, node, stree_update_level, NULL);
+ gtk_cmctree_pre_recursive (ctree, node, stree_update_level, NULL);
if (clist->row_list_end == NULL ||
clist->row_list_end->next == (GList *)node)
}
static void
-stree_update_level (GtkCTree *ctree,
- GtkCTreeNode *node,
+stree_update_level (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
gpointer data)
{
if (!node)
return;
- if (GTK_CTREE_ROW (node)->parent)
- GTK_CTREE_ROW (node)->level =
- GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->level + 1;
+ if (GTK_CMCTREE_ROW (node)->parent)
+ GTK_CMCTREE_ROW (node)->level =
+ GTK_CMCTREE_ROW (GTK_CMCTREE_ROW (node)->parent)->level + 1;
else
- GTK_CTREE_ROW (node)->level = 1;
+ GTK_CMCTREE_ROW (node)->level = 1;
}
-static GtkCTreeNode *
-gtk_sctree_last_visible (GtkCTree *ctree,
- GtkCTreeNode *node)
+static GtkCMCTreeNode *
+gtk_sctree_last_visible (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
{
- GtkCTreeNode *work;
+ GtkCMCTreeNode *work;
if (!node)
return NULL;
- work = GTK_CTREE_ROW (node)->children;
+ work = GTK_CMCTREE_ROW (node)->children;
- if (!work || !GTK_CTREE_ROW (node)->expanded)
+ if (!work || !GTK_CMCTREE_ROW (node)->expanded)
return node;
- while (GTK_CTREE_ROW (work)->sibling)
- work = GTK_CTREE_ROW (work)->sibling;
+ while (GTK_CMCTREE_ROW (work)->sibling)
+ work = GTK_CMCTREE_ROW (work)->sibling;
return gtk_sctree_last_visible (ctree, work);
}
* around a memory problem deep inside gtk,
* revealed by valgrind.
*/
-/*GtkCTreeNode* gtk_sctree_insert_node (GtkCTree *ctree,
- GtkCTreeNode *parent,
- GtkCTreeNode *sibling,
+/*GtkCMCTreeNode* gtk_sctree_insert_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *sibling,
gchar *text[],
guint8 spacing,
GdkPixmap *pixmap_closed,
pixmap_opened = emptyxpm;
mask_opened = emptyxpmmask;
}
- return gtk_ctree_insert_node(ctree, parent, sibling, text,spacing,
+ return gtk_cmctree_insert_node(ctree, parent, sibling, text,spacing,
pixmap_closed, mask_closed, pixmap_opened, mask_opened,
is_leaf, expanded);
}*/
static void
-sset_node_info (GtkCTree *ctree,
- GtkCTreeNode *node,
+sset_node_info (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
const gchar *text,
guint8 spacing,
GdkPixmap *pixmap_closed,
gboolean is_leaf,
gboolean expanded)
{
- if (GTK_CTREE_ROW (node)->pixmap_opened)
+ if (GTK_CMCTREE_ROW (node)->pixmap_opened)
{
- gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_opened);
- if (GTK_CTREE_ROW (node)->mask_opened)
- gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_opened);
+ g_object_unref (GTK_CMCTREE_ROW (node)->pixmap_opened);
+ if (GTK_CMCTREE_ROW (node)->mask_opened)
+ g_object_unref (GTK_CMCTREE_ROW (node)->mask_opened);
}
- if (GTK_CTREE_ROW (node)->pixmap_closed)
+ if (GTK_CMCTREE_ROW (node)->pixmap_closed)
{
- gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_closed);
- if (GTK_CTREE_ROW (node)->mask_closed)
- gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_closed);
+ g_object_unref (GTK_CMCTREE_ROW (node)->pixmap_closed);
+ if (GTK_CMCTREE_ROW (node)->mask_closed)
+ g_object_unref (GTK_CMCTREE_ROW (node)->mask_closed);
}
- GTK_CTREE_ROW (node)->pixmap_opened = NULL;
- GTK_CTREE_ROW (node)->mask_opened = NULL;
- GTK_CTREE_ROW (node)->pixmap_closed = NULL;
- GTK_CTREE_ROW (node)->mask_closed = NULL;
+ GTK_CMCTREE_ROW (node)->pixmap_opened = NULL;
+ GTK_CMCTREE_ROW (node)->mask_opened = NULL;
+ GTK_CMCTREE_ROW (node)->pixmap_closed = NULL;
+ GTK_CMCTREE_ROW (node)->mask_closed = NULL;
if (pixmap_closed)
{
- GTK_CTREE_ROW (node)->pixmap_closed = gdk_pixmap_ref (pixmap_closed);
+ GTK_CMCTREE_ROW (node)->pixmap_closed = g_object_ref (pixmap_closed);
if (mask_closed)
- GTK_CTREE_ROW (node)->mask_closed = gdk_bitmap_ref (mask_closed);
+ GTK_CMCTREE_ROW (node)->mask_closed = g_object_ref (mask_closed);
}
if (pixmap_opened)
{
- GTK_CTREE_ROW (node)->pixmap_opened = gdk_pixmap_ref (pixmap_opened);
+ GTK_CMCTREE_ROW (node)->pixmap_opened = g_object_ref (pixmap_opened);
if (mask_opened)
- GTK_CTREE_ROW (node)->mask_opened = gdk_bitmap_ref (mask_opened);
+ GTK_CMCTREE_ROW (node)->mask_opened = g_object_ref (mask_opened);
}
- GTK_CTREE_ROW (node)->is_leaf = is_leaf;
- GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
+ GTK_CMCTREE_ROW (node)->is_leaf = is_leaf;
+ GTK_CMCTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
- if (GTK_CTREE_ROW (node)->expanded)
- gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column,
+ if (GTK_CMCTREE_ROW (node)->expanded)
+ gtk_cmctree_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,
+ gtk_cmctree_node_set_pixtext (ctree, node, ctree->tree_column,
text, spacing, pixmap_closed, mask_closed);
}
static void
-stree_draw_node (GtkCTree *ctree,
- GtkCTreeNode *node)
+stree_draw_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
{
- GtkCList *clist;
+ GtkCMCList *clist;
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
- if (CLIST_UNFROZEN (clist) && gtk_ctree_is_viewable (ctree, node))
+ if (CLIST_UNFROZEN (clist) && gtk_cmctree_is_viewable (ctree, node))
{
- GtkCTreeNode *work;
+ GtkCMCTreeNode *work;
gint num = 0;
- work = GTK_CTREE_NODE (clist->row_list);
+ work = GTK_CMCTREE_NODE (clist->row_list);
while (work && work != node)
{
- work = GTK_CTREE_NODE_NEXT (work);
+ work = GTK_CMCTREE_NODE_NEXT (work);
num++;
}
- 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));
+ if (work && gtk_cmclist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE)
+ GTK_CMCLIST_GET_CLASS (clist)->draw_row
+ (clist, NULL, num, GTK_CMCLIST_ROW ((GList *) node));
}
}
* around a memory problem deep inside gtk,
* revealed by valgrind.
*/
-void gtk_sctree_set_node_info (GtkCTree *ctree,
- GtkCTreeNode *node,
+void gtk_sctree_set_node_info (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
const gchar *text,
guint8 spacing,
GdkPixmap *pixmap_closed,
{
gboolean old_leaf;
gboolean old_expanded;
- GtkCTreeNode *work;
+ GtkCMCTreeNode *work;
if (!emptyxpm) {
stock_pixmap_gdk(GTK_WIDGET(ctree), STOCK_PIXMAP_EMPTY,
mask_opened = emptyxpmmask;
}
- if (!GTK_IS_CTREE (ctree) || !node) return;
+ if (!GTK_IS_CMCTREE (ctree) || !node) return;
- old_leaf = GTK_CTREE_ROW (node)->is_leaf;
- old_expanded = GTK_CTREE_ROW (node)->expanded;
+ old_leaf = GTK_CMCTREE_ROW (node)->is_leaf;
+ old_expanded = GTK_CMCTREE_ROW (node)->expanded;
- if (is_leaf && (work = GTK_CTREE_ROW (node)->children) != NULL)
+ if (is_leaf && (work = GTK_CMCTREE_ROW (node)->children) != NULL)
{
- GtkCTreeNode *ptr;
+ GtkCMCTreeNode *ptr;
while (work)
{
ptr = work;
- work = GTK_CTREE_ROW (work)->sibling;
- gtk_ctree_remove_node (ctree, ptr);
+ work = GTK_CMCTREE_ROW (work)->sibling;
+ gtk_cmctree_remove_node (ctree, ptr);
}
}
if (!is_leaf && !old_leaf)
{
- GTK_CTREE_ROW (node)->expanded = old_expanded;
+ GTK_CMCTREE_ROW (node)->expanded = old_expanded;
if (expanded && !old_expanded)
- gtk_ctree_expand (ctree, node);
+ gtk_cmctree_expand (ctree, node);
else if (!expanded && old_expanded)
- gtk_ctree_collapse (ctree, node);
+ gtk_cmctree_collapse (ctree, node);
}
- GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
+ GTK_CMCTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
stree_draw_node (ctree, node);
}
-static GtkCTreeRow *
-srow_new (GtkCTree *ctree)
+static GtkCMCTreeRow *
+srow_new (GtkCMCTree *ctree)
{
- GtkCList *clist;
- GtkCTreeRow *ctree_row;
+ GtkCMCList *clist;
+ GtkCMCTreeRow *ctree_row;
int i;
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
#if GTK_CHECK_VERSION(2,9,0)
- ctree_row = g_slice_new (GtkCTreeRow);
- ctree_row->row.cell = g_slice_alloc (sizeof (GtkCell) * clist->columns);
+ ctree_row = g_slice_new (GtkCMCTreeRow);
+ ctree_row->row.cell = g_slice_alloc (sizeof (GtkCMCell) * clist->columns);
#else
- ctree_row = g_chunk_new (GtkCTreeRow, (GMemChunk *)clist->row_mem_chunk);
- ctree_row->row.cell = g_chunk_new (GtkCell, (GMemChunk *)clist->cell_mem_chunk);
+ ctree_row = g_chunk_new (GtkCMCTreeRow, (GMemChunk *)clist->row_mem_chunk);
+ ctree_row->row.cell = g_chunk_new (GtkCMCell, (GMemChunk *)clist->cell_mem_chunk);
#endif
for (i = 0; i < clist->columns; i++)
{
- ctree_row->row.cell[i].type = GTK_CELL_EMPTY;
+ ctree_row->row.cell[i].type = GTK_CMCELL_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;
+ GTK_CMCELL_PIXTEXT (ctree_row->row.cell[ctree->tree_column])->text = NULL;
ctree_row->row.fg_set = FALSE;
ctree_row->row.bg_set = FALSE;
}
static void
-srow_delete (GtkCTree *ctree,
- GtkCTreeRow *ctree_row)
+srow_delete (GtkCMCTree *ctree,
+ GtkCMCTreeRow *ctree_row)
{
- GtkCList *clist;
+ GtkCMCList *clist;
gint i;
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
for (i = 0; i < clist->columns; i++)
{
- GTK_CLIST_GET_CLASS (clist)->set_cell_contents
- (clist, &(ctree_row->row), i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
+ GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+ (clist, &(ctree_row->row), i, GTK_CMCELL_EMPTY, NULL, 0, NULL, NULL);
if (ctree_row->row.cell[i].style)
{
if (GTK_WIDGET_REALIZED (ctree))
if (ctree_row->pixmap_closed)
{
- gdk_pixmap_unref (ctree_row->pixmap_closed);
+ g_object_unref (ctree_row->pixmap_closed);
if (ctree_row->mask_closed)
- gdk_bitmap_unref (ctree_row->mask_closed);
+ g_object_unref (ctree_row->mask_closed);
}
if (ctree_row->pixmap_opened)
{
- gdk_pixmap_unref (ctree_row->pixmap_opened);
+ g_object_unref (ctree_row->pixmap_opened);
if (ctree_row->mask_opened)
- gdk_bitmap_unref (ctree_row->mask_opened);
+ g_object_unref (ctree_row->mask_opened);
}
if (ctree_row->row.destroy)
}
#if GTK_CHECK_VERSION(2,9,0)
- g_slice_free1 (sizeof (GtkCell) * clist->columns, ctree_row->row.cell);
- g_slice_free (GtkCTreeRow, ctree_row);
+ g_slice_free1 (sizeof (GtkCMCell) * clist->columns, ctree_row->row.cell);
+ g_slice_free (GtkCMCTreeRow, ctree_row);
#else
g_mem_chunk_free ((GMemChunk *)clist->cell_mem_chunk, ctree_row->row.cell);
g_mem_chunk_free ((GMemChunk *)clist->row_mem_chunk, ctree_row);
}
static void
-stree_delete_row (GtkCTree *ctree,
- GtkCTreeNode *node,
+stree_delete_row (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
gpointer data)
{
- srow_delete (ctree, GTK_CTREE_ROW (node));
+ srow_delete (ctree, GTK_CMCTREE_ROW (node));
g_list_free_1 ((GList *)node);
}
static void
-gtk_sctree_column_auto_resize (GtkCList *clist,
- GtkCListRow *clist_row,
+gtk_sctree_column_auto_resize (GtkCMCList *clist,
+ GtkCMCListRow *clist_row,
gint column,
gint old_width)
{
GtkRequisition requisition;
if (!clist->column[column].auto_resize ||
- GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+ GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
return;
if (clist_row)
- GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+ GTK_CMCLIST_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);
+ gtk_cmclist_set_column_width (clist, column, requisition.width);
else if (requisition.width < old_width &&
old_width == clist->column[column].width)
{
GList *list;
gint new_width;
- /* run a "gtk_clist_optimal_column_width" but break, if
+ /* run a "gtk_cmclist_optimal_column_width" but break, if
* the column doesn't shrink */
- if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[column].button)
+ if (GTK_CMCLIST_SHOW_TITLES (clist) && clist->column[column].button)
new_width = (clist->column[column].button->requisition.width -
(CELL_SPACING + (2 * COLUMN_INSET)));
else
for (list = clist->row_list; list; list = list->next)
{
- GTK_CLIST_GET_CLASS (clist)->cell_size_request
- (clist, GTK_CLIST_ROW (list), column, &requisition);
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+ (clist, GTK_CMCLIST_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);
+ gtk_cmclist_set_column_width (clist, column, new_width);
}
}
static void
-gtk_sctree_real_tree_expand (GtkCTree *ctree,
- GtkCTreeNode *node)
+gtk_sctree_real_tree_expand (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
{
- GtkCList *clist;
- GtkCTreeNode *work;
+ GtkCMCList *clist;
+ GtkCMCTreeNode *work;
GtkRequisition requisition;
gboolean visible;
gint level;
- g_return_if_fail (GTK_IS_CTREE (ctree));
+ g_return_if_fail (GTK_IS_CMCTREE (ctree));
- if (!node || GTK_CTREE_ROW (node)->expanded || GTK_CTREE_ROW (node)->is_leaf)
+ if (!node || GTK_CMCTREE_ROW (node)->expanded || GTK_CMCTREE_ROW (node)->is_leaf)
return;
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
- GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
- GTK_CTREE_ROW (node)->expanded = TRUE;
- level = GTK_CTREE_ROW (node)->level;
+ GTK_CMCTREE_ROW (node)->expanded = TRUE;
+ level = GTK_CMCTREE_ROW (node)->level;
- visible = gtk_ctree_is_viewable (ctree, node);
+ visible = gtk_cmctree_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);
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+ (clist, >K_CMCTREE_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)
+ if (GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
{
- gdk_pixmap_unref
- (GTK_CELL_PIXTEXT
- (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
+ g_object_unref
+ (GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
- GTK_CELL_PIXTEXT
- (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
- if (GTK_CELL_PIXTEXT
- (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
+ if (GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_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;
+ g_object_unref
+ (GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
}
}
/* set/ref opened pixmap */
- if (GTK_CTREE_ROW (node)->pixmap_opened)
+ if (GTK_CMCTREE_ROW (node)->pixmap_opened)
{
- GTK_CELL_PIXTEXT
- (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
- 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);
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
+ g_object_ref (GTK_CMCTREE_ROW (node)->pixmap_opened);
+
+ if (GTK_CMCTREE_ROW (node)->mask_opened)
+ GTK_CMCELL_PIXTEXT
+ (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
+ g_object_ref (GTK_CMCTREE_ROW (node)->mask_opened);
}
- work = GTK_CTREE_ROW (node)->children;
+ work = GTK_CMCTREE_ROW (node)->children;
if (work)
{
GList *list = (GList *)work;
gint row;
gint i;
- if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+ if (visible && !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
{
cell_width = g_new0 (gint, clist->columns);
if (clist->column[ctree->tree_column].auto_resize)
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);
+ GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+ (clist, >K_CMCTREE_ROW (work)->row, i, &requisition);
cell_width[i] = MAX (requisition.width, cell_width[i]);
}
list = (GList *)work;
- work = GTK_CTREE_NODE_NEXT (work);
+ work = GTK_CMCTREE_NODE_NEXT (work);
tmp++;
}
}
while (work)
{
list = (GList *)work;
- work = GTK_CTREE_NODE_NEXT (work);
+ work = GTK_CMCTREE_NODE_NEXT (work);
tmp++;
}
- list->next = (GList *)GTK_CTREE_NODE_NEXT (node);
+ list->next = (GList *)GTK_CMCTREE_NODE_NEXT (node);
- if (GTK_CTREE_NODE_NEXT (node))
+ if (GTK_CMCTREE_NODE_NEXT (node))
{
GList *tmp_list;
if (clist->row_list_end == list)
clist->row_list_end = g_list_last(list);
- tmp_list = (GList *)GTK_CTREE_NODE_NEXT (node);
+ tmp_list = (GList *)GTK_CMCTREE_NODE_NEXT (node);
tmp_list->prev = list;
}
else
clist->row_list_end = list;
list = (GList *)node;
- list->next = (GList *)(GTK_CTREE_ROW (node)->children);
+ list->next = (GList *)(GTK_CMCTREE_ROW (node)->children);
if (visible)
{
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]);
+ gtk_cmclist_set_column_width (clist, i, cell_width[i]);
g_free (cell_width);
if (!GTK_SCTREE(ctree)->sorting) {
}
else if (visible && clist->column[ctree->tree_column].auto_resize)
/* resize tree_column if needed */
- gtk_sctree_column_auto_resize (clist, >K_CTREE_ROW (node)->row, ctree->tree_column,
+ gtk_sctree_column_auto_resize (clist, >K_CMCTREE_ROW (node)->row, ctree->tree_column,
requisition.width);
}
-GtkCTreeNode *
-gtk_sctree_insert_node (GtkCTree *ctree,
- GtkCTreeNode *parent,
- GtkCTreeNode *sibling,
+GtkCMCTreeNode *
+gtk_sctree_insert_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *sibling,
gchar *text[],
guint8 spacing,
GdkPixmap *pixmap_closed,
gboolean is_leaf,
gboolean expanded)
{
- GtkCList *clist;
- GtkCTreeRow *new_row;
- GtkCTreeNode *node;
+ GtkCMCList *clist;
+ GtkCMCTreeRow *new_row;
+ GtkCMCTreeNode *node;
GList *list;
gint i;
pixmap_opened = emptyxpm;
mask_opened = emptyxpmmask;
}
- g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
+ g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
if (sibling)
- g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
+ g_return_val_if_fail (GTK_CMCTREE_ROW (sibling)->parent == parent, NULL);
- if (parent && GTK_CTREE_ROW (parent)->is_leaf)
+ if (parent && GTK_CMCTREE_ROW (parent)->is_leaf)
return NULL;
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
/* create the row */
new_row = srow_new (ctree);
list = g_list_alloc ();
list->data = new_row;
- node = GTK_CTREE_NODE (list);
+ node = GTK_CMCTREE_NODE (list);
if (text)
for (i = 0; i < clist->columns; i++)
if (text[i] && i != ctree->tree_column)
- GTK_CLIST_GET_CLASS (clist)->set_cell_contents
- (clist, &(new_row->row), i, GTK_CELL_TEXT, text[i], 0, NULL, NULL);
+ GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+ (clist, &(new_row->row), i, GTK_CMCELL_TEXT, text[i], 0, NULL, NULL);
sset_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 (GTK_CLIST_AUTO_SORT (clist))
+ if (GTK_CMCLIST_AUTO_SORT (clist))
{
if (parent)
- sibling = GTK_CTREE_ROW (parent)->children;
+ sibling = GTK_CMCTREE_ROW (parent)->children;
else
- sibling = GTK_CTREE_NODE (clist->row_list);
+ sibling = GTK_CMCTREE_NODE (clist->row_list);
while (sibling && clist->compare
- (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (sibling)) > 0)
- sibling = GTK_CTREE_ROW (sibling)->sibling;
+ (clist, GTK_CMCTREE_ROW (node), GTK_CMCTREE_ROW (sibling)) > 0)
+ sibling = GTK_CMCTREE_ROW (sibling)->sibling;
}
gtk_sctree_link (ctree, node, parent, sibling, FALSE);
- if (text && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) &&
- gtk_ctree_is_viewable (ctree, node))
+ if (text && !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist) &&
+ gtk_cmctree_is_viewable (ctree, node))
{
for (i = 0; i < clist->columns; i++)
if (clist->column[i].auto_resize)
return node;
}
-GtkCTreeNode *
-gtk_sctree_insert_gnode (GtkCTree *ctree,
- GtkCTreeNode *parent,
- GtkCTreeNode *sibling,
+GtkCMCTreeNode *
+gtk_sctree_insert_gnode (GtkCMCTree *ctree,
+ GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *sibling,
GNode *gnode,
- GtkCTreeGNodeFunc func,
+ GtkCMCTreeGNodeFunc func,
gpointer data)
{
- GtkCList *clist;
- GtkCTreeNode *cnode = NULL;
- GtkCTreeNode *child = NULL;
- GtkCTreeNode *new_child;
+ GtkCMCList *clist;
+ GtkCMCTreeNode *cnode = NULL;
+ GtkCMCTreeNode *child = NULL;
+ GtkCMCTreeNode *new_child;
GList *list;
GNode *work;
guint depth = 1;
- g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
+ g_return_val_if_fail (GTK_IS_CMCTREE (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);
+ g_return_val_if_fail (GTK_CMCTREE_ROW (sibling)->parent == parent, NULL);
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
if (parent)
- depth = GTK_CTREE_ROW (parent)->level + 1;
+ depth = GTK_CMCTREE_ROW (parent)->level + 1;
list = g_list_alloc ();
list->data = srow_new (ctree);
- cnode = GTK_CTREE_NODE (list);
+ cnode = GTK_CMCTREE_NODE (list);
- gtk_clist_freeze (clist);
+ gtk_cmclist_freeze (clist);
sset_node_info (ctree, cnode, "", 0, NULL, NULL, NULL, NULL, TRUE, FALSE);
if (!func (ctree, depth, gnode, cnode, data))
{
stree_delete_row (ctree, cnode, NULL);
- gtk_clist_thaw (clist);
+ gtk_cmclist_thaw (clist);
return NULL;
}
- if (GTK_CLIST_AUTO_SORT (clist))
+ if (GTK_CMCLIST_AUTO_SORT (clist))
{
if (parent)
- sibling = GTK_CTREE_ROW (parent)->children;
+ sibling = GTK_CMCTREE_ROW (parent)->children;
else
- sibling = GTK_CTREE_NODE (clist->row_list);
+ sibling = GTK_CMCTREE_NODE (clist->row_list);
while (sibling && clist->compare
- (clist, GTK_CTREE_ROW (cnode), GTK_CTREE_ROW (sibling)) > 0)
- sibling = GTK_CTREE_ROW (sibling)->sibling;
+ (clist, GTK_CMCTREE_ROW (cnode), GTK_CMCTREE_ROW (sibling)) > 0)
+ sibling = GTK_CMCTREE_ROW (sibling)->sibling;
}
gtk_sctree_link (ctree, cnode, parent, sibling, FALSE);
child = new_child;
}
- gtk_clist_thaw (clist);
+ gtk_cmclist_thaw (clist);
return cnode;
}
static void
-sreal_tree_move (GtkCTree *ctree,
- GtkCTreeNode *node,
- GtkCTreeNode *new_parent,
- GtkCTreeNode *new_sibling)
+sreal_tree_move (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ GtkCMCTreeNode *new_parent,
+ GtkCMCTreeNode *new_sibling)
{
- GtkCList *clist;
- GtkCTreeNode *work;
+ GtkCMCList *clist;
+ GtkCMCTreeNode *work;
gboolean visible = FALSE;
g_return_if_fail (ctree != NULL);
g_return_if_fail (node != NULL);
g_return_if_fail (!new_sibling ||
- GTK_CTREE_ROW (new_sibling)->parent == new_parent);
+ GTK_CMCTREE_ROW (new_sibling)->parent == new_parent);
- if (new_parent && GTK_CTREE_ROW (new_parent)->is_leaf)
+ if (new_parent && GTK_CMCTREE_ROW (new_parent)->is_leaf)
return;
/* new_parent != child of child */
- for (work = new_parent; work; work = GTK_CTREE_ROW (work)->parent)
+ for (work = new_parent; work; work = GTK_CMCTREE_ROW (work)->parent)
if (work == node)
return;
- clist = GTK_CLIST (ctree);
+ clist = GTK_CMCLIST (ctree);
- visible = gtk_ctree_is_viewable (ctree, node);
+ visible = gtk_cmctree_is_viewable (ctree, node);
if (clist->selection_mode == GTK_SELECTION_MULTIPLE)
{
- GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+ GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
g_list_free (clist->undo_selection);
g_list_free (clist->undo_unselection);
clist->undo_unselection = NULL;
}
- if (GTK_CLIST_AUTO_SORT (clist))
+ if (GTK_CMCLIST_AUTO_SORT (clist))
{
- if (new_parent == GTK_CTREE_ROW (node)->parent)
+ if (new_parent == GTK_CMCTREE_ROW (node)->parent)
return;
if (new_parent)
- new_sibling = GTK_CTREE_ROW (new_parent)->children;
+ new_sibling = GTK_CMCTREE_ROW (new_parent)->children;
else
- new_sibling = GTK_CTREE_NODE (clist->row_list);
+ new_sibling = GTK_CMCTREE_NODE (clist->row_list);
while (new_sibling && clist->compare
- (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (new_sibling)) > 0)
- new_sibling = GTK_CTREE_ROW (new_sibling)->sibling;
+ (clist, GTK_CMCTREE_ROW (node), GTK_CMCTREE_ROW (new_sibling)) > 0)
+ new_sibling = GTK_CMCTREE_ROW (new_sibling)->sibling;
}
- if (new_parent == GTK_CTREE_ROW (node)->parent &&
- new_sibling == GTK_CTREE_ROW (node)->sibling)
+ if (new_parent == GTK_CMCTREE_ROW (node)->parent &&
+ new_sibling == GTK_CMCTREE_ROW (node)->sibling)
return;
- gtk_clist_freeze (clist);
+ gtk_cmclist_freeze (clist);
work = NULL;
- if (!GTK_SCTREE(ctree)->sorting && gtk_ctree_is_viewable (ctree, node))
- work = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
+ if (!GTK_SCTREE(ctree)->sorting && gtk_cmctree_is_viewable (ctree, node))
+ work = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
gtk_sctree_unlink (ctree, node, FALSE);
gtk_sctree_link (ctree, node, new_parent, new_sibling, FALSE);
if (!GTK_SCTREE(ctree)->sorting && work)
{
- while (work && !gtk_ctree_is_viewable (ctree, work))
- work = GTK_CTREE_ROW (work)->parent;
+ while (work && !gtk_cmctree_is_viewable (ctree, work))
+ work = GTK_CMCTREE_ROW (work)->parent;
clist->focus_row = g_list_position (clist->row_list, (GList *)work);
clist->undo_anchor = clist->focus_row;
}
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
+ !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist) &&
+ (visible || gtk_cmctree_is_viewable (ctree, node)))
+ gtk_cmclist_set_column_width
(clist, ctree->tree_column,
- gtk_clist_optimal_column_width (clist, ctree->tree_column));
+ gtk_cmclist_optimal_column_width (clist, ctree->tree_column));
- gtk_clist_thaw (clist);
+ gtk_cmclist_thaw (clist);
}
void gtk_sctree_set_column_tooltip (GtkSCTree *sctree,
tips = sctree->tips;
#endif
- CLAWS_SET_TIP(GTK_CLIST(sctree)->column[column].button,
+ CLAWS_SET_TIP(GTK_CMCLIST(sctree)->column[column].button,
tip);
}
#define __GTK_SCTREE_H__
#include <gtk/gtk.h>
-#include <gtk/gtkclist.h>
-#include <gtk/gtkctree.h>
+#include "gtk/gtkcmctree.h"
/* This code is based on "gtkflist.{h,c}" from mc-4.5.42 .*/
typedef struct _GtkSCTreeClass GtkSCTreeClass;
struct _GtkSCTree {
- GtkCTree ctree;
+ GtkCMCTree ctree;
/* The anchor row for range selections */
- GtkCTreeNode *anchor_row;
+ GtkCMCTreeNode *anchor_row;
/* Mouse button and position saved on button press */
gint dnd_press_button;
/* (dis)allow fancy color stripes */
gboolean show_stripes;
- GtkTooltips *tips;
+#if !GTK_CHECK_VERSION(2,12,0)
+ GtkTooltips *tooltips;
+#endif
gboolean always_expand_recursively;
gboolean force_additive_sel;
gboolean *use_markup;
};
struct _GtkSCTreeClass {
- GtkCTreeClass parent_class;
+ GtkCMCTreeClass parent_class;
/* Signal: invoke the popup menu for rows */
void (* row_popup_menu) (GtkSCTree *sctree, GdkEventButton *event);
gint tree_column,
gchar *titles[]);
void gtk_sctree_select (GtkSCTree *sctree,
- GtkCTreeNode *node);
+ GtkCMCTreeNode *node);
void gtk_sctree_select_with_state (GtkSCTree *sctree,
- GtkCTreeNode *node,
+ GtkCMCTreeNode *node,
int state);
void gtk_sctree_unselect_all (GtkSCTree *sctree);
void gtk_sctree_set_anchor_row (GtkSCTree *sctree,
- GtkCTreeNode *node);
+ GtkCMCTreeNode *node);
void gtk_sctree_remove_node (GtkSCTree *sctree,
- GtkCTreeNode *node);
+ GtkCMCTreeNode *node);
void gtk_sctree_set_stripes(GtkSCTree *sctree, gboolean show_stripes);
void gtk_sctree_set_recursive_expand(GtkSCTree *sctree, gboolean rec_exp);
* Tree sorting functions *
***********************************************************/
-void gtk_sctree_sort_node (GtkCTree *ctree, GtkCTreeNode *node);
+void gtk_sctree_sort_node (GtkCMCTree *ctree, GtkCMCTreeNode *node);
-void gtk_sctree_sort_recursive (GtkCTree *ctree, GtkCTreeNode *node);
+void gtk_sctree_sort_recursive (GtkCMCTree *ctree, GtkCMCTreeNode *node);
-GtkCTreeNode* gtk_sctree_insert_node (GtkCTree *ctree,
- GtkCTreeNode *parent,
- GtkCTreeNode *sibling,
+GtkCMCTreeNode* gtk_sctree_insert_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *sibling,
gchar *text[],
guint8 spacing,
GdkPixmap *pixmap_closed,
GdkBitmap *mask_opened,
gboolean is_leaf,
gboolean expanded);
-void gtk_sctree_set_node_info (GtkCTree *ctree,
- GtkCTreeNode *node,
+void gtk_sctree_set_node_info (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
const gchar *text,
guint8 spacing,
GdkPixmap *pixmap_closed,
GdkBitmap *mask_opened,
gboolean is_leaf,
gboolean expanded);
-GtkCTreeNode *
-gtk_sctree_insert_gnode (GtkCTree *ctree,
- GtkCTreeNode *parent,
- GtkCTreeNode *sibling,
+GtkCMCTreeNode *
+gtk_sctree_insert_gnode (GtkCMCTree *ctree,
+ GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *sibling,
GNode *gnode,
- GtkCTreeGNodeFunc func,
+ GtkCMCTreeGNodeFunc func,
gpointer data);
void gtk_sctree_set_column_tooltip (GtkSCTree *sctree,
#include <glib/gi18n.h>
#include <gdk/gdkkeysyms.h>
#include <gdk/gdk.h>
-#include <gtk/gtkwidget.h>
-#include <gtk/gtkhbbox.h>
-#include <gtk/gtkbutton.h>
-#include <gtk/gtkctree.h>
-#include <gtk/gtkcombo.h>
-#include <gtk/gtkbindings.h>
-#include <gtk/gtkitemfactory.h>
+#include <gtk/gtk.h>
+#include "gtk/gtksctree.h"
#include <stdlib.h>
#include <stdarg.h>
#include <sys/stat.h>
#define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
((clist)->row_height + CELL_SPACING))
-void gtkut_ctree_node_move_if_on_the_edge(GtkCTree *ctree, GtkCTreeNode *node, gint _row)
+void gtkut_ctree_node_move_if_on_the_edge(GtkCMCTree *ctree, GtkCMCTreeNode *node, gint _row)
{
- GtkCList *clist = GTK_CLIST(ctree);
+ GtkCMCList *clist = GTK_CMCLIST(ctree);
gint row;
GtkVisibility row_visibility, prev_row_visibility, next_row_visibility;
row = (_row != -1 ? _row : g_list_position(clist->row_list, (GList *)node));
if (row < 0 || row >= clist->rows || clist->row_height == 0) return;
- row_visibility = gtk_clist_row_is_visible(clist, row);
- prev_row_visibility = gtk_clist_row_is_visible(clist, row - 1);
- next_row_visibility = gtk_clist_row_is_visible(clist, row + 1);
+ row_visibility = gtk_cmclist_row_is_visible(clist, row);
+ prev_row_visibility = gtk_cmclist_row_is_visible(clist, row - 1);
+ next_row_visibility = gtk_cmclist_row_is_visible(clist, row + 1);
if (row_visibility == GTK_VISIBILITY_NONE) {
- gtk_clist_moveto(clist, row, -1, 0.5, 0);
+ gtk_cmclist_moveto(clist, row, -1, 0.5, 0);
return;
}
if (row_visibility == GTK_VISIBILITY_FULL &&
return;
if (prev_row_visibility != GTK_VISIBILITY_FULL) {
- gtk_clist_moveto(clist, row, -1, 0.2, 0);
+ gtk_cmclist_moveto(clist, row, -1, 0.2, 0);
return;
}
if (next_row_visibility != GTK_VISIBILITY_FULL) {
- gtk_clist_moveto(clist, row, -1, 0.8, 0);
+ gtk_cmclist_moveto(clist, row, -1, 0.8, 0);
return;
}
}
#undef ROW_TOP_YPIXEL
#undef ROW_FROM_YPIXEL
-gint gtkut_ctree_get_nth_from_node(GtkCTree *ctree, GtkCTreeNode *node)
+gint gtkut_ctree_get_nth_from_node(GtkCMCTree *ctree, GtkCMCTreeNode *node)
{
g_return_val_if_fail(ctree != NULL, -1);
g_return_val_if_fail(node != NULL, -1);
- return g_list_position(GTK_CLIST(ctree)->row_list, (GList *)node);
+ return g_list_position(GTK_CMCLIST(ctree)->row_list, (GList *)node);
}
/* get the next node, including the invisible one */
-GtkCTreeNode *gtkut_ctree_node_next(GtkCTree *ctree, GtkCTreeNode *node)
+GtkCMCTreeNode *gtkut_ctree_node_next(GtkCMCTree *ctree, GtkCMCTreeNode *node)
{
- GtkCTreeNode *parent;
+ GtkCMCTreeNode *parent;
if (!node) return NULL;
- if (GTK_CTREE_ROW(node)->children)
- return GTK_CTREE_ROW(node)->children;
+ if (GTK_CMCTREE_ROW(node)->children)
+ return GTK_CMCTREE_ROW(node)->children;
- if (GTK_CTREE_ROW(node)->sibling)
- return GTK_CTREE_ROW(node)->sibling;
+ if (GTK_CMCTREE_ROW(node)->sibling)
+ return GTK_CMCTREE_ROW(node)->sibling;
- for (parent = GTK_CTREE_ROW(node)->parent; parent != NULL;
- parent = GTK_CTREE_ROW(parent)->parent) {
- if (GTK_CTREE_ROW(parent)->sibling)
- return GTK_CTREE_ROW(parent)->sibling;
+ for (parent = GTK_CMCTREE_ROW(node)->parent; parent != NULL;
+ parent = GTK_CMCTREE_ROW(parent)->parent) {
+ if (GTK_CMCTREE_ROW(parent)->sibling)
+ return GTK_CMCTREE_ROW(parent)->sibling;
}
return NULL;
}
/* get the previous node, including the invisible one */
-GtkCTreeNode *gtkut_ctree_node_prev(GtkCTree *ctree, GtkCTreeNode *node)
+GtkCMCTreeNode *gtkut_ctree_node_prev(GtkCMCTree *ctree, GtkCMCTreeNode *node)
{
- GtkCTreeNode *prev;
- GtkCTreeNode *child;
+ GtkCMCTreeNode *prev;
+ GtkCMCTreeNode *child;
if (!node) return NULL;
- prev = GTK_CTREE_NODE_PREV(node);
- if (prev == GTK_CTREE_ROW(node)->parent)
+ prev = GTK_CMCTREE_NODE_PREV(node);
+ if (prev == GTK_CMCTREE_ROW(node)->parent)
return prev;
child = prev;
- while (GTK_CTREE_ROW(child)->children != NULL) {
- child = GTK_CTREE_ROW(child)->children;
- while (GTK_CTREE_ROW(child)->sibling != NULL)
- child = GTK_CTREE_ROW(child)->sibling;
+ while (GTK_CMCTREE_ROW(child)->children != NULL) {
+ child = GTK_CMCTREE_ROW(child)->children;
+ while (GTK_CMCTREE_ROW(child)->sibling != NULL)
+ child = GTK_CMCTREE_ROW(child)->sibling;
}
return child;
}
-gboolean gtkut_ctree_node_is_selected(GtkCTree *ctree, GtkCTreeNode *node)
+gboolean gtkut_ctree_node_is_selected(GtkCMCTree *ctree, GtkCMCTreeNode *node)
{
- GtkCList *clist = GTK_CLIST(ctree);
+ GtkCMCList *clist = GTK_CMCLIST(ctree);
GList *cur;
for (cur = clist->selection; cur != NULL; cur = cur->next) {
- if (node == GTK_CTREE_NODE(cur->data))
+ if (node == GTK_CMCTREE_NODE(cur->data))
return TRUE;
}
return FALSE;
}
-GtkCTreeNode *gtkut_ctree_find_collapsed_parent(GtkCTree *ctree,
- GtkCTreeNode *node)
+GtkCMCTreeNode *gtkut_ctree_find_collapsed_parent(GtkCMCTree *ctree,
+ GtkCMCTreeNode *node)
{
if (!node) return NULL;
- while ((node = GTK_CTREE_ROW(node)->parent) != NULL) {
- if (!GTK_CTREE_ROW(node)->expanded)
+ while ((node = GTK_CMCTREE_ROW(node)->parent) != NULL) {
+ if (!GTK_CMCTREE_ROW(node)->expanded)
return node;
}
return NULL;
}
-void gtkut_ctree_expand_parent_all(GtkCTree *ctree, GtkCTreeNode *node)
+void gtkut_ctree_expand_parent_all(GtkCMCTree *ctree, GtkCMCTreeNode *node)
{
while ((node = gtkut_ctree_find_collapsed_parent(ctree, node)) != NULL)
- gtk_ctree_expand(ctree, node);
+ gtk_cmctree_expand(ctree, node);
}
-gboolean gtkut_ctree_node_is_parent(GtkCTreeNode *parent, GtkCTreeNode *node)
+gboolean gtkut_ctree_node_is_parent(GtkCMCTreeNode *parent, GtkCMCTreeNode *node)
{
- GtkCTreeNode *tmp;
+ GtkCMCTreeNode *tmp;
g_return_val_if_fail(node != NULL, FALSE);
g_return_val_if_fail(parent != NULL, FALSE);
tmp = node;
while (tmp) {
- if(GTK_CTREE_ROW(tmp)->parent && GTK_CTREE_ROW(tmp)->parent == parent)
+ if(GTK_CMCTREE_ROW(tmp)->parent && GTK_CMCTREE_ROW(tmp)->parent == parent)
return TRUE;
- tmp = GTK_CTREE_ROW(tmp)->parent;
+ tmp = GTK_CMCTREE_ROW(tmp)->parent;
}
return FALSE;
}
-void gtkut_ctree_set_focus_row(GtkCTree *ctree, GtkCTreeNode *node)
+void gtkut_ctree_set_focus_row(GtkCMCTree *ctree, GtkCMCTreeNode *node)
{
if (node == NULL)
return;
- gtkut_clist_set_focus_row(GTK_CLIST(ctree),
+ gtkut_clist_set_focus_row(GTK_CMCLIST(ctree),
gtkut_ctree_get_nth_from_node(ctree, node));
}
-void gtkut_clist_set_focus_row(GtkCList *clist, gint row)
+void gtkut_clist_set_focus_row(GtkCMCList *clist, gint row)
{
clist->focus_row = row;
GTKUT_CTREE_REFRESH(clist);
GtkBindingSet *binding_set;
binding_set = gtk_binding_set_by_class
- (GTK_CLIST_GET_CLASS(clist));
+ (GTK_CMCLIST_GET_CLASS(clist));
gtk_binding_entry_add_signal(binding_set, GDK_n, GDK_CONTROL_MASK,
"scroll_vertical", 2,
{
GtkWidget *clist;
- clist = gtk_clist_new(1);
+ clist = gtk_cmclist_new(1);
g_object_ref(GTK_OBJECT(clist));
g_object_ref_sink(GTK_OBJECT(clist));
gtkut_clist_bindings_add(clist);
g_object_unref(GTK_OBJECT(clist));
- clist = gtk_ctree_new(1, 0);
+ clist = gtk_cmctree_new(1, 0);
g_object_ref(GTK_OBJECT(clist));
g_object_ref_sink(GTK_OBJECT(clist));
gtkut_clist_bindings_add(clist);
#include <gtk/gtkmain.h>
#endif
-typedef struct _ComboButton ComboButton;
-
-struct _ComboButton
-{
- GtkWidget *arrow;
- GtkWidget *button;
- GtkWidget *menu;
- GtkItemFactory *factory;
- gpointer data;
-};
+#include "gtkcmctree.h"
#define GTK_EVENTS_FLUSH() \
{ \
#define GTKUT_CTREE_NODE_SET_ROW_DATA(node, d) \
{ \
- GTK_CTREE_ROW(node)->row.data = d; \
+ GTK_CMCTREE_ROW(node)->row.data = d; \
}
#define GTKUT_CTREE_NODE_GET_ROW_DATA(node) \
- (GTK_CTREE_ROW(node)->row.data)
+ (GTK_CMCTREE_ROW(node)->row.data)
#define GTKUT_CTREE_REFRESH(clist) \
- GTK_CLIST_GET_CLASS(clist)->refresh(clist)
+ GTK_CMCLIST_GET_CLASS(clist)->refresh(clist)
gboolean gtkut_get_font_size (GtkWidget *widget,
gint *width,
GtkWidget **button3, const gchar *label3, const gchar *text3);
void gtkut_ctree_node_move_if_on_the_edge
- (GtkCTree *ctree,
- GtkCTreeNode *node,
+ (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
gint _row);
-gint gtkut_ctree_get_nth_from_node (GtkCTree *ctree,
- GtkCTreeNode *node);
-GtkCTreeNode *gtkut_ctree_node_next (GtkCTree *ctree,
- GtkCTreeNode *node);
-GtkCTreeNode *gtkut_ctree_node_prev (GtkCTree *ctree,
- GtkCTreeNode *node);
-gboolean gtkut_ctree_node_is_selected (GtkCTree *ctree,
- GtkCTreeNode *node);
-GtkCTreeNode *gtkut_ctree_find_collapsed_parent
- (GtkCTree *ctree,
- GtkCTreeNode *node);
-void gtkut_ctree_expand_parent_all (GtkCTree *ctree,
- GtkCTreeNode *node);
-gboolean gtkut_ctree_node_is_parent (GtkCTreeNode *parent,
- GtkCTreeNode *node);
-void gtkut_ctree_set_focus_row (GtkCTree *ctree,
- GtkCTreeNode *node);
-
-void gtkut_clist_set_focus_row (GtkCList *clist,
+gint gtkut_ctree_get_nth_from_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+GtkCMCTreeNode *gtkut_ctree_node_next (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+GtkCMCTreeNode *gtkut_ctree_node_prev (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+gboolean gtkut_ctree_node_is_selected (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+GtkCMCTreeNode *gtkut_ctree_find_collapsed_parent
+ (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+void gtkut_ctree_expand_parent_all (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+gboolean gtkut_ctree_node_is_parent (GtkCMCTreeNode *parent,
+ GtkCMCTreeNode *node);
+void gtkut_ctree_set_focus_row (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node);
+
+void gtkut_clist_set_focus_row (GtkCMCList *clist,
gint row);
void gtkut_container_remove (GtkContainer *container,
static void gtk_vscrollbutton_set_sensitivity (GtkAdjustment *adjustment,
GtkVScrollbutton *scrollbutton);
-GtkType gtk_vscrollbutton_get_type(void)
+GType gtk_vscrollbutton_get_type(void)
{
- static GtkType vscrollbutton_type = 0;
+ static GType vscrollbutton_type = 0;
if (!vscrollbutton_type) {
- static const GtkTypeInfo vscrollbutton_info = {
- "GtkVScrollbutton",
- sizeof(GtkVScrollbutton),
- sizeof(GtkVScrollbuttonClass),
- (GtkClassInitFunc) gtk_vscrollbutton_class_init,
- (GtkObjectInitFunc) gtk_vscrollbutton_init,
- /* reserved_1 */ NULL,
- /* reserved_2 */ NULL,
- (GtkClassInitFunc) NULL,
+ static const GTypeInfo vscrollbutton_info = {
+ sizeof (GtkVScrollbuttonClass),
+
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+
+ (GClassInitFunc) gtk_vscrollbutton_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+
+ sizeof (GtkVScrollbutton),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gtk_vscrollbutton_init,
};
- vscrollbutton_type =
- gtk_type_unique(GTK_TYPE_VBOX, &vscrollbutton_info);
+ vscrollbutton_type = g_type_register_static (GTK_TYPE_VBOX, "GtkVScrollbutton", &vscrollbutton_info, (GTypeFlags)0);
}
return vscrollbutton_type;
GtkWidget *gtk_vscrollbutton_new(GtkAdjustment *adjustment)
{
GtkWidget *vscrollbutton;
- vscrollbutton = GTK_WIDGET(gtk_type_new(gtk_vscrollbutton_get_type()));
+ vscrollbutton = g_object_new (gtk_vscrollbutton_get_type(),
+ NULL);
gtk_vscrollbutton_set_adjustment(GTK_VSCROLLBUTTON(vscrollbutton),
adjustment);
g_signal_connect(G_OBJECT(GTK_VSCROLLBUTTON(vscrollbutton)->adjustment),
#include <glib/gi18n.h>
#include <gtk/gtk.h>
+#include "gtkcmoptionmenu.h"
#include "menu.h"
#include "utils.h"
#include "gtkutils.h"
*y -= mreq.height;
}
-gint menu_find_option_menu_index(GtkOptionMenu *optmenu, gpointer data,
+gint menu_find_option_menu_index(GtkCMOptionMenu *optmenu, gpointer data,
GCompareFunc func)
{
GtkWidget *menu;
GList *cur;
gint n;
- menu = gtk_option_menu_get_menu(optmenu);
+ menu = gtk_cmoption_menu_get_menu(optmenu);
for (cur = GTK_MENU_SHELL(menu)->children, n = 0;
cur != NULL; cur = cur->next, n++) {
void menu_connect_identical_items(void)
{
+#if 0 /* DEPRECATED */
gint n;
GtkWidget *item1;
GtkWidget *item2;
if (!item2) debug_print(" ** Menu item not found: %s\n",pairs[n].path2);
}
}
+#endif
}
#include <glib.h>
#include <gtk/gtk.h>
+#include "gtkcmoptionmenu.h"
#define MENU_VAL_ID "Claws::Menu::ValueID"
#define MENU_VAL_DATA "Claws::Menu::ValueDATA"
void cm_menu_set_sensitive_full(GtkUIManager *gui_manager, gchar *menu, gboolean sensitive);
void cm_toggle_menu_set_active_full(GtkUIManager *gui_manager, gchar *menu, gboolean active);
+gint menu_find_option_menu_index(GtkCMOptionMenu *optmenu, gpointer data,
+ GCompareFunc func);
+
void menu_button_position (GtkMenu *menu,
gint *x,
gint *y,
gboolean *push_in,
gpointer user_data);
-gint menu_find_option_menu_index(GtkOptionMenu *optmenu,
- gpointer data,
- GCompareFunc func);
void menu_set_sensitive_all(GtkMenuShell *menu_shell, gboolean sensitive);
void menu_connect_identical_items(void);
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
+#include "gtkcmoptionmenu.h"
#include "utils.h"
#include "combobox.h"
#include "menu.h"
static void quicksearch_set_type(QuickSearch *quicksearch, gint type)
{
gint index;
- index = menu_find_option_menu_index(GTK_OPTION_MENU(quicksearch->search_type_opt),
+ index = menu_find_option_menu_index(GTK_CMOPTION_MENU(quicksearch->search_type_opt),
GINT_TO_POINTER(type),
NULL);
- gtk_option_menu_set_history(GTK_OPTION_MENU(quicksearch->search_type_opt), index);
+ gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(quicksearch->search_type_opt), index);
}
static gchar *quicksearch_get_text(QuickSearch * quicksearch)
/* quick search */
hbox_search = gtk_hbox_new(FALSE, 0);
- search_type_opt = gtk_option_menu_new();
+ search_type_opt = gtk_cmoption_menu_new();
gtk_widget_show(search_type_opt);
gtk_box_pack_start(GTK_BOX(hbox_search), search_type_opt, FALSE, FALSE, 0);
G_CALLBACK(searchtype_autorun_changed),
quicksearch);
- gtk_option_menu_set_menu(GTK_OPTION_MENU(search_type_opt), search_type);
+ gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(search_type_opt), search_type);
quicksearch->search_type_opt = search_type_opt;
quicksearch_set_type(quicksearch, prefs_common.summary_quicksearch_type);
ctree = summary_get_main_widget(mainwin->summaryview);
if (ctree && mainwin->summaryview->selected)
- gtk_ctree_node_moveto(GTK_CTREE(ctree),
+ gtk_cmctree_node_moveto(GTK_CMCTREE(ctree),
mainwin->summaryview->selected,
0, 0.5, 0);
}
gtk_widget_destroy(viewer->socket);
}
- gtk_widget_unref(GTK_WIDGET(viewer->widget));
+ g_object_unref(GTK_WIDGET(viewer->widget));
claws_unlink(viewer->filename);
g_free(viewer->filename);
g_free(viewer);
viewer->widget = gtk_event_box_new();
gtk_widget_show(viewer->widget);
- gtk_widget_ref(viewer->widget);
+ g_object_ref(viewer->widget);
viewer->filename = NULL;
int okay;
GtkWidget *window;
GtkLabel *toplabel;
- GtkCList *clist;
+ GtkCMCList *clist;
const char *pattern;
unsigned int num_keys;
gpgme_key_t *kset;
};
-static void set_row (GtkCList *clist, gpgme_key_t key, gpgme_protocol_t proto);
+static void set_row (GtkCMCList *clist, gpgme_key_t key, gpgme_protocol_t proto);
static gpgme_key_t fill_clist (struct select_keys_s *sk, const char *pattern,
gpgme_protocol_t proto);
static void create_dialog (struct select_keys_s *sk);
do {
sk.pattern = recp_names? recp_names->data:NULL;
sk.proto = proto;
- gtk_clist_clear (sk.clist);
+ gtk_cmclist_clear (sk.clist);
key = fill_clist (&sk, sk.pattern, proto);
update_progress (&sk, 0, sk.pattern);
if (!key) {
}
static void
-set_row (GtkCList *clist, gpgme_key_t key, gpgme_protocol_t proto)
+set_row (GtkCMCList *clist, gpgme_key_t key, gpgme_protocol_t proto)
{
const char *s;
const char *text[N_COL_TITLES];
}
text[COL_VALIDITY] = s;
- row = gtk_clist_append (clist, (gchar**)text);
+ row = gtk_cmclist_append (clist, (gchar**)text);
g_free (algo_buf);
- gtk_clist_set_row_data_full (clist, row, key, destroy_key);
+ gtk_cmclist_set_row_data_full (clist, row, key, destroy_key);
}
static gpgme_key_t
fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t proto)
{
- GtkCList *clist;
+ GtkCMCList *clist;
gpgme_ctx_t ctx;
gpgme_error_t err;
gpgme_key_t key;
debug_print ("select_keys:fill_clist: pattern '%s' proto %d\n", pattern, proto);
- /*gtk_clist_freeze (select_keys.clist);*/
+ /*gtk_cmclist_freeze (select_keys.clist);*/
err = gpgme_new (&ctx);
g_assert (!err);
sk->select_ctx = NULL;
gpgme_release (ctx);
}
- /*gtk_clist_thaw (select_keys.clist);*/
+ /*gtk_cmclist_thaw (select_keys.clist);*/
return (exact_match == TRUE && num_results == 1 ? last_key:NULL);
}
titles[COL_EMAIL] = _("Address");
titles[COL_VALIDITY] = _("Val");
- clist = gtk_clist_new_with_titles (N_COL_TITLES, (char**)titles);
+ clist = gtk_cmclist_new_with_titles (N_COL_TITLES, (char**)titles);
gtk_container_add (GTK_CONTAINER (scrolledwin), clist);
- gtk_clist_set_column_width (GTK_CLIST(clist), COL_ALGO, 72);
- gtk_clist_set_column_width (GTK_CLIST(clist), COL_KEYID, 76);
- gtk_clist_set_column_width (GTK_CLIST(clist), COL_NAME, 130);
- gtk_clist_set_column_width (GTK_CLIST(clist), COL_EMAIL, 130);
- gtk_clist_set_column_width (GTK_CLIST(clist), COL_VALIDITY, 20);
- gtk_clist_set_selection_mode (GTK_CLIST(clist), GTK_SELECTION_BROWSE);
- g_signal_connect (G_OBJECT(GTK_CLIST(clist)->column[COL_NAME].button),
+ gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_ALGO, 72);
+ gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_KEYID, 76);
+ gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_NAME, 130);
+ gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_EMAIL, 130);
+ gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_VALIDITY, 20);
+ gtk_cmclist_set_selection_mode (GTK_CMCLIST(clist), GTK_SELECTION_BROWSE);
+ g_signal_connect (G_OBJECT(GTK_CMCLIST(clist)->column[COL_NAME].button),
"clicked",
G_CALLBACK(sort_keys_name), sk);
- g_signal_connect (G_OBJECT(GTK_CLIST(clist)->column[COL_EMAIL].button),
+ g_signal_connect (G_OBJECT(GTK_CMCLIST(clist)->column[COL_EMAIL].button),
"clicked",
G_CALLBACK(sort_keys_email), sk);
sk->window = window;
sk->toplabel = GTK_LABEL (label);
- sk->clist = GTK_CLIST (clist);
+ sk->clist = GTK_CMCLIST (clist);
}
return;
}
row = GPOINTER_TO_INT(sk->clist->selection->data);
- key = gtk_clist_get_row_data(sk->clist, row);
+ key = gtk_cmclist_get_row_data(sk->clist, row);
if (key) {
if ( key->uids->validity < GPGME_VALIDITY_FULL ) {
use_key = use_untrusted(key, sk->proto);
static gint
-cmp_name (GtkCList *clist, gconstpointer pa, gconstpointer pb)
+cmp_name (GtkCMCList *clist, gconstpointer pa, gconstpointer pb)
{
- gpgme_key_t a = ((GtkCListRow *)pa)->data;
- gpgme_key_t b = ((GtkCListRow *)pb)->data;
+ gpgme_key_t a = ((GtkCMCListRow *)pa)->data;
+ gpgme_key_t b = ((GtkCMCListRow *)pb)->data;
const char *sa, *sb;
sa = a? a->uids->name : NULL;
}
static gint
-cmp_email (GtkCList *clist, gconstpointer pa, gconstpointer pb)
+cmp_email (GtkCMCList *clist, gconstpointer pa, gconstpointer pb)
{
- gpgme_key_t a = ((GtkCListRow *)pa)->data;
- gpgme_key_t b = ((GtkCListRow *)pb)->data;
+ gpgme_key_t a = ((GtkCMCListRow *)pa)->data;
+ gpgme_key_t b = ((GtkCMCListRow *)pb)->data;
const char *sa, *sb;
sa = a? a->uids->email : NULL;
static void
sort_keys ( struct select_keys_s *sk, enum col_titles column)
{
- GtkCList *clist = sk->clist;
+ GtkCMCList *clist = sk->clist;
switch (column) {
case COL_NAME:
- gtk_clist_set_compare_func (clist, cmp_name);
+ gtk_cmclist_set_compare_func (clist, cmp_name);
break;
case COL_EMAIL:
- gtk_clist_set_compare_func (clist, cmp_email);
+ gtk_cmclist_set_compare_func (clist, cmp_email);
break;
default:
return;
sk->sort_type = GTK_SORT_ASCENDING;
sk->sort_column = column;
- gtk_clist_set_sort_type (clist, sk->sort_type);
- gtk_clist_sort (clist);
+ gtk_cmclist_set_sort_type (clist, sk->sort_type);
+ gtk_cmclist_sort (clist);
}
static void
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
-
+#include "gtkcmoptionmenu.h"
#include "main.h"
#include "prefs_gtk.h"
#include "prefs_account.h"
G_CALLBACK (crosspost_color_toggled),
NULL);
- colormenu_crosspost = gtk_option_menu_new();
+ colormenu_crosspost = gtk_cmoption_menu_new();
gtk_widget_show (colormenu_crosspost);
gtk_box_pack_start (GTK_BOX (hbox1), colormenu_crosspost, FALSE, FALSE, 0);
menu = colorlabel_create_color_menu();
- gtk_option_menu_set_menu (GTK_OPTION_MENU(colormenu_crosspost), menu);
+ gtk_cmoption_menu_set_menu (GTK_CMOPTION_MENU(colormenu_crosspost), menu);
SET_TOGGLE_SENSITIVITY(checkbtn_crosspost, colormenu_crosspost);
PACK_HBOX (hbox1);
GtkWidget *menu;
GtkWidget *menuitem;
- menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(advanced_page.crosspost_colormenu));
+ menu = gtk_cmoption_menu_get_menu(GTK_CMOPTION_MENU(advanced_page.crosspost_colormenu));
menuitem = gtk_menu_get_active(GTK_MENU(menu));
*((gint *)pparam->data) = GPOINTER_TO_INT
(g_object_get_data(G_OBJECT(menuitem), "color"));
static void prefs_account_crosspost_set_colormenu(PrefParam *pparam)
{
gint colorlabel = *((gint *)pparam->data);
- GtkOptionMenu *colormenu = GTK_OPTION_MENU(*pparam->widget);
+ GtkCMOptionMenu *colormenu = GTK_CMOPTION_MENU(*pparam->widget);
GtkWidget *menu;
GtkWidget *menuitem;
- gtk_option_menu_set_history(colormenu, colorlabel);
- menu = gtk_option_menu_get_menu(colormenu);
+ gtk_cmoption_menu_set_history(colormenu, colorlabel);
+ menu = gtk_cmoption_menu_get_menu(colormenu);
menuitem = gtk_menu_get_active(GTK_MENU(menu));
gtk_menu_item_activate(GTK_MENU_ITEM(menuitem));
}
#include <string.h>
#include <errno.h>
+#include "gtkcmoptionmenu.h"
#include "main.h"
#include "prefs_gtk.h"
#include "prefs_filtering_action.h"
prefs_filtering_action_create();
} else {
/* update color label menu */
- gtk_option_menu_set_menu(GTK_OPTION_MENU(filtering_action.color_optmenu),
+ gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(filtering_action.color_optmenu),
colorlabel_create_color_menu());
}
score_entry = gtk_spin_button_new_with_range(-1000, 1000, 1);
gtk_box_pack_start(GTK_BOX(hbox1), score_entry, FALSE, FALSE, 0);
- color_optmenu = gtk_option_menu_new();
+ color_optmenu = gtk_cmoption_menu_new();
gtk_size_group_add_widget(size_action, color_optmenu);
- gtk_option_menu_set_menu(GTK_OPTION_MENU(color_optmenu),
+ gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(color_optmenu),
colorlabel_create_color_menu());
prefs_filtering_action_check_widget_width(color_optmenu);
gtk_box_pack_start(GTK_BOX(hbox1), color_optmenu, FALSE, FALSE, 0);
break;
case ACTION_COLOR:
labelcolor = colorlabel_get_color_menu_active_item(
- gtk_option_menu_get_menu(GTK_OPTION_MENU(filtering_action.color_optmenu)));
+ gtk_cmoption_menu_get_menu(GTK_CMOPTION_MENU(filtering_action.color_optmenu)));
destination = NULL;
break;
case ACTION_CHANGE_SCORE:
gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), 0);
else if(GTK_IS_ENTRY(widget)) {
gtk_entry_set_text(GTK_ENTRY(widget), "");
- } else if(GTK_IS_OPTION_MENU(widget))
- gtk_option_menu_set_history(GTK_OPTION_MENU(widget), 0);
+ } else if(GTK_IS_CMOPTION_MENU(widget))
+ gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(widget), 0);
gtk_widget_set_sensitive(widget, TRUE);
gtk_widget_show(widget);
case MATCHACTION_COLOR:
combobox_select_by_data(GTK_COMBO_BOX(filtering_action.action_combo),
ACTION_COLOR);
- gtk_option_menu_set_history(GTK_OPTION_MENU(filtering_action.color_optmenu),
+ gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(filtering_action.color_optmenu),
action->labelcolor);
break;
case MATCHACTION_CHANGE_SCORE:
#include <string.h>
#include <errno.h>
+#include "gtkcmoptionmenu.h"
#include "main.h"
#include "prefs_gtk.h"
#include "prefs_matcher.h"
prefs_matcher_create();
} else {
/* update color label menu */
- gtk_option_menu_set_menu(GTK_OPTION_MENU(matcher.color_optmenu),
+ gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(matcher.color_optmenu),
colorlabel_create_color_menu());
}
gtk_box_pack_start(GTK_BOX(match_hbox), match_combo, TRUE, TRUE, 0);
/* color labels combo */
- color_optmenu = gtk_option_menu_new();
- gtk_option_menu_set_menu(GTK_OPTION_MENU(color_optmenu),
+ color_optmenu = gtk_cmoption_menu_new();
+ gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(color_optmenu),
colorlabel_create_color_menu());
gtk_box_pack_start(GTK_BOX(match_hbox), color_optmenu, FALSE, FALSE, 0);
gtk_combo_box_set_active(GTK_COMBO_BOX(matcher.criteria_combo2), 0);
gtk_combo_box_set_active(GTK_COMBO_BOX(matcher.match_combo), 0);
gtk_combo_box_set_active(GTK_COMBO_BOX(matcher.match_combo2), 0);
- gtk_option_menu_set_history(GTK_OPTION_MENU(matcher.color_optmenu), 0);
+ gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(matcher.color_optmenu), 0);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(matcher.numeric_entry), 0);
gtk_entry_set_text(GTK_ENTRY(matcher.header_entry), "");
gtk_entry_set_text(GTK_ENTRY(matcher.header_addr_entry), "");
case CRITERIA_COLORLABEL:
value = colorlabel_get_color_menu_active_item
- (gtk_option_menu_get_menu(GTK_OPTION_MENU
+ (gtk_cmoption_menu_get_menu(GTK_CMOPTION_MENU
(matcher.color_optmenu)));
break;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.case_checkbtn), FALSE);
break;
case MATCH_LABEL:
- gtk_option_menu_set_history(GTK_OPTION_MENU(matcher.color_optmenu), 0);
+ gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(matcher.color_optmenu), 0);
prefs_matcher_set_model(matcher.match_combo2, matcher.model_set);
gtk_label_set_text(GTK_LABEL(matcher.match_label), _("Label"));
gtk_label_set_text(GTK_LABEL(matcher.match_label2), _("is"));
case MATCHCRITERIA_NOT_COLORLABEL:
case MATCHCRITERIA_COLORLABEL:
- gtk_option_menu_set_history(GTK_OPTION_MENU(matcher.color_optmenu),
+ gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(matcher.color_optmenu),
prop->value);
- menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(matcher.color_optmenu));
+ menu = gtk_cmoption_menu_get_menu(GTK_CMOPTION_MENU(matcher.color_optmenu));
g_signal_emit_by_name(G_OBJECT(menu), "selection-done", menu);
break;