* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999. 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 <stdlib.h>
#include <string.h>
-#include "../config.h"
+#include "config.h"
#include "gtkmain.h"
#include "gtkclist.h"
#include "gtkbindings.h"
+#include "gtkdnd.h"
#include <gdk/gdkkeysyms.h>
+/* length of button_actions array */
+#define MAX_BUTTON 5
+
/* the number rows memchunk expands at a time */
-#define CLIST_OPTIMUM_SIZE 512
+#define CLIST_OPTIMUM_SIZE 64
/* the width of the column resize windows */
#define DRAG_WIDTH 6
/* used for auto-scrolling */
#define SCROLL_TIME 100
-/* scrollbar spacing class macro */
-#define SCROLLBAR_SPACING(w) (GTK_CLIST_CLASS (GTK_OBJECT (w)->klass)->scrollbar_spacing)
-
/* 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)) + \
gint i, cx;
for (i = 0; i < clist->columns; i++)
- {
- cx = clist->column[i].area.x + clist->hoffset;
+ 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;
- }
+ if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
+ x <= (cx + clist->column[i].area.width + COLUMN_INSET))
+ return i;
+ }
/* no match */
return -1;
#define LIST_HEIGHT(clist) (((clist)->row_height * ((clist)->rows)) + \
(CELL_SPACING * ((clist)->rows + 1)))
+
/* returns the total width of the list */
-#define LIST_WIDTH(clist) ((clist)->column[(clist)->columns - 1].area.x + \
- (clist)->column[(clist)->columns - 1].area.width + \
- COLUMN_INSET + CELL_SPACING)
+static inline gint
+LIST_WIDTH (GtkCList * 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)))
-#define GTK_CLIST_CLASS_FW(_widget_) GTK_CLIST_CLASS (GTK_OBJECT (_widget_)->klass)
+
+#define GTK_CLIST_CLASS_FW(_widget_) GTK_CLIST_CLASS (((GtkObject*) (_widget_))->klass)
+
+/* redraw the list if it's not frozen */
+#define CLIST_UNFROZEN(clist) (((GtkCList*) (clist))->freeze_count == 0)
+#define CLIST_REFRESH(clist) G_STMT_START { \
+ if (CLIST_UNFROZEN (clist)) \
+ GTK_CLIST_CLASS_FW (clist)->refresh ((GtkCList*) (clist)); \
+} G_STMT_END
/* Signals */
-enum
-{
+enum {
SELECT_ROW,
UNSELECT_ROW,
+ ROW_MOVE,
CLICK_COLUMN,
+ RESIZE_COLUMN,
TOGGLE_FOCUS_ROW,
SELECT_ALL,
UNSELECT_ALL,
LAST_SIGNAL
};
-enum
-{
+enum {
SYNC_REMOVE,
SYNC_INSERT
};
-
-typedef void (*GtkCListSignal1) (GtkObject * object,
- gint arg1,
- gint arg2,
- GdkEvent * arg3,
- gpointer data);
-
-typedef void (*GtkCListSignal2) (GtkObject *object,
- gpointer data);
-
-typedef void (*GtkCListSignal3) (GtkObject * object,
- gint arg1,
- gpointer data);
-typedef void (*GtkCListSignal4) (GtkObject * object,
- gint arg1,
- gfloat arg2,
- gpointer data);
-typedef void (*GtkCListSignal5) (GtkObject * object,
- gint arg1,
- gfloat arg2,
- gboolean arg3,
- gpointer data);
-
-
-static void sync_selection (GtkCList * clist,
- gint row,
- gint mode);
+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
+};
/* GtkCList Methods */
-static void gtk_clist_class_init (GtkCListClass * klass);
-static void gtk_clist_init (GtkCList * clist);
-static void real_clear (GtkCList * clist);
+static void gtk_clist_class_init (GtkCListClass *klass);
+static void gtk_clist_init (GtkCList *clist);
/* GtkObject Methods */
-static void gtk_clist_destroy (GtkObject * object);
-static void gtk_clist_finalize (GtkObject * object);
-
+static void gtk_clist_destroy (GtkObject *object);
+static void gtk_clist_finalize (GtkObject *object);
+static void gtk_clist_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_clist_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
/* GtkWidget Methods */
-static void gtk_clist_realize (GtkWidget * widget);
-static void gtk_clist_unrealize (GtkWidget * widget);
-static void gtk_clist_map (GtkWidget * widget);
-static void gtk_clist_unmap (GtkWidget * widget);
-static void gtk_clist_draw (GtkWidget * widget,
- GdkRectangle * area);
-static gint gtk_clist_expose (GtkWidget * widget,
- GdkEventExpose * event);
-static gint gtk_clist_button_press (GtkWidget * widget,
- GdkEventButton * event);
-static gint gtk_clist_button_release (GtkWidget * widget,
- GdkEventButton * event);
-static gint gtk_clist_motion (GtkWidget * widget,
- GdkEventMotion * event);
-static void gtk_clist_size_request (GtkWidget * widget,
- GtkRequisition * requisition);
-static void gtk_clist_size_allocate (GtkWidget * widget,
- GtkAllocation * allocation);
-static gint get_selection_info (GtkCList * clist,
- gint x,
- gint y,
- gint * row,
- gint * column);
+static void gtk_clist_set_scroll_adjustments (GtkCList *clist,
+ GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment);
+static void gtk_clist_realize (GtkWidget *widget);
+static void gtk_clist_unrealize (GtkWidget *widget);
+static void gtk_clist_map (GtkWidget *widget);
+static void gtk_clist_unmap (GtkWidget *widget);
+static void gtk_clist_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_clist_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_clist_key_press (GtkWidget *widget,
+ GdkEventKey *event);
+static gint gtk_clist_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_clist_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_clist_motion (GtkWidget *widget,
+ GdkEventMotion *event);
+static void gtk_clist_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_clist_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_clist_draw_focus (GtkWidget *widget);
+static gint gtk_clist_focus_in (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint gtk_clist_focus_out (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint gtk_clist_focus (GtkContainer *container,
+ GtkDirectionType direction);
+static void gtk_clist_style_set (GtkWidget *widget,
+ GtkStyle *previous_style);
+static void gtk_clist_drag_begin (GtkWidget *widget,
+ GdkDragContext *context);
+static gint gtk_clist_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time);
+static void gtk_clist_drag_leave (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time);
+static void gtk_clist_drag_end (GtkWidget *widget,
+ GdkDragContext *context);
+static gboolean gtk_clist_drag_drop (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time);
+static void gtk_clist_drag_data_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time);
+static void gtk_clist_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time);
/* GtkContainer Methods */
-static void gtk_clist_forall (GtkContainer *container,
- gboolean include_internals,
- GtkCallback callback,
- gpointer callback_data);
-
-/* Drawing */
-static void draw_row (GtkCList * clist,
- GdkRectangle * area,
- gint row,
- GtkCListRow * clist_row);
-static void draw_rows (GtkCList * clist,
- GdkRectangle * area);
-
-/* Size Allocation */
-static void size_allocate_title_buttons (GtkCList * clist);
-static void size_allocate_columns (GtkCList * clist);
+static void gtk_clist_set_focus_child (GtkContainer *container,
+ GtkWidget *child);
+static void gtk_clist_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
/* Selection */
-static void toggle_row (GtkCList * clist,
- gint row,
- gint column,
- GdkEvent * event);
-static void select_row (GtkCList * clist,
- gint row,
- gint column,
- GdkEvent * event);
-static void unselect_row (GtkCList * clist,
- gint row,
- gint column,
- GdkEvent * event);
-static void real_select_row (GtkCList * clist,
- gint row,
- gint column,
- GdkEvent * event);
-static void real_unselect_row (GtkCList * clist,
- gint row,
- gint column,
- GdkEvent * event);
-static void update_extended_selection (GtkCList *clist,
- gint row);
-static GList * selection_find (GtkCList *clist,
- gint row_number,
- GList *row_list_element);
-static void real_select_all (GtkCList * clist);
-static void real_unselect_all (GtkCList * clist);
-static void move_vertical (GtkCList *clist,
- gint row,
- gfloat align);
-static void move_horizontal (GtkCList *clist,
- gint diff);
-static void real_undo_selection (GtkCList * clist);
-static void fake_unselect_all (GtkCList *clist,
- gint row);
-static void fake_toggle_row (GtkCList *clist,
- gint row);
-static void resync_selection (GtkCList *clist,
- GdkEvent *event);
+static void toggle_row (GtkCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event);
+static void real_select_row (GtkCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event);
+static void real_unselect_row (GtkCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event);
+static void update_extended_selection (GtkCList *clist,
+ gint row);
+static GList *selection_find (GtkCList *clist,
+ gint row_number,
+ GList *row_list_element);
+static void real_select_all (GtkCList *clist);
+static void real_unselect_all (GtkCList *clist);
+static void move_vertical (GtkCList *clist,
+ gint row,
+ gfloat align);
+static void move_horizontal (GtkCList *clist,
+ gint diff);
+static void real_undo_selection (GtkCList *clist);
+static void fake_unselect_all (GtkCList *clist,
+ gint row);
+static void fake_toggle_row (GtkCList *clist,
+ gint row);
+static void resync_selection (GtkCList *clist,
+ GdkEvent *event);
+static void sync_selection (GtkCList *clist,
+ gint row,
+ gint mode);
+static void set_anchor (GtkCList *clist,
+ gboolean add_mode,
+ gint anchor,
+ gint undo_anchor);
+static void start_selection (GtkCList *clist);
+static void end_selection (GtkCList *clist);
+static void toggle_add_mode (GtkCList *clist);
+static void toggle_focus_row (GtkCList *clist);
+static void extend_selection (GtkCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position,
+ gboolean auto_start_selection);
+static gint get_selection_info (GtkCList *clist,
+ gint x,
+ gint y,
+ gint *row,
+ gint *column);
+
+/* Scrolling */
+static void move_focus_row (GtkCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position);
+static void scroll_horizontal (GtkCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position);
+static void scroll_vertical (GtkCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position);
+static void move_horizontal (GtkCList *clist,
+ gint diff);
+static void move_vertical (GtkCList *clist,
+ gint row,
+ gfloat align);
+static gint horizontal_timeout (GtkCList *clist);
+static gint vertical_timeout (GtkCList *clist);
+static void remove_grab (GtkCList *clist);
+
/* Resize Columns */
-static void draw_xor_line (GtkCList * clist);
-static gint new_column_width (GtkCList * clist,
- gint column,
- gint * x,
- gint * visible);
-static void resize_column (GtkCList * clist,
- gint column,
- gint width);
-static void abort_column_resize (GtkCList *clist);
+static void draw_xor_line (GtkCList *clist);
+static gint new_column_width (GtkCList *clist,
+ gint column,
+ gint *x);
+static void column_auto_resize (GtkCList *clist,
+ GtkCListRow *clist_row,
+ gint column,
+ gint old_width);
+static void real_resize_column (GtkCList *clist,
+ gint column,
+ gint width);
+static void abort_column_resize (GtkCList *clist);
+static void cell_size_request (GtkCList *clist,
+ GtkCListRow *clist_row,
+ gint column,
+ GtkRequisition *requisition);
/* Buttons */
-static void column_button_create (GtkCList * clist,
- gint column);
-static void column_button_clicked (GtkWidget * widget,
- gpointer data);
-
-/* Scrollbars */
-static void create_scrollbars (GtkCList * clist);
-static void adjust_scrollbars (GtkCList * clist);
-static void check_exposures (GtkCList * clist);
-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);
+static void column_button_create (GtkCList *clist,
+ gint column);
+static void column_button_clicked (GtkWidget *widget,
+ gpointer data);
+
+/* Adjustments */
+static void adjust_adjustments (GtkCList *clist,
+ gboolean block_resize);
+static void check_exposures (GtkCList *clist);
+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 (GtkCList *clist,
+ GtkCListRow *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 (GtkCList *clist,
+ GdkRectangle *area,
+ gint row,
+ GtkCListRow *clist_row);
+static void draw_rows (GtkCList *clist,
+ GdkRectangle *area);
+static void clist_refresh (GtkCList *clist);
+static void draw_drag_highlight (GtkCList *clist,
+ GtkCListRow *dest_row,
+ gint dest_row_number,
+ GtkCListDragPos drag_pos);
+
+/* Size Allocation / Requisition */
+static void size_allocate_title_buttons (GtkCList *clist);
+static void size_allocate_columns (GtkCList *clist,
+ gboolean block_resize);
+static gint list_requisition_width (GtkCList *clist);
/* Memory Allocation/Distruction Routines */
-static GtkCListColumn *columns_new (GtkCList * clist);
-
-static void column_title_new (GtkCList *clist,
- gint column,
- const gchar *title);
-static void columns_delete (GtkCList * clist);
-
-static GtkCListRow *row_new (GtkCList * clist);
-
-static void row_delete (GtkCList * clist,
- GtkCListRow * clist_row);
-static void set_cell_contents (GtkCList *clist,
- GtkCListRow *clist_row,
- gint column,
- GtkCellType type,
- const gchar *text,
- guint8 spacing,
- GdkPixmap *pixmap,
- GdkBitmap *mask);
-static gint real_insert_row (GtkCList * clist,
- gint row,
- gchar * text[]);
-static void real_remove_row (GtkCList * clist,
- gint row);
-
-/* Focus handling */
-static void gtk_clist_draw_focus (GtkWidget *widget);
-static gint gtk_clist_focus_in (GtkWidget *widget,
- GdkEventFocus *event);
-static gint gtk_clist_focus_out (GtkWidget *widget,
- GdkEventFocus *event);
-static gint gtk_clist_focus (GtkContainer *container,
- GtkDirectionType direction);
-static void gtk_clist_set_focus_child (GtkContainer *container,
- GtkWidget *child);
-static gint gtk_clist_key_press (GtkWidget *widget,
- GdkEventKey *event);
-
-/* Selection handling */
-static void set_anchor (GtkCList *clist,
- gboolean add_mode,
- gint anchor,
- gint undo_anchor);
-static void start_selection (GtkCList *clist);
-static void end_selection (GtkCList *clist);
-
-static void toggle_add_mode (GtkCList *clist);
-static void toggle_focus_row (GtkCList *clist);
-static void move_focus_row (GtkCList *clist,
- GtkScrollType scroll_type,
- gfloat position);
-static void scroll_horizontal (GtkCList *clist,
- GtkScrollType scroll_type,
- gfloat position);
-static void scroll_vertical (GtkCList *clist,
- GtkScrollType scroll_type,
- gfloat position);
-static void extend_selection (GtkCList *clist,
- GtkScrollType scroll_type,
- gfloat position,
- gboolean auto_start_selection);
+static GtkCListColumn *columns_new (GtkCList *clist);
+static void column_title_new (GtkCList *clist,
+ gint column,
+ const gchar *title);
+static void columns_delete (GtkCList *clist);
+static GtkCListRow *row_new (GtkCList *clist);
+static void row_delete (GtkCList *clist,
+ GtkCListRow *clist_row);
+static void set_cell_contents (GtkCList *clist,
+ GtkCListRow *clist_row,
+ gint column,
+ GtkCellType type,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask);
+static gint real_insert_row (GtkCList *clist,
+ gint row,
+ gchar *text[]);
+static void real_remove_row (GtkCList *clist,
+ gint row);
+static void real_clear (GtkCList *clist);
/* Sorting */
-static gint default_compare (GtkCList *clist,
- gconstpointer row1,
- gconstpointer row2);
-static GList * gtk_clist_merge (GtkCList *clist,
- GList *a,
- GList *b);
-static GList * gtk_clist_mergesort (GtkCList *clist,
- GList *list,
- gint num);
-static void real_sort_list (GtkCList *clist);
+static gint default_compare (GtkCList *clist,
+ gconstpointer row1,
+ gconstpointer row2);
+static void real_sort_list (GtkCList *clist);
+static GList *gtk_clist_merge (GtkCList *clist,
+ GList *a,
+ GList *b);
+static GList *gtk_clist_mergesort (GtkCList *clist,
+ GList *list,
+ gint num);
+/* Misc */
+static gboolean title_focus (GtkCList *clist,
+ gint dir);
+static void real_row_move (GtkCList *clist,
+ gint source_row,
+ gint dest_row);
+static gint column_title_passive_func (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data);
+static void drag_dest_cell (GtkCList *clist,
+ gint x,
+ gint y,
+ GtkCListDestInfo *dest_info);
-/* Fill in data after widget is realized and has style */
-static void add_style_data (GtkCList * clist);
static GtkContainerClass *parent_class = NULL;
static guint clist_signals[LAST_SIGNAL] = {0};
+static GtkTargetEntry clist_target_table = { "gtk-clist-drag-reorder", 0, 0};
GtkType
gtk_clist_get_type (void)
if (!clist_type)
{
- GtkTypeInfo clist_info =
+ static const GtkTypeInfo clist_info =
{
"GtkCList",
sizeof (GtkCList),
}
static void
-gtk_clist_class_init (GtkCListClass * klass)
+gtk_clist_class_init (GtkCListClass *klass)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
GtkContainerClass *container_class;
+ GtkBindingSet *binding_set;
object_class = (GtkObjectClass *) klass;
widget_class = (GtkWidgetClass *) klass;
parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
+ gtk_object_add_arg_type ("GtkCList::n_columns",
+ GTK_TYPE_UINT,
+ GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
+ ARG_N_COLUMNS);
+ gtk_object_add_arg_type ("GtkCList::shadow_type",
+ GTK_TYPE_SHADOW_TYPE,
+ GTK_ARG_READWRITE,
+ ARG_SHADOW_TYPE);
+ gtk_object_add_arg_type ("GtkCList::selection_mode",
+ GTK_TYPE_SELECTION_MODE,
+ GTK_ARG_READWRITE,
+ ARG_SELECTION_MODE);
+ gtk_object_add_arg_type ("GtkCList::row_height",
+ GTK_TYPE_UINT,
+ GTK_ARG_READWRITE,
+ ARG_ROW_HEIGHT);
+ gtk_object_add_arg_type ("GtkCList::reorderable",
+ GTK_TYPE_BOOL,
+ GTK_ARG_READWRITE,
+ ARG_REORDERABLE);
+ gtk_object_add_arg_type ("GtkCList::titles_active",
+ GTK_TYPE_BOOL,
+ GTK_ARG_READWRITE,
+ ARG_TITLES_ACTIVE);
+ gtk_object_add_arg_type ("GtkCList::use_drag_icons",
+ GTK_TYPE_BOOL,
+ GTK_ARG_READWRITE,
+ ARG_USE_DRAG_ICONS);
+ gtk_object_add_arg_type ("GtkCList::sort_type",
+ GTK_TYPE_SORT_TYPE,
+ GTK_ARG_READWRITE,
+ ARG_SORT_TYPE);
+ object_class->set_arg = gtk_clist_set_arg;
+ object_class->get_arg = gtk_clist_get_arg;
+ object_class->destroy = gtk_clist_destroy;
+ object_class->finalize = gtk_clist_finalize;
+
+
+ widget_class->set_scroll_adjustments_signal =
+ gtk_signal_new ("set_scroll_adjustments",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkCListClass, set_scroll_adjustments),
+ gtk_marshal_NONE__POINTER_POINTER,
+ GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
+
clist_signals[SELECT_ROW] =
gtk_signal_new ("select_row",
GTK_RUN_FIRST,
object_class->type,
GTK_SIGNAL_OFFSET (GtkCListClass, unselect_row),
gtk_marshal_NONE__INT_INT_POINTER,
- GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_GDK_EVENT);
+ GTK_TYPE_NONE, 3, GTK_TYPE_INT,
+ GTK_TYPE_INT, GTK_TYPE_GDK_EVENT);
+ clist_signals[ROW_MOVE] =
+ gtk_signal_new ("row_move",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkCListClass, row_move),
+ gtk_marshal_NONE__INT_INT,
+ GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
clist_signals[CLICK_COLUMN] =
gtk_signal_new ("click_column",
GTK_RUN_FIRST,
GTK_SIGNAL_OFFSET (GtkCListClass, click_column),
gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1, GTK_TYPE_INT);
+ clist_signals[RESIZE_COLUMN] =
+ gtk_signal_new ("resize_column",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkCListClass, resize_column),
+ gtk_marshal_NONE__INT_INT,
+ GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
clist_signals[TOGGLE_FOCUS_ROW] =
gtk_signal_new ("toggle_focus_row",
GTK_SIGNAL_OFFSET (GtkCListClass, abort_column_resize),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
-
-
gtk_object_class_add_signals (object_class, clist_signals, LAST_SIGNAL);
- object_class->destroy = gtk_clist_destroy;
- object_class->finalize = gtk_clist_finalize;
-
widget_class->realize = gtk_clist_realize;
widget_class->unrealize = gtk_clist_unrealize;
widget_class->map = gtk_clist_map;
widget_class->focus_in_event = gtk_clist_focus_in;
widget_class->focus_out_event = gtk_clist_focus_out;
widget_class->draw_focus = gtk_clist_draw_focus;
+ widget_class->style_set = gtk_clist_style_set;
+ widget_class->drag_begin = gtk_clist_drag_begin;
+ widget_class->drag_end = gtk_clist_drag_end;
+ widget_class->drag_motion = gtk_clist_drag_motion;
+ widget_class->drag_leave = gtk_clist_drag_leave;
+ widget_class->drag_drop = gtk_clist_drag_drop;
+ widget_class->drag_data_get = gtk_clist_drag_data_get;
+ widget_class->drag_data_received = gtk_clist_drag_data_received;
/* container_class->add = NULL; use the default GtkContainerClass warning */
- /* container_class->remove = NULL; use the default GtkContainerClass warning */
+ /* container_class->remove=NULL; use the default GtkContainerClass warning */
+
container_class->forall = gtk_clist_forall;
container_class->focus = gtk_clist_focus;
container_class->set_focus_child = gtk_clist_set_focus_child;
+ klass->set_scroll_adjustments = gtk_clist_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->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;
+
+ binding_set = gtk_binding_set_by_class (klass);
+ gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
+ "scroll_vertical", 2,
+ GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+ GTK_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
+ "scroll_vertical", 2,
+ GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+ GTK_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
+ "scroll_vertical", 2,
+ GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
+ GTK_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
+ "scroll_vertical", 2,
+ GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
+ GTK_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
+ "scroll_vertical", 2,
+ GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
+ GTK_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
+ "scroll_vertical", 2,
+ GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
+ GTK_TYPE_FLOAT, 1.0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Up, GDK_SHIFT_MASK,
+ "extend_selection", 3,
+ GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+ GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_Down, GDK_SHIFT_MASK,
+ "extend_selection", 3,
+ GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+ GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_SHIFT_MASK,
+ "extend_selection", 3,
+ GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
+ GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_SHIFT_MASK,
+ "extend_selection", 3,
+ GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
+ GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_Home,
+ GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "extend_selection", 3,
+ GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
+ GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_End,
+ GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "extend_selection", 3,
+ GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
+ GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
+ "scroll_horizontal", 2,
+ GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+ GTK_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
+ "scroll_horizontal", 2,
+ GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+ GTK_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
+ "scroll_horizontal", 2,
+ GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
+ GTK_TYPE_FLOAT, 0.0);
+ gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
+ "scroll_horizontal", 2,
+ GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
+ GTK_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_space, GDK_CONTROL_MASK,
+ "toggle_add_mode", 0);
+ gtk_binding_entry_add_signal (binding_set, '/', 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);
+}
- klass->scrollbar_spacing = 5;
+static void
+gtk_clist_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id)
+{
+ GtkCList *clist;
- {
- GtkBindingSet *binding_set;
-
- binding_set = gtk_binding_set_by_class (klass);
- gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
- "scroll_vertical", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
- "scroll_vertical", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
- "scroll_vertical", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
- "scroll_vertical", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
- "scroll_vertical", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
- "scroll_vertical", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
- GTK_TYPE_FLOAT, 1.0);
-
- gtk_binding_entry_add_signal (binding_set, GDK_Up, GDK_SHIFT_MASK,
- "extend_selection", 3,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
- GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_Down, GDK_SHIFT_MASK,
- "extend_selection", 3,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
- GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_SHIFT_MASK,
- "extend_selection", 3,
- GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
- GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_SHIFT_MASK,
- "extend_selection", 3,
- GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
- GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_Home,
- GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "extend_selection", 3,
- GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
- GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_End,
- GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "extend_selection", 3,
- GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
- GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
-
-
- gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
- "scroll_horizontal", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
- "scroll_horizontal", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
- "scroll_horizontal", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
- "scroll_horizontal", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
- GTK_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_space, GDK_CONTROL_MASK,
- "toggle_add_mode", 0);
- gtk_binding_entry_add_signal (binding_set, '/', 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);
- }
+ clist = GTK_CLIST (object);
- /*
- {
- GtkBindingSet *binding_set;
-
- binding_set = gtk_binding_set_by_class (klass);
- gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
- "scroll_vertical", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
- "scroll_vertical", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
- "scroll_vertical", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
- "scroll_vertical", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
- "scroll_vertical", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
- "scroll_vertical", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
- GTK_TYPE_FLOAT, 0);
-
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
- "extend_selection", 3,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
- GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
- "extend_selection", 3,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
- GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, 0,
- "extend_selection", 3,
- GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
- GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, 0,
- "extend_selection", 3,
- GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
- GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
- "extend_selection", 3,
- GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
- GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
- "extend_selection", 3,
- GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
- GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
-
- gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
- "scroll_horizontal", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
- "scroll_horizontal", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
- "scroll_horizontal", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
- "scroll_horizontal", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
- "scroll_horizontal", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
- GTK_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
- "sroll_horizontal", 2,
- GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
- GTK_TYPE_FLOAT, 1.0);
-
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Divide, 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_Multiply, 0,
- "toggle_add_mode", 0);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, 0,
- "select_all", 0);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, 0,
- "unselect_all", 0);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
- "end_selection", 0);
- }
- */
+ switch (arg_id)
+ {
+ case ARG_N_COLUMNS: /* construct-only arg, only set when !GTK_CONSTRUCTED */
+ gtk_clist_construct (clist, MAX (1, GTK_VALUE_UINT (*arg)), NULL);
+ break;
+ case ARG_SHADOW_TYPE:
+ gtk_clist_set_shadow_type (clist, GTK_VALUE_ENUM (*arg));
+ break;
+ case ARG_SELECTION_MODE:
+ gtk_clist_set_selection_mode (clist, GTK_VALUE_ENUM (*arg));
+ break;
+ case ARG_ROW_HEIGHT:
+ gtk_clist_set_row_height (clist, GTK_VALUE_UINT (*arg));
+ break;
+ case ARG_REORDERABLE:
+ gtk_clist_set_reorderable (clist, GTK_VALUE_BOOL (*arg));
+ break;
+ case ARG_TITLES_ACTIVE:
+ if (GTK_VALUE_BOOL (*arg))
+ gtk_clist_column_titles_active (clist);
+ else
+ gtk_clist_column_titles_passive (clist);
+ break;
+ case ARG_USE_DRAG_ICONS:
+ gtk_clist_set_use_drag_icons (clist, GTK_VALUE_BOOL (*arg));
+ break;
+ case ARG_SORT_TYPE:
+ gtk_clist_set_sort_type (clist, GTK_VALUE_ENUM (*arg));
+ break;
+ }
+}
+
+static void
+gtk_clist_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id)
+{
+ GtkCList *clist;
+
+ clist = GTK_CLIST (object);
+
+ switch (arg_id)
+ {
+ guint i;
+
+ case ARG_N_COLUMNS:
+ GTK_VALUE_UINT (*arg) = clist->columns;
+ break;
+ case ARG_SHADOW_TYPE:
+ GTK_VALUE_ENUM (*arg) = clist->shadow_type;
+ break;
+ case ARG_SELECTION_MODE:
+ GTK_VALUE_ENUM (*arg) = clist->selection_mode;
+ break;
+ case ARG_ROW_HEIGHT:
+ GTK_VALUE_UINT (*arg) = GTK_CLIST_ROW_HEIGHT_SET(clist) ? clist->row_height : 0;
+ break;
+ case ARG_REORDERABLE:
+ GTK_VALUE_BOOL (*arg) = GTK_CLIST_REORDERABLE (clist);
+ break;
+ case ARG_TITLES_ACTIVE:
+ GTK_VALUE_BOOL (*arg) = TRUE;
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].button &&
+ !GTK_WIDGET_SENSITIVE (clist->column[i].button))
+ {
+ GTK_VALUE_BOOL (*arg) = FALSE;
+ break;
+ }
+ break;
+ case ARG_USE_DRAG_ICONS:
+ GTK_VALUE_BOOL (*arg) = GTK_CLIST_USE_DRAG_ICONS (clist);
+ break;
+ case ARG_SORT_TYPE:
+ GTK_VALUE_ENUM (*arg) = clist->sort_type;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
}
static void
-gtk_clist_init (GtkCList * clist)
+gtk_clist_init (GtkCList *clist)
{
clist->flags = 0;
GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
- GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
+ GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
+ GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
+ GTK_CLIST_SET_FLAG (clist, CLIST_DRAW_DRAG_LINE);
+ GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
clist->row_mem_chunk = NULL;
clist->cell_mem_chunk = NULL;
+ clist->freeze_count = 0;
+
clist->rows = 0;
clist->row_center_offset = 0;
clist->row_height = 0;
clist->voffset = 0;
clist->shadow_type = GTK_SHADOW_IN;
- clist->hscrollbar_policy = GTK_POLICY_ALWAYS;
- clist->vscrollbar_policy = GTK_POLICY_ALWAYS;
+ clist->vadjustment = NULL;
+ clist->hadjustment = NULL;
+
+ clist->button_actions[0] = GTK_BUTTON_SELECTS | GTK_BUTTON_DRAGS;
+ clist->button_actions[1] = GTK_BUTTON_IGNORED;
+ clist->button_actions[2] = GTK_BUTTON_IGNORED;
+ clist->button_actions[3] = GTK_BUTTON_IGNORED;
+ clist->button_actions[4] = GTK_BUTTON_IGNORED;
clist->cursor_drag = NULL;
clist->xor_gc = NULL;
clist->undo_selection = NULL;
clist->undo_unselection = NULL;
- GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
- GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
clist->focus_row = -1;
clist->undo_anchor = -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;
/* Constructors */
void
-gtk_clist_construct (GtkCList * clist,
- gint columns,
- gchar *titles[])
+gtk_clist_construct (GtkCList *clist,
+ gint columns,
+ gchar *titles[])
{
- int i;
-
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- g_return_if_fail (GTK_CLIST_CONSTRUCTED (clist) == FALSE);
+ g_return_if_fail (columns > 0);
+ g_return_if_fail (GTK_OBJECT_CONSTRUCTED (clist) == FALSE);
- GTK_CLIST_SET_FLAG (clist, CLIST_CONSTRUCTED);
+ /* mark the object as constructed */
+ gtk_object_constructed (GTK_OBJECT (clist));
/* initalize memory chunks, if this has not been done by any
* possibly derived widget
if (!clist->row_mem_chunk)
clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
sizeof (GtkCListRow),
- sizeof (GtkCListRow) * CLIST_OPTIMUM_SIZE,
+ sizeof (GtkCListRow) *
+ CLIST_OPTIMUM_SIZE,
G_ALLOC_AND_FREE);
if (!clist->cell_mem_chunk)
clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
sizeof (GtkCell) * columns,
- sizeof (GtkCell) * columns * CLIST_OPTIMUM_SIZE,
+ sizeof (GtkCell) * columns *
+ CLIST_OPTIMUM_SIZE,
G_ALLOC_AND_FREE);
/* set number of columns, allocate memory */
* isn't there*/
column_button_create (clist, 0);
- /* create scrollbars */
- create_scrollbars (clist);
-
if (titles)
{
+ guint i;
+
GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
for (i = 0; i < columns; i++)
gtk_clist_set_column_title (clist, i, titles[i]);
}
}
-/*
- * GTKCLIST PUBLIC INTERFACE
- * gtk_clist_new_with_titles
+/* GTKCLIST PUBLIC INTERFACE
* gtk_clist_new
+ * gtk_clist_new_with_titles
+ * gtk_clist_set_hadjustment
+ * gtk_clist_set_vadjustment
+ * gtk_clist_get_hadjustment
+ * gtk_clist_get_vadjustment
+ * gtk_clist_set_shadow_type
+ * gtk_clist_set_selection_mode
+ * gtk_clist_freeze
+ * gtk_clist_thaw
*/
-GtkWidget *
-gtk_clist_new_with_titles (gint columns,
- gchar * titles[])
+GtkWidget*
+gtk_clist_new (gint columns)
+{
+ return gtk_clist_new_with_titles (columns, NULL);
+}
+
+GtkWidget*
+gtk_clist_new_with_titles (gint columns,
+ gchar *titles[])
{
GtkWidget *widget;
- g_return_val_if_fail (titles != NULL, NULL);
-
widget = gtk_type_new (GTK_TYPE_CLIST);
-
gtk_clist_construct (GTK_CLIST (widget), columns, titles);
return widget;
}
-GtkWidget *
-gtk_clist_new (gint columns)
+void
+gtk_clist_set_hadjustment (GtkCList *clist,
+ GtkAdjustment *adjustment)
{
- GtkCList *clist;
+ GtkAdjustment *old_adjustment;
- if (columns < 1)
- return NULL;
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
+ if (adjustment)
+ g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+
+ if (clist->hadjustment == adjustment)
+ return;
+
+ old_adjustment = clist->hadjustment;
+
+ if (clist->hadjustment)
+ {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (clist->hadjustment), clist);
+ gtk_object_unref (GTK_OBJECT (clist->hadjustment));
+ }
+
+ clist->hadjustment = adjustment;
+
+ if (clist->hadjustment)
+ {
+ gtk_object_ref (GTK_OBJECT (clist->hadjustment));
+ gtk_object_sink (GTK_OBJECT (clist->hadjustment));
+
+ gtk_signal_connect (GTK_OBJECT (clist->hadjustment), "changed",
+ (GtkSignalFunc) hadjustment_changed,
+ (gpointer) clist);
+ gtk_signal_connect (GTK_OBJECT (clist->hadjustment), "value_changed",
+ (GtkSignalFunc) hadjustment_value_changed,
+ (gpointer) clist);
+ }
+
+ if (!clist->hadjustment || !old_adjustment)
+ gtk_widget_queue_resize (GTK_WIDGET (clist));
+}
+
+GtkAdjustment *
+gtk_clist_get_hadjustment (GtkCList *clist)
+{
+ g_return_val_if_fail (clist != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
+
+ return clist->hadjustment;
+}
+
+void
+gtk_clist_set_vadjustment (GtkCList *clist,
+ GtkAdjustment *adjustment)
+{
+ GtkAdjustment *old_adjustment;
+
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
+ if (adjustment)
+ g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+
+ if (clist->vadjustment == adjustment)
+ return;
+
+ old_adjustment = clist->vadjustment;
+
+ if (clist->vadjustment)
+ {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (clist->vadjustment), clist);
+ gtk_object_unref (GTK_OBJECT (clist->vadjustment));
+ }
+
+ clist->vadjustment = adjustment;
+
+ if (clist->vadjustment)
+ {
+ gtk_object_ref (GTK_OBJECT (clist->vadjustment));
+ gtk_object_sink (GTK_OBJECT (clist->vadjustment));
+
+ gtk_signal_connect (GTK_OBJECT (clist->vadjustment), "changed",
+ (GtkSignalFunc) vadjustment_changed,
+ (gpointer) clist);
+ gtk_signal_connect (GTK_OBJECT (clist->vadjustment), "value_changed",
+ (GtkSignalFunc) vadjustment_value_changed,
+ (gpointer) clist);
+ }
- clist = gtk_type_new (GTK_TYPE_CLIST);
- gtk_clist_construct (clist, columns, NULL);
- return GTK_WIDGET (clist);
+ if (!clist->vadjustment || !old_adjustment)
+ gtk_widget_queue_resize (GTK_WIDGET (clist));
+}
+
+GtkAdjustment *
+gtk_clist_get_vadjustment (GtkCList *clist)
+{
+ g_return_val_if_fail (clist != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
+
+ return clist->vadjustment;
+}
+
+static void
+gtk_clist_set_scroll_adjustments (GtkCList *clist,
+ GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment)
+{
+ if (clist->hadjustment != hadjustment)
+ gtk_clist_set_hadjustment (clist, hadjustment);
+ if (clist->vadjustment != vadjustment)
+ gtk_clist_set_vadjustment (clist, vadjustment);
}
void
-gtk_clist_set_border (GtkCList * clist,
- GtkShadowType border)
+gtk_clist_set_shadow_type (GtkCList *clist,
+ GtkShadowType type)
{
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- clist->shadow_type = border;
+ clist->shadow_type = type;
if (GTK_WIDGET_VISIBLE (clist))
gtk_widget_queue_resize (GTK_WIDGET (clist));
}
void
-gtk_clist_set_selection_mode (GtkCList * clist,
- GtkSelectionMode mode)
+gtk_clist_set_selection_mode (GtkCList *clist,
+ GtkSelectionMode mode)
{
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
}
void
-gtk_clist_freeze (GtkCList * clist)
+gtk_clist_freeze (GtkCList *clist)
{
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
+ clist->freeze_count++;
}
void
-gtk_clist_thaw (GtkCList * clist)
+gtk_clist_thaw (GtkCList *clist)
{
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
-
- adjust_scrollbars (clist);
- draw_rows (clist, NULL);
-}
-
+ if (clist->freeze_count)
+ {
+ clist->freeze_count--;
+ CLIST_REFRESH (clist);
+ }
+}
+
+/* PUBLIC COLUMN FUNCTIONS
+ * gtk_clist_column_titles_show
+ * gtk_clist_column_titles_hide
+ * gtk_clist_column_title_active
+ * gtk_clist_column_title_passive
+ * gtk_clist_column_titles_active
+ * gtk_clist_column_titles_passive
+ * gtk_clist_set_column_title
+ * gtk_clist_get_column_title
+ * gtk_clist_set_column_widget
+ * gtk_clist_set_column_justification
+ * gtk_clist_set_column_visibility
+ * gtk_clist_set_column_resizeable
+ * gtk_clist_set_column_auto_resize
+ * gtk_clist_optimal_column_width
+ * gtk_clist_set_column_width
+ * gtk_clist_set_column_min_width
+ * gtk_clist_set_column_max_width
+ */
void
-gtk_clist_column_titles_show (GtkCList * clist)
+gtk_clist_column_titles_show (GtkCList *clist)
{
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (!GTK_CLIST_SHOW_TITLES (clist))
+ if (!GTK_CLIST_SHOW_TITLES(clist))
{
GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
if (clist->title_window)
- gdk_window_show (clist->title_window);
+ gdk_window_show (clist->title_window);
gtk_widget_queue_resize (GTK_WIDGET (clist));
}
}
void
-gtk_clist_column_titles_hide (GtkCList * clist)
+gtk_clist_column_titles_hide (GtkCList *clist)
{
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (GTK_CLIST_SHOW_TITLES (clist))
+ if (GTK_CLIST_SHOW_TITLES(clist))
{
GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
if (clist->title_window)
- gdk_window_hide (clist->title_window);
+ gdk_window_hide (clist->title_window);
gtk_widget_queue_resize (GTK_WIDGET (clist));
}
}
void
-gtk_clist_column_title_active (GtkCList * clist,
- gint column)
+gtk_clist_column_title_active (GtkCList *clist,
+ gint column)
{
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
if (column < 0 || column >= clist->columns)
return;
+ if (!clist->column[column].button || !clist->column[column].button_passive)
+ return;
- if (!GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
- !GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
- {
- GTK_WIDGET_SET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
- if (GTK_WIDGET_VISIBLE (clist))
- gtk_widget_queue_draw (clist->column[column].button);
- }
+ clist->column[column].button_passive = FALSE;
+
+ gtk_signal_disconnect_by_func (GTK_OBJECT (clist->column[column].button),
+ (GtkSignalFunc) column_title_passive_func,
+ NULL);
+
+ 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_clist_column_title_passive (GtkCList * clist,
- gint column)
+gtk_clist_column_title_passive (GtkCList *clist,
+ gint column)
{
+ GtkButton *button;
+
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
if (column < 0 || column >= clist->columns)
return;
+ if (!clist->column[column].button || clist->column[column].button_passive)
+ return;
- if (GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
- GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
- {
- GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
- if (GTK_WIDGET_VISIBLE (clist))
- gtk_widget_queue_draw (clist->column[column].button);
- }
+ 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);
+
+ gtk_signal_connect (GTK_OBJECT (clist->column[column].button), "event",
+ (GtkSignalFunc) 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_clist_column_titles_active (GtkCList * clist)
+gtk_clist_column_titles_active (GtkCList *clist)
{
gint i;
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
+ if (!GTK_CLIST_SHOW_TITLES(clist))
+ return;
+
for (i = 0; i < clist->columns; i++)
- if (clist->column[i].button)
- gtk_clist_column_title_active (clist, i);
+ gtk_clist_column_title_active (clist, i);
}
void
-gtk_clist_column_titles_passive (GtkCList * clist)
+gtk_clist_column_titles_passive (GtkCList *clist)
{
gint i;
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
+ if (!GTK_CLIST_SHOW_TITLES(clist))
+ return;
+
for (i = 0; i < clist->columns; i++)
- if (clist->column[i].button)
- gtk_clist_column_title_passive (clist, i);
+ gtk_clist_column_title_passive (clist, i);
}
void
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);
size_allocate_title_buttons (clist);
}
+gchar *
+gtk_clist_get_column_title (GtkCList *clist,
+ gint column)
+{
+ g_return_val_if_fail (clist != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
+
+ if (column < 0 || column >= clist->columns)
+ return NULL;
+
+ return clist->column[column].title;
+}
+
void
-gtk_clist_set_column_widget (GtkCList * clist,
- gint column,
- GtkWidget * widget)
+gtk_clist_set_column_widget (GtkCList *clist,
+ gint column,
+ GtkWidget *widget)
{
gint new_button = 0;
GtkWidget *old_widget;
/* 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);
+ gtk_container_remove (GTK_CONTAINER (clist->column[column].button),
+ old_widget);
/* add and show the widget */
if (widget)
size_allocate_title_buttons (clist);
}
+GtkWidget *
+gtk_clist_get_column_widget (GtkCList *clist,
+ gint column)
+{
+ g_return_val_if_fail (clist != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
+
+ if (column < 0 || column >= clist->columns)
+ return NULL;
+
+ if (clist->column[column].button)
+ return GTK_BUTTON (clist->column[column].button)->child;
+
+ return NULL;
+}
+
void
-gtk_clist_set_column_justification (GtkCList * clist,
- gint column,
- GtkJustification justification)
+gtk_clist_set_column_justification (GtkCList *clist,
+ gint column,
+ GtkJustification justification)
{
GtkWidget *alignment;
}
}
- if (!GTK_CLIST_FROZEN (clist))
+ if (CLIST_UNFROZEN (clist))
draw_rows (clist, NULL);
}
void
-gtk_clist_set_column_width (GtkCList * clist,
- gint column,
- gint width)
+gtk_clist_set_column_visibility (GtkCList *clist,
+ gint column,
+ gboolean visible)
{
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
if (column < 0 || column >= clist->columns)
return;
+ if (clist->column[column].visible == visible)
+ return;
- clist->column[column].width = width;
- clist->column[column].width_set = TRUE;
+ /* don't hide last visible column */
+ if (!visible)
+ {
+ gint i;
+ gint vis_columns = 0;
- /* 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);
- size_allocate_title_buttons (clist);
+ 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 (!GTK_CLIST_FROZEN (clist))
+ if (clist->column[column].button)
{
- adjust_scrollbars (clist);
- draw_rows (clist, NULL);
+ 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_clist_set_row_height (GtkCList * clist,
- gint height)
+gtk_clist_set_column_resizeable (GtkCList *clist,
+ gint column,
+ gboolean resizeable)
{
- gint text_height;
-
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (height > 0)
- clist->row_height = height;
- else
+ if (column < 0 || column >= clist->columns)
+ return;
+ if (clist->column[column].resizeable == resizeable)
return;
- GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
-
- if (GTK_WIDGET_REALIZED (clist))
- {
- text_height = height - (GTK_WIDGET (clist)->style->font->ascent +
- GTK_WIDGET (clist) ->style->font->descent + 1);
- clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
- }
-
- if (!GTK_CLIST_FROZEN (clist))
- {
- adjust_scrollbars (clist);
- draw_rows (clist, NULL);
- }
+ 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_clist_moveto (GtkCList * clist,
- gint row,
- gint column,
- gfloat row_align,
- gfloat col_align)
+gtk_clist_set_column_auto_resize (GtkCList *clist,
+ gint column,
+ gboolean auto_resize)
{
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (row < -1 || row >= clist->rows)
+ if (column < 0 || column >= clist->columns)
return;
- if (column < -1 || column >= clist->columns)
+ if (clist->column[column].auto_resize == auto_resize)
return;
- row_align = CLAMP (row_align, 0, 1);
- col_align = CLAMP (col_align, 0, 1);
-
- /* adjust horizontal scrollbar */
- if (column >= 0)
+ clist->column[column].auto_resize = auto_resize;
+ if (auto_resize)
{
- GtkAdjustment *adj;
- gint x;
-
- adj = GTK_RANGE (clist->hscrollbar)->adjustment;
+ clist->column[column].resizeable = FALSE;
+ if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
+ {
+ gint width;
- 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 (adj, 0.0);
- else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
- gtk_adjustment_set_value
- (adj, LIST_WIDTH (clist) - clist->clist_window_width);
- else
- gtk_adjustment_set_value (adj, x);
+ width = gtk_clist_optimal_column_width (clist, column);
+ gtk_clist_set_column_width (clist, column, width);
+ }
}
- /* adjust vertical scrollbar */
- if (row >= 0)
- move_vertical (clist, row, row_align);
-}
-
-GtkCellType
-gtk_clist_get_cell_type (GtkCList * clist,
- gint row,
- gint column)
-{
- GtkCListRow *clist_row;
-
- g_return_val_if_fail (clist != NULL, -1);
- g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
-
- if (row < 0 || row >= clist->rows)
- return -1;
- if (column < 0 || column >= clist->columns)
- return -1;
-
- clist_row = (g_list_nth (clist->row_list, row))->data;
-
- return clist_row->cell[column].type;
+ if (GTK_WIDGET_VISIBLE (clist))
+ size_allocate_title_buttons (clist);
}
-void
-gtk_clist_set_text (GtkCList *clist,
- gint row,
- gint column,
- const gchar *text)
+gint
+gtk_clist_columns_autosize (GtkCList *clist)
{
- GtkCListRow *clist_row;
-
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
-
- if (row < 0 || row >= clist->rows)
- return;
- if (column < 0 || column >= clist->columns)
- return;
-
- clist_row = (g_list_nth (clist->row_list, row))->data;
+ gint i;
+ gint width;
- /* if text is null, then the cell is empty */
- GTK_CLIST_CLASS_FW (clist)->set_cell_contents
- (clist, clist_row, column, GTK_CELL_TEXT, text, 0, NULL, NULL);
+ g_return_val_if_fail (clist != NULL, 0);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
- /* redraw the list if it's not frozen */
- if (!GTK_CLIST_FROZEN (clist))
+ gtk_clist_freeze (clist);
+ width = 0;
+ for (i = 0; i < clist->columns; i++)
{
- if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
- GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+ gtk_clist_set_column_width (clist, i,
+ gtk_clist_optimal_column_width (clist, i));
+
+ width += clist->column[i].width;
}
+
+ gtk_clist_thaw (clist);
+ return width;
}
gint
-gtk_clist_get_text (GtkCList * clist,
- gint row,
- gint column,
- gchar ** text)
+gtk_clist_optimal_column_width (GtkCList *clist,
+ gint column)
{
- GtkCListRow *clist_row;
+ GtkRequisition requisition;
+ GList *list;
+ gint width;
g_return_val_if_fail (clist != NULL, 0);
- g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
+ g_return_val_if_fail (GTK_CLIST (clist), 0);
- if (row < 0 || row >= clist->rows)
- return 0;
- if (column < 0 || column >= clist->columns)
+ if (column < 0 || column > clist->columns)
return 0;
- clist_row = (g_list_nth (clist->row_list, row))->data;
-
- if (clist_row->cell[column].type != GTK_CELL_TEXT)
- return 0;
+ if (GTK_CLIST_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;
- if (text)
- *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
+ for (list = clist->row_list; list; list = list->next)
+ {
+ GTK_CLIST_CLASS_FW (clist)->cell_size_request
+ (clist, GTK_CLIST_ROW (list), column, &requisition);
+ width = MAX (width, requisition.width);
+ }
- return 1;
+ return width;
}
void
-gtk_clist_set_pixmap (GtkCList * clist,
- gint row,
- gint column,
- GdkPixmap * pixmap,
- GdkBitmap * mask)
+gtk_clist_set_column_width (GtkCList *clist,
+ gint column,
+ gint width)
{
- GtkCListRow *clist_row;
-
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (row < 0 || row >= clist->rows)
- return;
if (column < 0 || column >= clist->columns)
return;
- clist_row = (g_list_nth (clist->row_list, row))->data;
-
- gdk_pixmap_ref (pixmap);
-
- if (mask) gdk_pixmap_ref (mask);
-
- GTK_CLIST_CLASS_FW (clist)->set_cell_contents
- (clist, clist_row, column, GTK_CELL_PIXMAP, NULL, 0, pixmap, mask);
-
- /* redraw the list if it's not frozen */
- if (!GTK_CLIST_FROZEN (clist))
- {
- if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
- GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
- }
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[RESIZE_COLUMN],
+ column, width);
}
-gint
-gtk_clist_get_pixmap (GtkCList * clist,
- gint row,
- gint column,
- GdkPixmap ** pixmap,
- GdkBitmap ** mask)
+void
+gtk_clist_set_column_min_width (GtkCList *clist,
+ gint column,
+ gint min_width)
{
- GtkCListRow *clist_row;
-
- g_return_val_if_fail (clist != NULL, 0);
- g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- if (row < 0 || row >= clist->rows)
- return 0;
if (column < 0 || column >= clist->columns)
- return 0;
-
- clist_row = (g_list_nth (clist->row_list, row))->data;
-
- if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
- return 0;
+ return;
+ if (clist->column[column].min_width == min_width)
+ return;
- if (pixmap)
- {
- *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
- /* mask can be NULL */
- *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
- }
+ 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;
- return 1;
+ if (clist->column[column].area.width < clist->column[column].min_width)
+ gtk_clist_set_column_width (clist, column,clist->column[column].min_width);
}
void
-gtk_clist_set_pixtext (GtkCList *clist,
- gint row,
- gint column,
- const gchar *text,
- guint8 spacing,
- GdkPixmap *pixmap,
- GdkBitmap *mask)
+gtk_clist_set_column_max_width (GtkCList *clist,
+ gint column,
+ gint max_width)
{
- GtkCListRow *clist_row;
-
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (row < 0 || row >= clist->rows)
- return;
if (column < 0 || column >= clist->columns)
return;
+ if (clist->column[column].max_width == max_width)
+ return;
- clist_row = (g_list_nth (clist->row_list, row))->data;
+ 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;
- gdk_pixmap_ref (pixmap);
- if (mask) gdk_pixmap_ref (mask);
- GTK_CLIST_CLASS_FW (clist)->set_cell_contents
- (clist, clist_row, column, GTK_CELL_PIXTEXT, text, spacing, pixmap, mask);
-
- /* redraw the list if it's not frozen */
- if (!GTK_CLIST_FROZEN (clist))
- {
- if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
- GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
- }
+ if (clist->column[column].area.width > clist->column[column].max_width)
+ gtk_clist_set_column_width (clist, column,clist->column[column].max_width);
}
-gint
-gtk_clist_get_pixtext (GtkCList * clist,
- gint row,
- gint column,
- gchar ** text,
- guint8 * spacing,
- GdkPixmap ** pixmap,
- GdkBitmap ** mask)
+/* 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 (GtkCList *clist,
+ GtkCListRow *clist_row,
+ gint column,
+ gint old_width)
{
- GtkCListRow *clist_row;
-
- g_return_val_if_fail (clist != NULL, 0);
- g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
-
- if (row < 0 || row >= clist->rows)
- return 0;
- if (column < 0 || column >= clist->columns)
- return 0;
+ /* resize column if needed for auto_resize */
+ GtkRequisition requisition;
- clist_row = (g_list_nth (clist->row_list, row))->data;
+ if (!clist->column[column].auto_resize ||
+ GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
+ return;
- if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
- return 0;
+ if (clist_row)
+ GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
+ column, &requisition);
+ else
+ requisition.width = 0;
- if (text)
- *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
- if (spacing)
- *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
- if (pixmap)
- *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
+ if (requisition.width > clist->column[column].width)
+ gtk_clist_set_column_width (clist, column, requisition.width);
+ else if (requisition.width < old_width &&
+ old_width == clist->column[column].width)
+ {
+ GList *list;
+ gint new_width = 0;
- /* mask can be NULL */
- *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
+ /* run a "gtk_clist_optimal_column_width" but break, if
+ * the column doesn't shrink */
+ if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button)
+ new_width = (clist->column[column].button->requisition.width -
+ (CELL_SPACING + (2 * COLUMN_INSET)));
+ else
+ new_width = 0;
- return 1;
+ for (list = clist->row_list; list; list = list->next)
+ {
+ GTK_CLIST_CLASS_FW (clist)->cell_size_request
+ (clist, GTK_CLIST_ROW (list), column, &requisition);
+ new_width = MAX (new_width, requisition.width);
+ if (new_width == clist->column[column].width)
+ break;
+ }
+ if (new_width < clist->column[column].width)
+ gtk_clist_set_column_width
+ (clist, column, MAX (new_width, clist->column[column].min_width));
+ }
}
-void
-gtk_clist_set_foreground (GtkCList * clist,
- gint row,
- GdkColor * color)
+static void
+real_resize_column (GtkCList *clist,
+ gint column,
+ gint width)
{
- GtkCListRow *clist_row;
-
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (row < 0 || row >= clist->rows)
+ 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_row = (g_list_nth (clist->row_list, row))->data;
+ clist->column[column].width = width;
+ clist->column[column].width_set = TRUE;
- if (color)
- {
- clist_row->foreground = *color;
- clist_row->fg_set = TRUE;
- }
- else
- clist_row->fg_set = FALSE;
+ /* 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);
- if (!GTK_CLIST_FROZEN (clist)
- && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
- GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+ CLIST_REFRESH (clist);
}
-void
-gtk_clist_set_background (GtkCList * clist,
- gint row,
- GdkColor * color)
+static void
+abort_column_resize (GtkCList *clist)
{
- GtkCListRow *clist_row;
-
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (row < 0 || row >= clist->rows)
+ if (!GTK_CLIST_IN_DRAG(clist))
return;
- clist_row = (g_list_nth (clist->row_list, row))->data;
+ GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
+ gtk_grab_remove (GTK_WIDGET (clist));
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ clist->drag_pos = -1;
- if (color)
+ if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
+ draw_xor_line (clist);
+
+ if (GTK_CLIST_ADD_MODE(clist))
{
- clist_row->background = *color;
- clist_row->bg_set = TRUE;
+ 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
- clist_row->bg_set = FALSE;
-
- if (!GTK_CLIST_FROZEN (clist)
- && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
- GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
}
-void
-gtk_clist_set_shift (GtkCList * clist,
- gint row,
- gint column,
- gint vertical,
- gint horizontal)
+static void
+size_allocate_title_buttons (GtkCList *clist)
{
- GtkCListRow *clist_row;
-
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ GtkAllocation button_allocation;
+ gint last_column;
+ gint last_button = 0;
+ gint i;
- if (row < 0 || row >= clist->rows)
- return;
- if (column < 0 || column >= clist->columns)
+ if (!GTK_WIDGET_REALIZED (clist))
return;
- clist_row = (g_list_nth (clist->row_list, row))->data;
+ button_allocation.x = clist->hoffset;
+ button_allocation.y = 0;
+ button_allocation.width = 0;
+ button_allocation.height = clist->column_title_area.height;
- clist_row->cell[column].vertical = vertical;
- clist_row->cell[column].horizontal = horizontal;
+ /* find last visible column */
+ for (last_column = clist->columns - 1; last_column >= 0; last_column--)
+ if (clist->column[last_column].visible)
+ break;
- if (!GTK_CLIST_FROZEN (clist)
- && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
- GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
-}
+ for (i = 0; i < last_column; i++)
+ {
+ if (!clist->column[i].visible)
+ {
+ last_button = i + 1;
+ gdk_window_hide (clist->column[i].window);
+ continue;
+ }
-void
-gtk_clist_set_selectable (GtkCList *clist,
- gint row,
- gboolean selectable)
-{
- GtkCListRow *clist_row;
+ button_allocation.width += (clist->column[i].area.width +
+ CELL_SPACING + 2 * COLUMN_INSET);
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
-
- if (row < 0 || row >= clist->rows)
- return;
-
- clist_row = (g_list_nth (clist->row_list, 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_EXTENDED)
+ if (!clist->column[i + 1].button)
{
- if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)))
- {
- GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
- gtk_grab_remove (GTK_WIDGET (clist));
- gdk_pointer_ungrab (GDK_CURRENT_TIME);
- if (clist->htimer)
- {
- gtk_timeout_remove (clist->htimer);
- clist->htimer = 0;
- }
- if (clist->vtimer)
- {
- gtk_timeout_remove (clist->vtimer);
- clist->vtimer = 0;
- }
- }
- GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+ gdk_window_hide (clist->column[i].window);
+ continue;
}
- unselect_row (clist, row, -1, NULL);
- }
-}
-gboolean
-gtk_clist_get_selectable (GtkCList *clist,
- gint row)
-{
- g_return_val_if_fail (clist != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
+ gtk_widget_size_allocate (clist->column[last_button].button,
+ &button_allocation);
+ button_allocation.x += button_allocation.width;
+ button_allocation.width = 0;
- if (row < 0 || row >= clist->rows)
- return FALSE;
+ 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);
- return GTK_CLIST_ROW (g_list_nth (clist->row_list, row))->selectable;
-}
+ last_button = i + 1;
+ }
-gint
-gtk_clist_append (GtkCList * clist,
- gchar * text[])
-{
- g_return_val_if_fail (clist != NULL, -1);
- g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
- g_return_val_if_fail (text != NULL, -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);
- return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, clist->rows, text);
-}
+ if (clist->column[last_button].resizeable)
+ {
+ button_allocation.x += button_allocation.width;
-gint
-gtk_clist_insert (GtkCList * clist,
- gint row,
- gchar * text[])
-{
- return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, row, text);
+ 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 gint
-real_insert_row (GtkCList * clist,
- gint row,
- gchar * text[])
+static void
+size_allocate_columns (GtkCList *clist,
+ gboolean block_resize)
{
+ gint xoffset = CELL_SPACING + COLUMN_INSET;
+ gint last_column;
gint i;
- GtkCListRow *clist_row;
-
- g_return_val_if_fail (clist != NULL, -1);
- g_return_val_if_fail (GTK_IS_CLIST (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);
+ /* 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--);
- /* set the text in the row's columns */
- for (i = 0; i < clist->columns; i++)
- if (text[i])
- GTK_CLIST_CLASS_FW (clist)->set_cell_contents
- (clist, clist_row, i, GTK_CELL_TEXT, text[i], 0, NULL ,NULL);
+ if (last_column < 0)
+ return;
- if (!clist->rows)
- {
- clist->row_list = g_list_append (clist->row_list, clist_row);
- clist->row_list_end = clist->row_list;
- }
- else
+ for (i = 0; i <= last_column; i++)
{
- if (GTK_CLIST_AUTO_SORT (clist)) /* override insertion pos */
+ if (!clist->column[i].visible)
+ continue;
+ clist->column[i].area.x = xoffset;
+ if (clist->column[i].width_set)
{
- 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_CLIST_ROW (work)) > 0)
- {
- row++;
- work = work->next;
- }
- }
- else
+ if (!block_resize && GTK_CLIST_SHOW_TITLES(clist) &&
+ clist->column[i].auto_resize && clist->column[i].button)
{
- while (row < clist->rows &&
- clist->compare (clist, clist_row,
- GTK_CLIST_ROW (work)) < 0)
- {
- row++;
- work = work->next;
- }
+ gint width;
+
+ width = (clist->column[i].button->requisition.width -
+ (CELL_SPACING + (2 * COLUMN_INSET)));
+
+ if (width > clist->column[i].width)
+ gtk_clist_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_CLIST_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;
}
-
- /* 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);
+ clist->column[last_column].area.width = clist->column[last_column].area.width
+ + MAX (0, clist->clist_window_width + COLUMN_INSET - xoffset);
+}
- /* syncronize the selection list */
- sync_selection (clist, row, SYNC_INSERT);
+static gint
+list_requisition_width (GtkCList *clist)
+{
+ gint width = CELL_SPACING;
+ gint i;
- /* redraw the list if it isn't frozen */
- if (!GTK_CLIST_FROZEN (clist))
+ for (i = clist->columns - 1; i >= 0; i--)
{
- adjust_scrollbars (clist);
+ if (!clist->column[i].visible)
+ continue;
- if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
- draw_rows (clist, NULL);
+ if (clist->column[i].width_set)
+ width += clist->column[i].width + CELL_SPACING + (2 * COLUMN_INSET);
+ else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
+ width += clist->column[i].button->requisition.width;
}
- return row;
-}
-
-void
-gtk_clist_remove (GtkCList * clist,
- gint row)
-{
- GTK_CLIST_CLASS_FW (clist)->remove_row (clist, row);
+ return width;
}
-static void
-real_remove_row (GtkCList * clist,
- gint row)
+/* 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 (GtkCList *clist,
+ gint column,
+ gint *x)
{
- gint was_visible, was_selected;
- GList *list;
- GtkCListRow *clist_row;
-
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ gint xthickness = GTK_WIDGET (clist)->style->klass->xthickness;
+ gint width;
+ gint cx;
+ gint dx;
+ gint last_column;
- /* return if out of bounds */
- if (row < 0 || row > (clist->rows - 1))
- return;
+ /* first translate the x position from widget->window
+ * to clist->clist_window */
+ cx = *x - xthickness;
- was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
- was_selected = 0;
+ for (last_column = clist->columns - 1;
+ last_column >= 0 && !clist->column[last_column].visible; last_column--);
- /* get the row we're going to delete */
- list = g_list_nth (clist->row_list, row);
- clist_row = list->data;
+ /* 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 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)
+ if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
{
- switch (clist->selection_mode)
- {
- case GTK_SELECTION_SINGLE:
- case GTK_SELECTION_MULTIPLE:
- case GTK_SELECTION_EXTENDED:
- unselect_row (clist, row, -1, NULL);
- break;
-
- case GTK_SELECTION_BROWSE:
- select_row (clist, row - 1, -1, NULL);
- break;
-
- default:
- break;
- }
+ 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;
+ }
- /* reset the row end pointer if we're removing at the
- * end of the list */
- if (row == clist->rows - 1)
- clist->row_list_end = list->prev;
- if (row >= clist->focus_row && clist->focus_row >=0)
- clist->focus_row--;
+ if (cx < 0 || cx > clist->clist_window_width)
+ *x = -1;
- clist->row_list = g_list_remove (clist->row_list, clist_row);
- clist->rows--;
-
- if (row < ROW_FROM_YPIXEL (clist, 0))
- clist->voffset += clist->row_height + CELL_SPACING;
+ return width;
+}
- sync_selection (clist, row, SYNC_REMOVE);
+static void
+column_button_create (GtkCList *clist,
+ gint column)
+{
+ GtkWidget *button;
- /* toast the row */
- row_delete (clist, clist_row);
+ gtk_widget_push_composite_child ();
+ button = clist->column[column].button = gtk_button_new ();
+ gtk_widget_pop_composite_child ();
- /* redraw the row if it isn't frozen */
- if (!GTK_CLIST_FROZEN (clist))
- {
- adjust_scrollbars (clist);
+ 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));
- if (was_visible)
- draw_rows (clist, NULL);
- }
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) column_button_clicked,
+ (gpointer) clist);
+ gtk_widget_show (button);
}
static void
-sync_selection (GtkCList * clist,
- gint row,
- gint mode)
+column_button_clicked (GtkWidget *widget,
+ gpointer data)
{
- GList *list;
- gint d;
-
- if (mode == SYNC_INSERT)
- d = 1;
- else
- d = -1;
-
- if (clist->focus_row >= row)
- {
- clist->focus_row += d;
- if (clist->focus_row == -1 && clist->rows >= 1)
- clist->focus_row = 0;
- }
+ gint i;
+ GtkCList *clist;
- if (clist->selection_mode == GTK_SELECTION_BROWSE && clist->anchor != -1)
- GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (data));
- g_list_free (clist->undo_selection);
- g_list_free (clist->undo_unselection);
- clist->undo_selection = NULL;
- clist->undo_unselection = NULL;
+ clist = GTK_CLIST (data);
- clist->anchor = -1;
- clist->drag_pos = -1;
- clist->undo_anchor = clist->focus_row;
+ /* find the column who's button was pressed */
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].button == widget)
+ break;
- list = clist->selection;
- while (list)
- {
- if (GPOINTER_TO_INT (list->data) >= row)
- list->data = ((gchar*) list->data) + d;
- list = list->next;
- }
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
}
-void
-gtk_clist_clear (GtkCList * clist)
+static gint
+column_title_passive_func (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data)
{
- GTK_CLIST_CLASS_FW (clist)->clear (clist);
+ 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;
}
-static void
-real_clear (GtkCList * clist)
+
+/* PUBLIC CELL FUNCTIONS
+ * gtk_clist_get_cell_type
+ * gtk_clist_set_text
+ * gtk_clist_get_text
+ * gtk_clist_set_pixmap
+ * gtk_clist_get_pixmap
+ * gtk_clist_set_pixtext
+ * gtk_clist_get_pixtext
+ * gtk_clist_set_shift
+ */
+GtkCellType
+gtk_clist_get_cell_type (GtkCList *clist,
+ gint row,
+ gint column)
{
- GList *list;
+ GtkCListRow *clist_row;
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
-
- /* remove all the rows */
- for (list = clist->row_list; list; list = list->next)
- row_delete (clist, GTK_CLIST_ROW (list));
-
- g_list_free (clist->row_list);
+ g_return_val_if_fail (clist != NULL, -1);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
- /* free up the selection list */
- g_list_free (clist->selection);
- g_list_free (clist->undo_selection);
- g_list_free (clist->undo_unselection);
+ if (row < 0 || row >= clist->rows)
+ return -1;
+ if (column < 0 || column >= clist->columns)
+ return -1;
- clist->row_list = NULL;
- clist->row_list_end = NULL;
- clist->selection = NULL;
- clist->selection_end = NULL;
- clist->undo_selection = NULL;
- clist->undo_unselection = NULL;
- clist->voffset = 0;
- clist->rows = 0;
- clist->focus_row = -1;
- clist->anchor = -1;
- clist->undo_anchor = -1;
- clist->anchor_state = GTK_STATE_SELECTED;
- clist->drag_pos = -1;
+ clist_row = ROW_ELEMENT (clist, row)->data;
- /* zero-out the scrollbars */
- if (clist->vscrollbar)
- {
- GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
- gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
-
- if (!GTK_CLIST_FROZEN (clist))
- gtk_clist_thaw (clist);
- }
+ return clist_row->cell[column].type;
}
-void
-gtk_clist_swap_rows (GtkCList * clist,
- gint row1,
- gint row2)
+void
+gtk_clist_set_text (GtkCList *clist,
+ gint row,
+ gint column,
+ const gchar *text)
{
- gint first, last;
- GList *list, *link1, *link2;
- gpointer swap;
-
+ GtkCListRow *clist_row;
+
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (GTK_CLIST_AUTO_SORT (clist))
- return;
-
- if (row1 < 0 || row1 > (clist->rows - 1))
+ if (row < 0 || row >= clist->rows)
return;
-
- if (row2 < 0 || row2 > (clist->rows - 1))
+ if (column < 0 || column >= clist->columns)
return;
- first = MIN (row1, row2);
- last = MAX (row1, row2);
+ clist_row = ROW_ELEMENT (clist, row)->data;
- link1 = g_list_nth (clist->row_list, first);
- link2 = g_list_nth (link1, row2 - row1);
+ /* if text is null, then the cell is empty */
+ GTK_CLIST_CLASS_FW (clist)->set_cell_contents
+ (clist, clist_row, column, GTK_CELL_TEXT, text, 0, NULL, NULL);
- swap = link1->data;
- link1->data = link2->data;
- link2->data = swap;
-
- list = clist->selection;
- while (list)
- {
- if (GPOINTER_TO_INT (list->data) == row1)
- list->data = GINT_TO_POINTER (row2);
-
- if (GPOINTER_TO_INT (list->data) == row2)
- list->data = GINT_TO_POINTER (row1);
-
- list = list->next;
- }
-
- if (!GTK_CLIST_FROZEN (clist))
+ /* redraw the list if it's not frozen */
+ if (CLIST_UNFROZEN (clist))
{
- if (gtk_clist_row_is_visible (clist, row1) != GTK_VISIBILITY_NONE)
- GTK_CLIST_CLASS_FW (clist)->draw_row
- (clist, NULL, row1, GTK_CLIST_ROW (link2));
-
- if (gtk_clist_row_is_visible (clist, row2) != GTK_VISIBILITY_NONE)
- GTK_CLIST_CLASS_FW (clist)->draw_row
- (clist, NULL, row2, GTK_CLIST_ROW (link1));
+ if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
}
}
-void
-gtk_clist_set_row_data (GtkCList * clist,
- gint row,
- gpointer data)
+gint
+gtk_clist_get_text (GtkCList *clist,
+ gint row,
+ gint column,
+ gchar **text)
{
- gtk_clist_set_row_data_full (clist, row, data, NULL);
+ GtkCListRow *clist_row;
+
+ g_return_val_if_fail (clist != NULL, 0);
+ g_return_val_if_fail (GTK_IS_CLIST (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_CELL_TEXT)
+ return 0;
+
+ if (text)
+ *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
+
+ return 1;
}
void
-gtk_clist_set_row_data_full (GtkCList * clist,
- gint row,
- gpointer data,
- GtkDestroyNotify destroy)
+gtk_clist_set_pixmap (GtkCList *clist,
+ gint row,
+ gint column,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask)
{
GtkCListRow *clist_row;
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (row < 0 || row > (clist->rows - 1))
+ if (row < 0 || row >= clist->rows)
+ return;
+ if (column < 0 || column >= clist->columns)
return;
- clist_row = (g_list_nth (clist->row_list, row))->data;
- clist_row->data = data;
- clist_row->destroy = destroy;
-}
-
-gpointer
-gtk_clist_get_row_data (GtkCList * clist,
- gint row)
-{
- GtkCListRow *clist_row;
-
- g_return_val_if_fail (clist != NULL, NULL);
- g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
-
- if (row < 0 || row > (clist->rows - 1))
- return NULL;
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ gdk_pixmap_ref (pixmap);
+
+ if (mask) gdk_pixmap_ref (mask);
+
+ GTK_CLIST_CLASS_FW (clist)->set_cell_contents
+ (clist, clist_row, column, GTK_CELL_PIXMAP, NULL, 0, pixmap, mask);
- clist_row = (g_list_nth (clist->row_list, row))->data;
- return clist_row->data;
+ /* redraw the list if it's not frozen */
+ if (CLIST_UNFROZEN (clist))
+ {
+ if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+ }
}
gint
-gtk_clist_find_row_from_data (GtkCList * clist,
- gpointer data)
+gtk_clist_get_pixmap (GtkCList *clist,
+ gint row,
+ gint column,
+ GdkPixmap **pixmap,
+ GdkBitmap **mask)
{
- GList *list;
- gint n;
-
- g_return_val_if_fail (clist != NULL, -1);
- g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
-
- if (clist->rows < 1)
- return -1; /* is this an optimization or just worthless? */
+ GtkCListRow *clist_row;
- for (n = 0, list = clist->row_list; list; n++, list = list->next)
- if (GTK_CLIST_ROW (list)->data == data)
- return n;
+ g_return_val_if_fail (clist != NULL, 0);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
- return -1;
-}
+ if (row < 0 || row >= clist->rows)
+ return 0;
+ if (column < 0 || column >= clist->columns)
+ return 0;
-void
-gtk_clist_select_row (GtkCList * clist,
- gint row,
- gint column)
-{
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ clist_row = ROW_ELEMENT (clist, row)->data;
- if (row < 0 || row >= clist->rows)
- return;
+ if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
+ return 0;
- if (column < -1 || column >= clist->columns)
- return;
+ if (pixmap)
+ {
+ *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
+ /* mask can be NULL */
+ *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
+ }
- select_row (clist, row, column, NULL);
+ return 1;
}
void
-gtk_clist_unselect_row (GtkCList * clist,
- gint row,
- gint column)
+gtk_clist_set_pixtext (GtkCList *clist,
+ gint row,
+ gint column,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask)
{
+ GtkCListRow *clist_row;
+
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
if (row < 0 || row >= clist->rows)
return;
-
- if (column < -1 || column >= clist->columns)
+ if (column < 0 || column >= clist->columns)
return;
- unselect_row (clist, row, column, NULL);
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ gdk_pixmap_ref (pixmap);
+ if (mask) gdk_pixmap_ref (mask);
+ GTK_CLIST_CLASS_FW (clist)->set_cell_contents
+ (clist, clist_row, column, GTK_CELL_PIXTEXT, text, spacing, pixmap, mask);
+
+ /* redraw the list if it's not frozen */
+ if (CLIST_UNFROZEN (clist))
+ {
+ if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+ }
}
-GtkVisibility
-gtk_clist_row_is_visible (GtkCList * clist,
- gint row)
+gint
+gtk_clist_get_pixtext (GtkCList *clist,
+ gint row,
+ gint column,
+ gchar **text,
+ guint8 *spacing,
+ GdkPixmap **pixmap,
+ GdkBitmap **mask)
{
- gint top;
+ GtkCListRow *clist_row;
g_return_val_if_fail (clist != NULL, 0);
g_return_val_if_fail (GTK_IS_CLIST (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 0;
+ if (column < 0 || column >= clist->columns)
+ return 0;
- return GTK_VISIBILITY_FULL;
-}
+ clist_row = ROW_ELEMENT (clist, row)->data;
-#if 0
-static GtkAdjustment*
-gtk_clist_get_vadjustment (GtkCList * clist)
-{
- g_return_val_if_fail (clist != NULL, NULL);
- g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
+ if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
+ return 0;
- return gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
-}
+ if (text)
+ *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
+ if (spacing)
+ *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
+ if (pixmap)
+ *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
-static GtkAdjustment*
-gtk_clist_get_hadjustment (GtkCList * clist)
-{
- g_return_val_if_fail (clist != NULL, NULL);
- g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
+ /* mask can be NULL */
+ *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
- return gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
+ return 1;
}
-#endif
void
-gtk_clist_set_policy (GtkCList * clist,
- GtkPolicyType vscrollbar_policy,
- GtkPolicyType hscrollbar_policy)
+gtk_clist_set_shift (GtkCList *clist,
+ gint row,
+ gint column,
+ gint vertical,
+ gint horizontal)
{
+ GtkRequisition requisition = { 0 };
+ GtkCListRow *clist_row;
+
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (clist->vscrollbar_policy != vscrollbar_policy)
- {
- clist->vscrollbar_policy = vscrollbar_policy;
+ if (row < 0 || row >= clist->rows)
+ return;
+ if (column < 0 || column >= clist->columns)
+ return;
- if (GTK_WIDGET (clist)->parent)
- gtk_widget_queue_resize (GTK_WIDGET (clist));
- }
+ clist_row = ROW_ELEMENT (clist, row)->data;
- if (clist->hscrollbar_policy != hscrollbar_policy)
- {
- clist->hscrollbar_policy = hscrollbar_policy;
+ if (clist->column[column].auto_resize &&
+ !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
+ GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
+ column, &requisition);
- if (GTK_WIDGET (clist)->parent)
- gtk_widget_queue_resize (GTK_WIDGET (clist));
- }
-}
+ clist_row->cell[column].vertical = vertical;
+ clist_row->cell[column].horizontal = horizontal;
-void
-gtk_clist_undo_selection (GtkCList *clist)
-{
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ column_auto_resize (clist, clist_row, column, requisition.width);
- if (clist->selection_mode == GTK_SELECTION_EXTENDED &&
- (clist->undo_selection || clist->undo_unselection))
- gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNDO_SELECTION]);
+ if (CLIST_UNFROZEN (clist) && gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
}
+/* PRIVATE CELL FUNCTIONS
+ * set_cell_contents
+ * cell_size_request
+ */
static void
-real_undo_selection (GtkCList *clist)
+set_cell_contents (GtkCList *clist,
+ GtkCListRow *clist_row,
+ gint column,
+ GtkCellType type,
+ const gchar *text,
+ guint8 spacing,
+ GdkPixmap *pixmap,
+ GdkBitmap *mask)
{
- GList *work;
+ GtkRequisition requisition;
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
+ g_return_if_fail (clist_row != NULL);
- if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
- clist->selection_mode != GTK_SELECTION_EXTENDED)
- return;
+ if (clist->column[column].auto_resize &&
+ !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
+ GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
+ column, &requisition);
- if (clist->anchor >= 0)
- GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
-
- if (!(clist->undo_selection || clist->undo_unselection))
+ switch (clist_row->cell[column].type)
{
- gtk_clist_unselect_all (clist);
- return;
+ case GTK_CELL_EMPTY:
+ break;
+ case GTK_CELL_TEXT:
+ g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
+ break;
+ case GTK_CELL_PIXMAP:
+ gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
+ if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
+ gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
+ break;
+ case GTK_CELL_PIXTEXT:
+ g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
+ gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
+ if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
+ gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
+ break;
+ case GTK_CELL_WIDGET:
+ /* unimplimented */
+ break;
+ default:
+ break;
}
- for (work = clist->undo_selection; work; work = work->next)
- gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
- GPOINTER_TO_INT (work->data), -1, NULL);
-
- for (work = clist->undo_unselection; work; work = work->next)
- gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
- GPOINTER_TO_INT (work->data), -1, NULL);
+ clist_row->cell[column].type = GTK_CELL_EMPTY;
- if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
+ switch (type)
{
- gtk_clist_draw_focus (GTK_WIDGET (clist));
- clist->focus_row = clist->undo_anchor;
- gtk_clist_draw_focus (GTK_WIDGET (clist));
+ case GTK_CELL_TEXT:
+ if (text)
+ {
+ clist_row->cell[column].type = GTK_CELL_TEXT;
+ GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
+ }
+ break;
+ case GTK_CELL_PIXMAP:
+ if (pixmap)
+ {
+ clist_row->cell[column].type = GTK_CELL_PIXMAP;
+ GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
+ /* We set the mask even if it is NULL */
+ GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
+ }
+ break;
+ case GTK_CELL_PIXTEXT:
+ if (text && pixmap)
+ {
+ clist_row->cell[column].type = GTK_CELL_PIXTEXT;
+ GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
+ GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
+ GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
+ GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
+ }
+ break;
+ default:
+ break;
}
- 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_clist_moveto (clist, clist->focus_row, -1, 1, 0);
- else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
- gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+ if (clist->column[column].auto_resize &&
+ !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
+ column_auto_resize (clist, clist_row, column, requisition.width);
}
-/*
- * GTKOBJECT
- * gtk_clist_destroy
- * gtk_clist_finalize
- */
static void
-gtk_clist_destroy (GtkObject * object)
+cell_size_request (GtkCList *clist,
+ GtkCListRow *clist_row,
+ gint column,
+ GtkRequisition *requisition)
{
- gint i;
- GtkCList *clist;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (GTK_IS_CLIST (object));
-
- clist = GTK_CLIST (object);
-
- /* freeze the list */
- GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
-
- /* get rid of all the rows */
- gtk_clist_clear (clist);
+ GtkStyle *style;
+ gint width;
+ gint height;
- /* 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.
- */
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
+ g_return_if_fail (requisition != NULL);
- /* destroy the scrollbars */
- if (clist->vscrollbar)
- {
- gtk_widget_unparent (clist->vscrollbar);
- clist->vscrollbar = NULL;
- }
- if (clist->hscrollbar)
- {
- gtk_widget_unparent (clist->hscrollbar);
- clist->hscrollbar = NULL;
- }
+ get_cell_style (clist, clist_row, GTK_STATE_NORMAL, column, &style,
+ NULL, NULL);
- if (clist->htimer)
- {
- gtk_timeout_remove (clist->htimer);
- clist->htimer = 0;
- }
- if (clist->vtimer)
+ switch (clist_row->cell[column].type)
{
- gtk_timeout_remove (clist->vtimer);
- clist->vtimer = 0;
+ case GTK_CELL_TEXT:
+ requisition->width =
+ gdk_string_width (style->font,
+ GTK_CELL_TEXT (clist_row->cell[column])->text);
+ requisition->height = style->font->ascent + style->font->descent;
+ break;
+ case GTK_CELL_PIXTEXT:
+ gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap,
+ &width, &height);
+ requisition->width = width +
+ GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing +
+ gdk_string_width (style->font,
+ GTK_CELL_TEXT (clist_row->cell[column])->text);
+
+ requisition->height = MAX (style->font->ascent + style->font->descent,
+ height);
+ break;
+ case GTK_CELL_PIXMAP:
+ gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap,
+ &width, &height);
+ requisition->width = width;
+ requisition->height = height;
+ break;
+ default:
+ requisition->width = 0;
+ requisition->height = 0;
+ break;
}
- /* 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);
+ requisition->width += clist_row->cell[column].horizontal;
+ requisition->height += clist_row->cell[column].vertical;
}
-static void
-gtk_clist_finalize (GtkObject * object)
+/* PUBLIC INSERT/REMOVE ROW FUNCTIONS
+ * gtk_clist_prepend
+ * gtk_clist_append
+ * gtk_clist_insert
+ * gtk_clist_remove
+ * gtk_clist_clear
+ */
+gint
+gtk_clist_prepend (GtkCList *clist,
+ gchar *text[])
{
- GtkCList *clist;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (GTK_IS_CLIST (object));
-
- clist = GTK_CLIST (object);
+ g_return_val_if_fail (clist != NULL, -1);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
+ g_return_val_if_fail (text != NULL, -1);
- columns_delete (clist);
+ return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, 0, text);
+}
- g_mem_chunk_destroy (clist->cell_mem_chunk);
- g_mem_chunk_destroy (clist->row_mem_chunk);
+gint
+gtk_clist_append (GtkCList *clist,
+ gchar *text[])
+{
+ g_return_val_if_fail (clist != NULL, -1);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
+ g_return_val_if_fail (text != NULL, -1);
- if (GTK_OBJECT_CLASS (parent_class)->finalize)
- (*GTK_OBJECT_CLASS (parent_class)->finalize) (object);
+ return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, clist->rows, text);
}
-/*
- * GTKWIDGET
- * gtk_clist_realize
- * gtk_clist_unrealize
- * gtk_clist_map
- * gtk_clist_unmap
- * gtk_clist_draw
- * gtk_clist_expose
- * gtk_clist_button_press
- * gtk_clist_button_release
- * gtk_clist_motion
- * gtk_clist_size_request
- * gtk_clist_size_allocate
- */
-static void
-gtk_clist_realize (GtkWidget * widget)
+gint
+gtk_clist_insert (GtkCList *clist,
+ gint row,
+ gchar *text[])
{
- gint i;
- GtkCList *clist;
- GdkWindowAttr attributes;
- gint attributes_mask;
- GdkGCValues values;
- gint border_width;
-
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_CLIST (widget));
+ g_return_val_if_fail (clist != NULL, -1);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
+ g_return_val_if_fail (text != NULL, -1);
- clist = GTK_CLIST (widget);
+ if (row < 0 || row > clist->rows)
+ row = clist->rows;
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, row, text);
+}
- add_style_data (clist);
+void
+gtk_clist_remove (GtkCList *clist,
+ gint row)
+{
+ GTK_CLIST_CLASS_FW (clist)->remove_row (clist, row);
+}
- border_width = GTK_CONTAINER (widget)->border_width;
+void
+gtk_clist_clear (GtkCList *clist)
+{
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- 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_PRESS_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_CLIST_CLASS_FW (clist)->clear (clist);
+}
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+/* PRIVATE INSERT/REMOVE ROW FUNCTIONS
+ * real_insert_row
+ * real_remove_row
+ * real_clear
+ * real_row_move
+ */
+static gint
+real_insert_row (GtkCList *clist,
+ gint row,
+ gchar *text[])
+{
+ gint i;
+ GtkCListRow *clist_row;
- /* column-title window */
+ g_return_val_if_fail (clist != NULL, -1);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
+ g_return_val_if_fail (text != NULL, -1);
- 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);
+ /* return if out of bounds */
+ if (row < 0 || row > clist->rows)
+ return -1;
- gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_SELECTED);
- gdk_window_show (clist->title_window);
+ /* create the row */
+ clist_row = row_new (clist);
- /* set things up so column buttons are drawn in title window */
+ /* set the text in the row's columns */
for (i = 0; i < clist->columns; i++)
- if (clist->column[i].button)
- gtk_widget_set_parent_window (clist->column[i].button, clist->title_window);
+ if (text[i])
+ GTK_CLIST_CLASS_FW (clist)->set_cell_contents
+ (clist, clist_row, i, GTK_CELL_TEXT, text[i], 0, NULL ,NULL);
- /* clist-window */
- attributes.x = clist->internal_allocation.x + widget->style->klass->xthickness;
- attributes.y = clist->internal_allocation.y + widget->style->klass->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);
+ if (!clist->rows)
+ {
+ clist->row_list = g_list_append (clist->row_list, clist_row);
+ clist->row_list_end = clist->row_list;
+ }
+ else
+ {
+ if (GTK_CLIST_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_CLIST_ROW (work)) > 0)
+ {
+ row++;
+ work = work->next;
+ }
+ }
+ else
+ {
+ while (row < clist->rows &&
+ clist->compare (clist, clist_row,
+ GTK_CLIST_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);
- gdk_window_set_background (clist->clist_window, &widget->style->bg[GTK_STATE_PRELIGHT]);
- gdk_window_show (clist->clist_window);
- gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
- &clist->clist_window_height);
+ }
+ clist->rows++;
- /* 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 |
- GDK_KEY_PRESS_MASK);
- attributes.cursor = clist->cursor_drag = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
- attributes_mask = GDK_WA_CURSOR;
-
- for (i = 0; i < clist->columns; i++)
+ 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->column[i].window = gdk_window_new (clist->title_window, &attributes, attributes_mask);
- gdk_window_set_user_data (clist->column[i].window, clist);
+ clist->focus_row = 0;
+ if (clist->selection_mode == GTK_SELECTION_BROWSE)
+ gtk_clist_select_row (clist, 0, -1);
}
- /* This is slightly less efficient than creating them with the
- * right size to begin with, but easier
- */
- size_allocate_title_buttons (clist);
+ /* redraw the list if it isn't frozen */
+ if (CLIST_UNFROZEN (clist))
+ {
+ adjust_adjustments (clist, FALSE);
- /* 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);
+ if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ draw_rows (clist, NULL);
+ }
- values.foreground = 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);
+ return row;
}
static void
-gtk_clist_unrealize (GtkWidget * widget)
+real_remove_row (GtkCList *clist,
+ gint row)
{
- gint i;
- GtkCList *clist;
-
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_CLIST (widget));
+ gint was_visible, was_selected;
+ GList *list;
+ GtkCListRow *clist_row;
- clist = GTK_CLIST (widget);
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
+ /* return if out of bounds */
+ if (row < 0 || row > (clist->rows - 1))
+ return;
- gdk_cursor_destroy (clist->cursor_drag);
- gdk_gc_destroy (clist->xor_gc);
- gdk_gc_destroy (clist->fg_gc);
- gdk_gc_destroy (clist->bg_gc);
+ was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
+ was_selected = 0;
- for (i = 0; i < clist->columns; i++)
- 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;
- }
+ /* get the row we're going to delete */
+ list = ROW_ELEMENT (clist, row);
+ g_assert (list != NULL);
+ clist_row = list->data;
- gdk_window_set_user_data (clist->clist_window, NULL);
- gdk_window_destroy (clist->clist_window);
- clist->clist_window = NULL;
+ /* 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)
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
+ row, -1, NULL);
- gdk_window_set_user_data (clist->title_window, NULL);
- gdk_window_destroy (clist->title_window);
- clist->title_window = NULL;
+ /* 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);
+ g_list_remove (list, clist_row);
- clist->cursor_drag = NULL;
- clist->xor_gc = NULL;
- clist->fg_gc = NULL;
- clist->bg_gc = NULL;
+ /*if (clist->focus_row >=0 &&
+ (row <= clist->focus_row || clist->focus_row >= clist->rows))
+ clist->focus_row--;*/
- if (GTK_WIDGET_CLASS (parent_class)->unrealize)
- (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
-}
+ if (row < ROW_FROM_YPIXEL (clist, 0))
+ clist->voffset += clist->row_height + CELL_SPACING;
-static void
-gtk_clist_map (GtkWidget * widget)
-{
- gint i;
- GtkCList *clist;
+ sync_selection (clist, row, SYNC_REMOVE);
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_CLIST (widget));
+ if (clist->selection_mode == GTK_SELECTION_BROWSE && !clist->selection &&
+ clist->focus_row >= 0)
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+ clist->focus_row, -1, NULL);
- clist = GTK_CLIST (widget);
+ /* toast the row */
+ row_delete (clist, clist_row);
- if (!GTK_WIDGET_MAPPED (widget))
+ /* redraw the row if it isn't frozen */
+ if (CLIST_UNFROZEN (clist))
{
- GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
-
- gdk_window_show (widget->window);
- gdk_window_show (clist->title_window);
- gdk_window_show (clist->clist_window);
-
- /* 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);
-
- /* map resize windows AFTER column buttons (above) */
- for (i = 0; i < clist->columns; i++)
- if (clist->column[i].window && clist->column[i].button)
- gdk_window_show (clist->column[i].window);
-
- /* map vscrollbars */
- if (GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
- !GTK_WIDGET_MAPPED (clist->vscrollbar))
- gtk_widget_map (clist->vscrollbar);
-
- if (GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
- !GTK_WIDGET_MAPPED (clist->hscrollbar))
- gtk_widget_map (clist->hscrollbar);
+ adjust_adjustments (clist, FALSE);
- /* unfreeze the list */
- GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
+ if (was_visible)
+ draw_rows (clist, NULL);
}
}
static void
-gtk_clist_unmap (GtkWidget * widget)
+real_clear (GtkCList *clist)
{
+ GList *list;
+ GList *free_list;
gint i;
- GtkCList *clist;
-
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_CLIST (widget));
-
- clist = GTK_CLIST (widget);
-
- if (GTK_WIDGET_MAPPED (widget))
- {
- GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
-
- 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 scrollbars */
- if (GTK_WIDGET_MAPPED (clist->vscrollbar))
- gtk_widget_unmap (clist->vscrollbar);
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- if (GTK_WIDGET_MAPPED (clist->hscrollbar))
- gtk_widget_unmap (clist->hscrollbar);
+ /* free up the selection list */
+ g_list_free (clist->selection);
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
- /* 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);
+ 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;
- /* freeze the list */
- GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
+ /* remove all the rows */
+ GTK_CLIST_SET_FLAG (clist, CLIST_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_CLIST_ROW (list));
+ g_list_free (free_list);
+ GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].auto_resize)
+ {
+ if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
+ gtk_clist_set_column_width
+ (clist, i, (clist->column[i].button->requisition.width -
+ (CELL_SPACING + (2 * COLUMN_INSET))));
+ else
+ gtk_clist_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
-gtk_clist_draw (GtkWidget * widget,
- GdkRectangle * area)
+real_row_move (GtkCList *clist,
+ gint source_row,
+ gint dest_row)
{
- GtkCList *clist;
- gint border_width;
- GdkRectangle child_area;
- int i;
+ GtkCListRow *clist_row;
+ GList *list;
+ gint first, last;
+ gint d;
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_CLIST (widget));
- g_return_if_fail (area != NULL);
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- if (GTK_WIDGET_DRAWABLE (widget))
- {
- clist = GTK_CLIST (widget);
- border_width = GTK_CONTAINER (widget)->border_width;
+ if (GTK_CLIST_AUTO_SORT(clist))
+ return;
- gdk_window_clear_area (widget->window,
- area->x - border_width,
- area->y - border_width,
- area->width, area->height);
+ if (source_row < 0 || source_row >= clist->rows ||
+ dest_row < 0 || dest_row >= clist->rows ||
+ source_row == dest_row)
+ return;
- /* draw list shadow/border */
- gtk_draw_shadow (widget->style, widget->window,
- GTK_STATE_NORMAL, clist->shadow_type,
- 0, 0,
- clist->clist_window_width + (2 * widget->style->klass->xthickness),
- clist->clist_window_height + (2 * widget->style->klass->ythickness) +
- clist->column_title_area.height);
+ gtk_clist_freeze (clist);
- gdk_window_clear_area (clist->clist_window,
- 0, 0, -1, -1);
+ /* 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--;
- draw_rows (clist, NULL);
+ /* 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++;
- for (i = 0; i < clist->columns; i++)
- {
- if (gtk_widget_intersect (clist->column[i].button, area, &child_area))
- gtk_widget_draw (clist->column[i].button, &child_area);
- }
+ /* sync selection */
+ if (source_row > dest_row)
+ {
+ first = dest_row;
+ last = source_row;
+ d = 1;
+ }
+ else
+ {
+ first = source_row;
+ last = dest_row;
+ d = -1;
}
-}
-static gint
-gtk_clist_expose (GtkWidget * widget,
- GdkEventExpose * event)
+ 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_clist_thaw (clist);
+}
+
+/* PUBLIC ROW FUNCTIONS
+ * gtk_clist_moveto
+ * gtk_clist_set_row_height
+ * gtk_clist_set_row_data
+ * gtk_clist_set_row_data_full
+ * gtk_clist_get_row_data
+ * gtk_clist_find_row_from_data
+ * gtk_clist_swap_rows
+ * gtk_clist_row_move
+ * gtk_clist_row_is_visible
+ * gtk_clist_set_foreground
+ * gtk_clist_set_background
+ */
+void
+gtk_clist_moveto (GtkCList *clist,
+ gint row,
+ gint column,
+ gfloat row_align,
+ gfloat col_align)
{
- GtkCList *clist;
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+ if (row < -1 || row >= clist->rows)
+ return;
+ if (column < -1 || column >= clist->columns)
+ return;
- if (GTK_WIDGET_DRAWABLE (widget))
- {
- clist = GTK_CLIST (widget);
+ row_align = CLAMP (row_align, 0, 1);
+ col_align = CLAMP (col_align, 0, 1);
- /* draw border */
- if (event->window == widget->window)
- gtk_draw_shadow (widget->style, widget->window,
- GTK_STATE_NORMAL, clist->shadow_type,
- 0, 0,
- clist->clist_window_width + (2 * widget->style->klass->xthickness),
- clist->clist_window_height + (2 * widget->style->klass->ythickness) +
- clist->column_title_area.height);
+ /* adjust horizontal scrollbar */
+ if (clist->hadjustment && column >= 0)
+ {
+ gint x;
- /* exposure events on the list */
- if (event->window == clist->clist_window)
- draw_rows (clist, &event->area);
+ 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);
}
- return FALSE;
+ /* adjust vertical scrollbar */
+ if (clist->vadjustment && row >= 0)
+ move_vertical (clist, row, row_align);
}
-static gint
-gtk_clist_button_press (GtkWidget * widget,
- GdkEventButton * event)
+void
+gtk_clist_set_row_height (GtkCList *clist,
+ guint height)
{
- gint i;
- GtkCList *clist;
- gint x;
- gint y;
- gint row;
- gint column;
+ GtkWidget *widget;
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- clist = GTK_CLIST (widget);
+ widget = GTK_WIDGET (clist);
- /* we don't handle button 2 and 3 */
- if (event->button != 1)
- return FALSE;
-
- /* selections on the list */
- if (event->window == clist->clist_window)
+ if (height > 0)
{
- x = event->x;
- y = event->y;
+ clist->row_height = height;
+ GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
+ }
+ else
+ {
+ GTK_CLIST_UNSET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
+ clist->row_height = 0;
+ }
- if (get_selection_info (clist, x, y, &row, &column))
+ if (GTK_WIDGET_REALIZED (clist))
+ {
+ if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
{
- gint old_row = clist->focus_row;
-
- if (clist->focus_row == -1)
- old_row = row;
-
- if (event->type == GDK_BUTTON_PRESS)
- {
- GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION);
- gdk_pointer_grab (clist->clist_window, FALSE,
- GDK_POINTER_MOTION_HINT_MASK |
- GDK_BUTTON1_MOTION_MASK |
- GDK_BUTTON_RELEASE_MASK,
- NULL, NULL, event->time);
- gtk_grab_add (widget);
- }
- else if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (widget))
- {
- GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
- gtk_grab_remove (widget);
- gdk_pointer_ungrab (event->time);
- }
-
- if (GTK_CLIST_ADD_MODE (clist))
- {
- GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
- if (GTK_WIDGET_HAS_FOCUS (widget))
- {
- gtk_clist_draw_focus (widget);
- gdk_gc_set_line_attributes (clist->xor_gc, 1,
- GDK_LINE_SOLID, 0, 0);
- clist->focus_row = row;
- gtk_clist_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_clist_draw_focus (widget);
- clist->focus_row = row;
- gtk_clist_draw_focus (widget);
- }
- else
- clist->focus_row = row;
- }
-
- if (!GTK_WIDGET_HAS_FOCUS (widget))
- gtk_widget_grab_focus (widget);
-
- switch (clist->selection_mode)
- {
- case GTK_SELECTION_SINGLE:
- case GTK_SELECTION_MULTIPLE:
- if (event->type != GDK_BUTTON_PRESS)
- select_row (clist, row, column, (GdkEvent *) event);
- else
- clist->anchor = row;
- break;
-
- case GTK_SELECTION_BROWSE:
- select_row (clist, row, column, (GdkEvent *) event);
- break;
-
- case GTK_SELECTION_EXTENDED:
- if (event->type != GDK_BUTTON_PRESS)
- {
- if (clist->anchor != -1)
- {
- update_extended_selection (clist, clist->focus_row);
- GTK_CLIST_CLASS_FW (clist)->resync_selection
- (clist, (GdkEvent *) event);
- }
- select_row (clist, row, column, (GdkEvent *) 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;
- }
+ clist->row_height = (widget->style->font->ascent +
+ widget->style->font->descent + 1);
+ clist->row_center_offset = widget->style->font->ascent + 1.5;
}
-
- return FALSE;
+ else
+ clist->row_center_offset = 1.5 + (clist->row_height +
+ widget->style->font->ascent -
+ widget->style->font->descent - 1) / 2;
}
+
+ CLIST_REFRESH (clist);
+}
- /* press on resize windows */
- for (i = 0; i < clist->columns; i++)
- if (clist->column[i].window && event->window == clist->column[i].window)
- {
- 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);
- gtk_grab_add (widget);
- GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
+void
+gtk_clist_set_row_data (GtkCList *clist,
+ gint row,
+ gpointer data)
+{
+ gtk_clist_set_row_data_full (clist, row, data, NULL);
+}
- if (!GTK_WIDGET_HAS_FOCUS (widget))
- gtk_widget_grab_focus (widget);
+void
+gtk_clist_set_row_data_full (GtkCList *clist,
+ gint row,
+ gpointer data,
+ GtkDestroyNotify destroy)
+{
+ GtkCListRow *clist_row;
- clist->drag_pos = i;
- clist->x_drag = (COLUMN_LEFT_XPIXEL(clist, i) + COLUMN_INSET +
- clist->column[i].area.width + CELL_SPACING);
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- if (GTK_CLIST_ADD_MODE (clist))
- gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
- draw_xor_line (clist);
+ if (row < 0 || row > (clist->rows - 1))
+ return;
- return FALSE;
- }
+ clist_row = ROW_ELEMENT (clist, row)->data;
- return FALSE;
+ if (clist_row->destroy)
+ clist_row->destroy (clist_row->data);
+
+ clist_row->data = data;
+ clist_row->destroy = destroy;
}
-static gint
-gtk_clist_button_release (GtkWidget * widget,
- GdkEventButton * event)
+gpointer
+gtk_clist_get_row_data (GtkCList *clist,
+ gint row)
{
- GtkCList *clist;
-
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+ GtkCListRow *clist_row;
- clist = GTK_CLIST (widget);
+ g_return_val_if_fail (clist != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
- /* we don't handle button 2 and 3 */
- if (event->button != 1)
- return FALSE;
+ if (row < 0 || row > (clist->rows - 1))
+ return NULL;
- /* release on resize windows */
- if (GTK_CLIST_IN_DRAG (clist))
- {
- gint i, x, width, visible;
+ clist_row = ROW_ELEMENT (clist, row)->data;
+ return clist_row->data;
+}
- i = clist->drag_pos;
- clist->drag_pos = -1;
- GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
- gtk_widget_get_pointer (widget, &x, NULL);
+gint
+gtk_clist_find_row_from_data (GtkCList *clist,
+ gpointer data)
+{
+ GList *list;
+ gint n;
- width = new_column_width (clist, i, &x, &visible);
- gtk_grab_remove (widget);
- gdk_pointer_ungrab (event->time);
+ g_return_val_if_fail (clist != NULL, -1);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
- if (visible)
- draw_xor_line (clist);
+ for (n = 0, list = clist->row_list; list; n++, list = list->next)
+ if (GTK_CLIST_ROW (list)->data == data)
+ return n;
- if (GTK_CLIST_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);
- }
+ return -1;
+}
- resize_column (clist, i, width);
- return FALSE;
- }
+void
+gtk_clist_swap_rows (GtkCList *clist,
+ gint row1,
+ gint row2)
+{
+ gint first, last;
- if (GTK_CLIST_DRAG_SELECTION (clist))
- {
- gint row;
- gint column;
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
+ g_return_if_fail (row1 != row2);
- GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
- gtk_grab_remove (widget);
- gdk_pointer_ungrab (event->time);
- if (clist->htimer)
- {
- gtk_timeout_remove (clist->htimer);
- clist->htimer = 0;
- }
- if (clist->vtimer)
- {
- gtk_timeout_remove (clist->vtimer);
- clist->vtimer = 0;
- }
- switch (clist->selection_mode)
- {
- case GTK_SELECTION_EXTENDED:
- if (!(event->state & GDK_SHIFT_MASK) ||
- event->x < 0 || event->x >= clist->clist_window_width ||
- event->y < 0 || event->y >= clist->clist_window_height)
- GTK_CLIST_CLASS_FW (clist)->resync_selection
- (clist, (GdkEvent *) event);
- break;
+ if (GTK_CLIST_AUTO_SORT(clist))
+ return;
- case GTK_SELECTION_SINGLE:
- case GTK_SELECTION_MULTIPLE:
- if (get_selection_info (clist, event->x, event->y, &row, &column))
- {
- if (clist->anchor == clist->focus_row)
- toggle_row (clist, row, column, (GdkEvent *) event);
- }
- clist->anchor = -1;
- break;
+ gtk_clist_freeze (clist);
- default:
- break;
- }
- }
+ first = MIN (row1, row2);
+ last = MAX (row1, row2);
- return FALSE;
+ gtk_clist_row_move (clist, last, first);
+ gtk_clist_row_move (clist, first + 1, last);
+
+ gtk_clist_thaw (clist);
}
-static gint
-horizontal_timeout (GtkCList *clist)
+void
+gtk_clist_row_move (GtkCList *clist,
+ gint source_row,
+ gint dest_row)
{
- gint x, y;
- GdkEventMotion event;
- GdkModifierType mask;
-
- g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- clist->htimer = 0;
- gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
+ if (GTK_CLIST_AUTO_SORT(clist))
+ return;
- event.is_hint = 0;
- event.x = x;
- event.y = y;
- event.state = mask;
+ if (source_row < 0 || source_row >= clist->rows ||
+ dest_row < 0 || dest_row >= clist->rows ||
+ source_row == dest_row)
+ return;
- gtk_clist_motion (GTK_WIDGET (clist), &event);
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[ROW_MOVE],
+ source_row, dest_row);
+}
- return FALSE;
-}
-
-static gint
-vertical_timeout (GtkCList *clist)
+GtkVisibility
+gtk_clist_row_is_visible (GtkCList *clist,
+ gint row)
{
- gint x, y;
- GdkEventMotion event;
- GdkModifierType mask;
-
- g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
+ gint top;
- clist->vtimer = 0;
- gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
+ g_return_val_if_fail (clist != NULL, 0);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
- event.is_hint = 0;
- event.x = x;
- event.y = y;
- event.state = mask;
+ if (row < 0 || row >= clist->rows)
+ return GTK_VISIBILITY_NONE;
- gtk_clist_motion (GTK_WIDGET (clist), &event);
+ if (clist->row_height == 0)
+ return GTK_VISIBILITY_NONE;
- return FALSE;
-}
+ if (row < ROW_FROM_YPIXEL (clist, 0))
+ return GTK_VISIBILITY_NONE;
-static void
-move_vertical (GtkCList *clist,
- gint row,
- gfloat align)
-{
- gint y;
- GtkAdjustment *adj;
+ if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
+ return GTK_VISIBILITY_NONE;
- adj = GTK_RANGE (clist->vscrollbar)->adjustment;
+ top = ROW_TOP_YPIXEL (clist, row);
- y = ROW_TOP_YPIXEL (clist, row) - clist->voffset;
-
- y = y - align * (clist->clist_window_height - clist->row_height)
- + (2 * align - 1) * CELL_SPACING;
-
- if (y + adj->page_size > adj->upper)
- adj->value = adj->upper - adj->page_size;
- else
- adj->value = y;
+ if ((top < 0)
+ || ((top + clist->row_height) >= clist->clist_window_height))
+ return GTK_VISIBILITY_PARTIAL;
- gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
+ return GTK_VISIBILITY_FULL;
}
-static void
-move_horizontal (GtkCList *clist,
- gint diff)
+void
+gtk_clist_set_foreground (GtkCList *clist,
+ gint row,
+ GdkColor *color)
{
- gfloat upper;
- GtkAdjustment *adj;
+ GtkCListRow *clist_row;
- adj = GTK_RANGE (clist->hscrollbar)->adjustment;
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
+
+ if (row < 0 || row >= clist->rows)
+ return;
- adj->value += diff;
+ clist_row = ROW_ELEMENT (clist, row)->data;
- upper = adj->upper - adj->page_size;
- adj->value = MIN (adj->value, upper);
- adj->value = MAX (adj->value, 0.0);
+ if (color)
+ {
+ clist_row->foreground = *color;
+ clist_row->fg_set = TRUE;
+ if (GTK_WIDGET_REALIZED (clist))
+ gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
+ &clist_row->foreground);
+ }
+ else
+ clist_row->fg_set = FALSE;
- gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
+ if (CLIST_UNFROZEN (clist) && gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
}
-static gint
-gtk_clist_motion (GtkWidget * widget,
- GdkEventMotion * event)
+void
+gtk_clist_set_background (GtkCList *clist,
+ gint row,
+ GdkColor *color)
{
- GtkCList *clist;
- gint x, y, visible;
- gint row;
- gint new_width;
- static gint cc =0;
+ GtkCListRow *clist_row;
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- clist = GTK_CLIST (widget);
- cc++;
- if (!(gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)))
- return FALSE;
+ if (row < 0 || row >= clist->rows)
+ return;
- if (GTK_CLIST_IN_DRAG (clist))
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ if (color)
{
- if (event->is_hint || event->window != widget->window)
- gtk_widget_get_pointer (widget, &x, NULL);
- else
- x = event->x;
+ clist_row->background = *color;
+ clist_row->bg_set = TRUE;
+ if (GTK_WIDGET_REALIZED (clist))
+ gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
+ &clist_row->background);
+ }
+ else
+ clist_row->bg_set = FALSE;
- new_width = new_column_width (clist, clist->drag_pos, &x, &visible);
- /* Welcome to my hack! I'm going to use a value of x_drag = -99999
- * to indicate that the xor line is already invisible */
-
- if (!visible && clist->x_drag != -99999)
- {
- draw_xor_line (clist);
- clist->x_drag = -99999;
- }
+ if (CLIST_UNFROZEN (clist)
+ && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+ GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+}
- if (x != clist->x_drag && visible)
- {
- if (clist->x_drag != -99999)
- draw_xor_line (clist);
+/* PUBLIC ROW/CELL STYLE FUNCTIONS
+ * gtk_clist_set_cell_style
+ * gtk_clist_get_cell_style
+ * gtk_clist_set_row_style
+ * gtk_clist_get_row_style
+ */
+void
+gtk_clist_set_cell_style (GtkCList *clist,
+ gint row,
+ gint column,
+ GtkStyle *style)
+{
+ GtkRequisition requisition = { 0 };
+ GtkCListRow *clist_row;
- clist->x_drag = x;
- draw_xor_line (clist);
- }
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- if (new_width <= COLUMN_MIN_WIDTH + 1)
- {
- if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) && x < 0)
- gtk_clist_moveto (clist, -1, clist->drag_pos, 0, 0);
- return FALSE;
- }
- }
+ if (row < 0 || row >= clist->rows)
+ return;
+ if (column < 0 || column >= clist->columns)
+ return;
-
- if (event->is_hint || event->window != clist->clist_window)
- gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
+ clist_row = ROW_ELEMENT (clist, row)->data;
- /* horizontal autoscrolling */
- if (LIST_WIDTH (clist) > clist->clist_window_width &&
- (x < 0 || x >= clist->clist_window_width))
- {
- if (clist->htimer)
- return FALSE;
+ if (clist_row->cell[column].style == style)
+ return;
- clist->htimer = gtk_timeout_add
- (SCROLL_TIME, (GtkFunction) horizontal_timeout, clist);
+ if (clist->column[column].auto_resize &&
+ !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
+ GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
+ column, &requisition);
- if (!((x < 0 && GTK_RANGE (clist->hscrollbar)->adjustment->value == 0) ||
- (x >= clist->clist_window_width &&
- GTK_RANGE (clist->hscrollbar)->adjustment->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 (clist_row->cell[column].style)
+ {
+ if (GTK_WIDGET_REALIZED (clist))
+ gtk_style_detach (clist_row->cell[column].style);
+ gtk_style_unref (clist_row->cell[column].style);
}
- if (GTK_CLIST_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;
+ clist_row->cell[column].style = style;
- if (LIST_HEIGHT (clist) > clist->clist_window_height &&
- (y < 0 || y >= clist->clist_window_height))
+ if (clist_row->cell[column].style)
{
- if (clist->vtimer)
- return FALSE;
+ gtk_style_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);
+ }
- clist->vtimer = gtk_timeout_add (SCROLL_TIME,
- (GtkFunction) vertical_timeout, clist);
+ column_auto_resize (clist, clist_row, column, requisition.width);
- if (GTK_CLIST_DRAG_SELECTION (clist))
- {
- if ((y < 0 && clist->focus_row == 0) ||
- (y >= clist->clist_window_height &&
- clist->focus_row == clist->rows-1))
- return FALSE;
- }
+ /* redraw the list if it's not frozen */
+ if (CLIST_UNFROZEN (clist))
+ {
+ if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
}
+}
- row = CLAMP (row, 0, clist->rows - 1);
+GtkStyle *
+gtk_clist_get_cell_style (GtkCList *clist,
+ gint row,
+ gint column)
+{
+ GtkCListRow *clist_row;
- if (GTK_CLIST_DRAG_SELECTION (clist))
- {
- if (row == clist->focus_row)
- return FALSE;
+ g_return_val_if_fail (clist != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
- gtk_clist_draw_focus (widget);
- clist->focus_row = row;
- gtk_clist_draw_focus (widget);
+ if (row < 0 || row >= clist->rows || column < 0 || column >= clist->columns)
+ return NULL;
- switch (clist->selection_mode)
- {
- case GTK_SELECTION_BROWSE:
- select_row (clist, clist->focus_row, - 1, (GdkEvent *) event);
- break;
-
- case GTK_SELECTION_EXTENDED:
- 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);
+ clist_row = ROW_ELEMENT (clist, row)->data;
- return FALSE;
+ return clist_row->cell[column].style;
}
-static void
-gtk_clist_size_request (GtkWidget * widget,
- GtkRequisition * requisition)
+void
+gtk_clist_set_row_style (GtkCList *clist,
+ gint row,
+ GtkStyle *style)
{
+ GtkRequisition requisition;
+ GtkCListRow *clist_row;
+ gint *old_width;
gint i;
- GtkCList *clist;
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_CLIST (widget));
- g_return_if_fail (requisition != NULL);
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- clist = GTK_CLIST (widget);
+ if (row < 0 || row >= clist->rows)
+ return;
- add_style_data (clist);
+ clist_row = ROW_ELEMENT (clist, row)->data;
- requisition->width = 0;
- requisition->height = 0;
+ if (clist_row->style == style)
+ return;
- /* compute the size of the column title (title) area */
- clist->column_title_area.height = 0;
- if (GTK_CLIST_SHOW_TITLES (clist))
- for (i = 0; i < clist->columns; i++)
- if (clist->column[i].button)
- {
- gtk_widget_size_request (clist->column[i].button, &clist->column[i].button->requisition);
- clist->column_title_area.height = MAX (clist->column_title_area.height,
- clist->column[i].button->requisition.height);
- }
- requisition->height += clist->column_title_area.height;
+ old_width = g_new (gint, clist->columns);
- /* add the vscrollbar space */
- if ((clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
- GTK_WIDGET_VISIBLE (clist->vscrollbar))
+ if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
{
- gtk_widget_size_request (clist->vscrollbar, &clist->vscrollbar->requisition);
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].auto_resize)
+ {
+ GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
+ i, &requisition);
+ old_width[i] = requisition.width;
+ }
+ }
- requisition->width += clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist);
- requisition->height = MAX (requisition->height,
- clist->vscrollbar->requisition.height);
+ if (clist_row->style)
+ {
+ if (GTK_WIDGET_REALIZED (clist))
+ gtk_style_detach (clist_row->style);
+ gtk_style_unref (clist_row->style);
}
- /* add the hscrollbar space */
- if ((clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
- GTK_WIDGET_VISIBLE (clist->hscrollbar))
+ clist_row->style = style;
+
+ if (clist_row->style)
{
- gtk_widget_size_request (clist->hscrollbar, &clist->hscrollbar->requisition);
+ gtk_style_ref (clist_row->style);
+
+ if (GTK_WIDGET_REALIZED (clist))
+ clist_row->style = gtk_style_attach (clist_row->style,
+ clist->clist_window);
+ }
- requisition->height += clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist);
- requisition->width = MAX (clist->hscrollbar->requisition.width,
- requisition->width -
- clist->vscrollbar->requisition.width);
+ if (GTK_CLIST_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_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
}
+}
+
+GtkStyle *
+gtk_clist_get_row_style (GtkCList *clist,
+ gint row)
+{
+ GtkCListRow *clist_row;
+
+ g_return_val_if_fail (clist != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
+
+ if (row < 0 || row >= clist->rows)
+ return NULL;
- requisition->width += widget->style->klass->xthickness * 2 +
- GTK_CONTAINER (widget)->border_width * 2;
- requisition->height += widget->style->klass->ythickness * 2 +
- GTK_CONTAINER (widget)->border_width * 2;
+ clist_row = ROW_ELEMENT (clist, row)->data;
+
+ return clist_row->style;
}
-static void
-gtk_clist_size_allocate (GtkWidget * widget,
- GtkAllocation * allocation)
+/* PUBLIC SELECTION FUNCTIONS
+ * gtk_clist_set_selectable
+ * gtk_clist_get_selectable
+ * gtk_clist_select_row
+ * gtk_clist_unselect_row
+ * gtk_clist_select_all
+ * gtk_clist_unselect_all
+ * gtk_clist_undo_selection
+ */
+void
+gtk_clist_set_selectable (GtkCList *clist,
+ gint row,
+ gboolean selectable)
{
- GtkCList *clist;
- GtkAllocation clist_allocation;
- GtkAllocation child_allocation;
- gint i, vscrollbar_vis, hscrollbar_vis;
+ GtkCListRow *clist_row;
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_CLIST (widget));
- g_return_if_fail (allocation != NULL);
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- clist = GTK_CLIST (widget);
- widget->allocation = *allocation;
+ if (row < 0 || row >= clist->rows)
+ return;
- if (GTK_WIDGET_REALIZED (widget))
- {
- gdk_window_move_resize (widget->window,
- allocation->x + GTK_CONTAINER (widget)->border_width,
- allocation->y + GTK_CONTAINER (widget)->border_width,
- allocation->width - GTK_CONTAINER (widget)->border_width * 2,
- allocation->height - GTK_CONTAINER (widget)->border_width * 2);
- }
+ clist_row = ROW_ELEMENT (clist, row)->data;
- /* 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, allocation->width -
- GTK_CONTAINER (widget)->border_width * 2);
- clist->internal_allocation.height = MAX (1, allocation->height -
- GTK_CONTAINER (widget)->border_width * 2);
-
- /* allocate clist window assuming no scrollbars */
- clist_allocation.x = clist->internal_allocation.x + widget->style->klass->xthickness;
- clist_allocation.y = clist->internal_allocation.y + widget->style->klass->ythickness +
- clist->column_title_area.height;
- clist_allocation.width = MAX (1, clist->internal_allocation.width -
- (2 * widget->style->klass->xthickness));
- clist_allocation.height = MAX (1, clist->internal_allocation.height -
- (2 * widget->style->klass->ythickness) -
- clist->column_title_area.height);
-
- /*
- * here's where we decide to show/not show the scrollbars
- */
- vscrollbar_vis = 0;
- hscrollbar_vis = 0;
-
- for (i = 0; i <= 1; i++)
- {
- if (LIST_HEIGHT (clist) <= clist_allocation.height &&
- clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
- {
- vscrollbar_vis = 0;
- }
- else
- {
- if (!vscrollbar_vis)
- {
- vscrollbar_vis = 1;
- clist_allocation.width = MAX (1, clist_allocation.width -
- (clist->vscrollbar->requisition.width +
- SCROLLBAR_SPACING (clist)));
- }
- }
-
- if (LIST_WIDTH (clist) <= clist_allocation.width &&
- clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
- {
- hscrollbar_vis = 0;
- }
- else
- {
- if (!hscrollbar_vis)
- {
- hscrollbar_vis = 1;
- clist_allocation.height = MAX (1, clist_allocation.height -
- (clist->hscrollbar->requisition.height +
- SCROLLBAR_SPACING (clist)));
- }
- }
- }
-
- 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->klass->xthickness;
- clist->column_title_area.y = widget->style->klass->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);
- size_allocate_title_buttons (clist);
+ if (selectable == clist_row->selectable)
+ return;
- adjust_scrollbars (clist);
-
- /* allocate the vscrollbar */
- if (vscrollbar_vis)
- {
- if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
- gtk_widget_show (clist->vscrollbar);
-
- child_allocation.x = clist->internal_allocation.x +
- clist->internal_allocation.width -
- clist->vscrollbar->requisition.width;
- child_allocation.y = clist->internal_allocation.y;
- child_allocation.width = clist->vscrollbar->requisition.width;
- child_allocation.height = MAX (1, clist->internal_allocation.height -
- (hscrollbar_vis ? (clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist)) : 0));
-
- gtk_widget_size_allocate (clist->vscrollbar, &child_allocation);
- }
- else
- {
- if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
- gtk_widget_hide (clist->vscrollbar);
- }
-
- if (hscrollbar_vis)
- {
- if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
- gtk_widget_show (clist->hscrollbar);
-
- child_allocation.x = clist->internal_allocation.x;
- child_allocation.y = clist->internal_allocation.y +
- clist->internal_allocation.height -
- clist->hscrollbar->requisition.height;
- child_allocation.width = MAX (1, clist->internal_allocation.width -
- (vscrollbar_vis ? (clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist)) : 0));
- child_allocation.height = clist->hscrollbar->requisition.height;
-
- gtk_widget_size_allocate (clist->hscrollbar, &child_allocation);
- }
- else
- {
- if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
- gtk_widget_hide (clist->hscrollbar);
- }
+ clist_row->selectable = selectable;
- /* set the vscrollbar adjustments */
- adjust_scrollbars (clist);
+ if (!selectable && clist_row->state == GTK_STATE_SELECTED)
+ {
+ if (clist->anchor >= 0 &&
+ clist->selection_mode == GTK_SELECTION_EXTENDED)
+ {
+ clist->drag_button = 0;
+ remove_grab (clist);
+ GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+ }
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
+ row, -1, NULL);
+ }
}
-/*
- * GTKCONTAINER
- * gtk_clist_forall
- */
-static void
-gtk_clist_forall (GtkContainer *container,
- gboolean include_internals,
- GtkCallback callback,
- gpointer callback_data)
+gboolean
+gtk_clist_get_selectable (GtkCList *clist,
+ gint row)
{
- GtkCList *clist;
+ g_return_val_if_fail (clist != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
- g_return_if_fail (container != NULL);
- g_return_if_fail (GTK_IS_CLIST (container));
- g_return_if_fail (callback != NULL);
+ if (row < 0 || row >= clist->rows)
+ return FALSE;
- clist = GTK_CLIST (container);
-
- if (include_internals)
- {
- guint i;
-
- /* callback for the column buttons */
- for (i = 0; i < clist->columns; i++)
- if (clist->column[i].button)
- (*callback) (clist->column[i].button, callback_data);
-
- /* callbacks for the scrollbars */
- if (clist->vscrollbar)
- (*callback) (clist->vscrollbar, callback_data);
- if (clist->hscrollbar)
- (*callback) (clist->hscrollbar, callback_data);
- }
+ return GTK_CLIST_ROW (ROW_ELEMENT (clist, row))->selectable;
}
-/*
- * DRAWING
- * draw_row
- * draw_rows
- */
-static void
-draw_row (GtkCList * clist,
- GdkRectangle * area,
- gint row,
- GtkCListRow * clist_row)
+void
+gtk_clist_select_row (GtkCList *clist,
+ gint row,
+ gint column)
{
- GtkWidget *widget;
- GdkGC *fg_gc, *bg_gc;
- GdkRectangle row_rectangle, cell_rectangle, clip_rectangle, intersect_rectangle,
- *rect;
- gint i, offset = 0, width, height, pixmap_width = 0;
- gint xsrc, ysrc, xdest, ydest;
-
g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- /* bail now if we arn't drawable yet */
- if (!GTK_WIDGET_DRAWABLE (clist))
+ if (row < 0 || row >= clist->rows)
+ return;
+ if (column < -1 || column >= clist->columns)
return;
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+ row, column, NULL);
+}
+
+void
+gtk_clist_unselect_row (GtkCList *clist,
+ gint row,
+ gint column)
+{
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
+
if (row < 0 || row >= clist->rows)
return;
+ if (column < -1 || column >= clist->columns)
+ 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 = (g_list_nth (clist->row_list, row))->data;
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
+ row, column, NULL);
+}
- /* 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;
+void
+gtk_clist_select_all (GtkCList *clist)
+{
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- /* 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;
+ GTK_CLIST_CLASS_FW (clist)->select_all (clist);
+}
- /* rectangle used to clip drawing operations, it's 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;
+void
+gtk_clist_unselect_all (GtkCList *clist)
+{
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- /* select GC for background rectangle */
- if (clist_row->state == GTK_STATE_SELECTED)
- {
- fg_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
- bg_gc = widget->style->bg_gc[GTK_STATE_SELECTED];
- }
- else
- {
- if (clist_row->fg_set)
- {
- gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
- fg_gc = clist->fg_gc;
- }
- else
- fg_gc = widget->style->fg_gc[GTK_STATE_NORMAL];
-
- if (clist_row->bg_set)
- {
- gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
- bg_gc = clist->bg_gc;
- }
- else
- bg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
- }
+ GTK_CLIST_CLASS_FW (clist)->unselect_all (clist);
+}
- /* draw the cell borders and background */
- if (area)
- {
- if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
- gdk_draw_rectangle (clist->clist_window,
- widget->style->base_gc[GTK_STATE_NORMAL],
- TRUE,
- intersect_rectangle.x,
- intersect_rectangle.y,
- intersect_rectangle.width,
- intersect_rectangle.height);
+void
+gtk_clist_undo_selection (GtkCList *clist)
+{
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- /* the last row has to clear it's bottom cell spacing too */
- if (clist_row == clist->row_list_end->data)
- {
- cell_rectangle.y += clist->row_height + CELL_SPACING;
+ if (clist->selection_mode == GTK_SELECTION_EXTENDED &&
+ (clist->undo_selection || clist->undo_unselection))
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNDO_SELECTION]);
+}
- 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);
- }
+/* 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 (GtkCList *clist,
+ gint row_number,
+ GList *row_list_element)
+{
+ return g_list_find (clist->selection, GINT_TO_POINTER (row_number));
+}
- if (!gdk_rectangle_intersect (area, &row_rectangle, &intersect_rectangle))
- return;
+static void
+toggle_row (GtkCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event)
+{
+ GtkCListRow *clist_row;
- if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
- gdk_draw_rectangle (clist->clist_window,
- bg_gc,
- TRUE,
- intersect_rectangle.x,
- intersect_rectangle.y,
- intersect_rectangle.width,
- intersect_rectangle.height);
- else
- gdk_window_clear_area (clist->clist_window,
- intersect_rectangle.x,
- intersect_rectangle.y,
- intersect_rectangle.width,
- intersect_rectangle.height);
- }
- else
+ switch (clist->selection_mode)
{
- 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);
+ case GTK_SELECTION_EXTENDED:
+ case GTK_SELECTION_MULTIPLE:
+ case GTK_SELECTION_SINGLE:
+ clist_row = ROW_ELEMENT (clist, row)->data;
- /* the last row has to clear it's bottom cell spacing too */
- if (clist_row == clist->row_list_end->data)
+ if (!clist_row)
+ return;
+
+ if (clist_row->state == GTK_STATE_SELECTED)
{
- cell_rectangle.y += clist->row_height + CELL_SPACING;
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
+ row, column, event);
+ return;
+ }
+ case GTK_SELECTION_BROWSE:
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+ row, column, event);
+ break;
+ }
+}
- 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);
- }
+static void
+fake_toggle_row (GtkCList *clist,
+ gint row)
+{
+ GList *work;
- if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
- gdk_draw_rectangle (clist->clist_window,
- bg_gc,
- TRUE,
- row_rectangle.x,
- row_rectangle.y,
- row_rectangle.width,
- row_rectangle.height);
- else
- gdk_window_clear_area (clist->clist_window,
- row_rectangle.x,
- row_rectangle.y,
- row_rectangle.width,
- row_rectangle.height);
- }
+ work = ROW_ELEMENT (clist, row);
- /* iterate and draw all the columns (row cells) and draw their contents */
- for (i = 0; i < clist->columns; i++)
- {
- clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
- clip_rectangle.width = clist->column[i].area.width;
+ if (!work || !GTK_CLIST_ROW (work)->selectable)
+ return;
+
+ if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
+ clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
+ else
+ clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
+
+ if (CLIST_UNFROZEN (clist) &&
+ gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
+ GTK_CLIST_ROW (work));
+}
- /* calculate clipping region clipping region */
- if (!area)
- {
- rect = &clip_rectangle;
- }
- else
- {
- if (!gdk_rectangle_intersect (area, &clip_rectangle,
- &intersect_rectangle))
- continue;
- rect = &intersect_rectangle;
- }
+static void
+toggle_focus_row (GtkCList *clist)
+{
+ g_return_if_fail (clist != 0);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- /* calculate real width for column justification */
- switch (clist_row->cell[i].type)
- {
- case GTK_CELL_EMPTY:
- continue;
- break;
+ if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
+ clist->focus_row < 0 || clist->focus_row >= clist->rows)
+ return;
- case GTK_CELL_TEXT:
- width = gdk_string_width (GTK_WIDGET (clist)->style->font,
- GTK_CELL_TEXT (clist_row->cell[i])->text);
- break;
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_SINGLE:
+ case GTK_SELECTION_MULTIPLE:
+ toggle_row (clist, clist->focus_row, 0, NULL);
+ break;
+ case GTK_SELECTION_EXTENDED:
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
- case GTK_CELL_PIXMAP:
- gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &width, &height);
- pixmap_width = width;
- break;
+ clist->anchor = clist->focus_row;
+ clist->drag_pos = clist->focus_row;
+ clist->undo_anchor = clist->focus_row;
+
+ if (GTK_CLIST_ADD_MODE(clist))
+ fake_toggle_row (clist, clist->focus_row);
+ else
+ GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist,clist->focus_row);
- case GTK_CELL_PIXTEXT:
- gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap, &width, &height);
- pixmap_width = width;
- width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
- width = gdk_string_width (GTK_WIDGET (clist)->style->font,
- GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
- break;
+ GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+ break;
+ default:
+ break;
+ }
+}
- case GTK_CELL_WIDGET:
- /* unimplimented */
- continue;
- break;
+static void
+toggle_add_mode (GtkCList *clist)
+{
+ g_return_if_fail (clist != 0);
+ g_return_if_fail (GTK_IS_CLIST (clist));
+
+ if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
+ clist->selection_mode != GTK_SELECTION_EXTENDED)
+ return;
- default:
- continue;
- break;
- }
+ gtk_clist_draw_focus (GTK_WIDGET (clist));
+ if (!GTK_CLIST_ADD_MODE(clist))
+ {
+ GTK_CLIST_SET_FLAG (clist, CLIST_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_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
+ gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
+ clist->anchor_state = GTK_STATE_SELECTED;
+ }
+ gtk_clist_draw_focus (GTK_WIDGET (clist));
+}
- switch (clist->column[i].justification)
- {
- case GTK_JUSTIFY_LEFT:
- offset = clip_rectangle.x;
- break;
+static void
+real_select_row (GtkCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event)
+{
+ GtkCListRow *clist_row;
+ GList *list;
+ gint sel_row;
+ gboolean row_selected;
- case GTK_JUSTIFY_RIGHT:
- offset = (clip_rectangle.x + clip_rectangle.width) - width;
- break;
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- case GTK_JUSTIFY_CENTER:
- offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
- break;
+ if (row < 0 || row > (clist->rows - 1))
+ return;
- case GTK_JUSTIFY_FILL:
- offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
- break;
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_SINGLE:
+ case GTK_SELECTION_BROWSE:
- default:
- offset = 0;
- break;
- };
+ row_selected = FALSE;
+ list = clist->selection;
- /* Draw Text or Pixmap */
- switch (clist_row->cell[i].type)
+ while (list)
{
- case GTK_CELL_EMPTY:
- continue;
- break;
-
- case GTK_CELL_TEXT:
- gdk_gc_set_clip_rectangle (fg_gc, rect);
-
- gdk_draw_string (clist->clist_window,
- widget->style->font,
- fg_gc,
- offset + clist_row->cell[i].horizontal,
- row_rectangle.y + clist->row_center_offset +
- clist_row->cell[i].vertical,
- GTK_CELL_TEXT (clist_row->cell[i])->text);
-
- gdk_gc_set_clip_rectangle (fg_gc, NULL);
- break;
-
- case GTK_CELL_PIXMAP:
- xsrc = 0;
- ysrc = 0;
- xdest = offset + clist_row->cell[i].horizontal;
- ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
- clist_row->cell[i].vertical;
-
- if (xdest < clip_rectangle.x)
- {
- xsrc = clip_rectangle.x - xdest;
- pixmap_width -= xsrc;
- xdest = clip_rectangle.x;
- }
-
- if (xdest + pixmap_width > clip_rectangle.x + clip_rectangle.width)
- pixmap_width = (clip_rectangle.x + clip_rectangle.width) - xdest;
-
- if (ydest < clip_rectangle.y)
- {
- ysrc = clip_rectangle.y - ydest;
- height -= ysrc;
- ydest = clip_rectangle.y;
- }
-
- if (ydest + height > clip_rectangle.y + clip_rectangle.height)
- height = (clip_rectangle.y + clip_rectangle.height) - ydest;
-
- if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
- {
- gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXMAP (clist_row->cell[i])->mask);
- gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
- }
- gdk_draw_pixmap (clist->clist_window,
- fg_gc,
- GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
- xsrc, ysrc,
- xdest, ydest,
- pixmap_width, height);
-
- if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
- {
- gdk_gc_set_clip_origin (fg_gc, 0, 0);
- gdk_gc_set_clip_mask (fg_gc, NULL);
- }
- break;
-
- case GTK_CELL_PIXTEXT:
- /* draw the pixmap */
- xsrc = 0;
- ysrc = 0;
- xdest = offset + clist_row->cell[i].horizontal;
- ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
- clist_row->cell[i].vertical;
-
- if (xdest < clip_rectangle.x)
- {
- xsrc = clip_rectangle.x - xdest;
- pixmap_width -= xsrc;
- xdest = clip_rectangle.x;
- }
-
- if (xdest + pixmap_width > clip_rectangle.x + clip_rectangle.width)
- pixmap_width = (clip_rectangle.x + clip_rectangle.width) - xdest;
+ sel_row = GPOINTER_TO_INT (list->data);
+ list = list->next;
- if (ydest < clip_rectangle.y)
- {
- ysrc = clip_rectangle.y - ydest;
- height -= ysrc;
- ydest = clip_rectangle.y;
- }
+ if (row == sel_row)
+ row_selected = TRUE;
+ else
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
+ sel_row, column, event);
+ }
- if (ydest + height > clip_rectangle.y + clip_rectangle.height)
- height = (clip_rectangle.y + clip_rectangle.height) - ydest;
-
- if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask)
- {
- gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
- gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
- }
-
- gdk_draw_pixmap (clist->clist_window,
- fg_gc,
- GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
- xsrc, ysrc,
- xdest,
- ydest,
- pixmap_width, height);
-
- gdk_gc_set_clip_origin (fg_gc, 0, 0);
-
- offset += pixmap_width + GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
-
- /* draw the string */
- gdk_gc_set_clip_rectangle (fg_gc, rect);
-
- gdk_draw_string (clist->clist_window,
- widget->style->font,
- fg_gc,
- offset + clist_row->cell[i].horizontal,
- row_rectangle.y + clist->row_center_offset +
- clist_row->cell[i].vertical,
- GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
+ if (row_selected)
+ return;
+
+ default:
+ break;
+ }
- gdk_gc_set_clip_rectangle (fg_gc, NULL);
- break;
+ clist_row = ROW_ELEMENT (clist, row)->data;
- case GTK_CELL_WIDGET:
- /* unimplimented */
- continue;
- break;
+ if (clist_row->state != GTK_STATE_NORMAL || !clist_row->selectable)
+ return;
- default:
- continue;
- break;
- }
- }
- if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget))
+ clist_row->state = GTK_STATE_SELECTED;
+ if (!clist->selection)
{
- if (area)
- {
- if (gdk_rectangle_intersect (area, &row_rectangle,
- &intersect_rectangle))
- {
- gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
- gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
- row_rectangle.x, row_rectangle.y,
- row_rectangle.width - 1,
- row_rectangle.height - 1);
- gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
- }
- }
- else
- gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
- row_rectangle.x, row_rectangle.y,
- row_rectangle.width - 1, row_rectangle.height - 1);
+ 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_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+ GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
}
static void
-draw_rows (GtkCList * clist,
- GdkRectangle * area)
+real_unselect_row (GtkCList *clist,
+ gint row,
+ gint column,
+ GdkEvent *event)
{
- GList *list;
GtkCListRow *clist_row;
- int i, first_row, last_row;
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (clist->row_height == 0 ||
- !GTK_WIDGET_DRAWABLE (clist))
+ if (row < 0 || row > (clist->rows - 1))
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--;
+ clist_row = ROW_ELEMENT (clist, row)->data;
- list = g_list_nth (clist->row_list, first_row);
- i = first_row;
- while (list)
+ if (clist_row->state == GTK_STATE_SELECTED)
{
- clist_row = list->data;
- list = list->next;
+ clist_row->state = GTK_STATE_NORMAL;
- if (i > last_row)
- return;
+ if (clist->selection_end &&
+ clist->selection_end->data == GINT_TO_POINTER (row))
+ clist->selection_end = clist->selection_end->prev;
- GTK_CLIST_CLASS_FW (clist)->draw_row (clist, area, i, clist_row);
- i++;
+ clist->selection = g_list_remove (clist->selection,
+ GINT_TO_POINTER (row));
+
+ if (CLIST_UNFROZEN (clist)
+ && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+ GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
}
-
- if (!area)
- gdk_window_clear_area (clist->clist_window, 0, ROW_TOP_YPIXEL (clist, i), -1, -1);
}
-/*
- * SIZE ALLOCATION
- * size_allocate_title_buttons
- * size_allocate_columns
- */
static void
-size_allocate_title_buttons (GtkCList * clist)
+real_select_all (GtkCList *clist)
{
- gint i, last_button = 0;
- GtkAllocation button_allocation;
+ GList *list;
+ gint i;
+
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- if (!GTK_WIDGET_REALIZED (clist))
+ if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
return;
- button_allocation.x = clist->hoffset;
- button_allocation.y = 0;
- button_allocation.width = 0;
- button_allocation.height = clist->column_title_area.height;
-
- for (i = 0; i < clist->columns; i++)
+ switch (clist->selection_mode)
{
- button_allocation.width += clist->column[i].area.width;
+ case GTK_SELECTION_SINGLE:
+ case GTK_SELECTION_BROWSE:
+ return;
- if (i == clist->columns - 1)
- button_allocation.width += 2 * (CELL_SPACING + COLUMN_INSET);
- else
- button_allocation.width += CELL_SPACING + (2 * COLUMN_INSET);
+ case GTK_SELECTION_EXTENDED:
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
+
+ if (clist->rows &&
+ ((GtkCListRow *) (clist->row_list->data))->state !=
+ GTK_STATE_SELECTED)
+ fake_toggle_row (clist, 0);
- if (i == (clist->columns - 1) || clist->column[i + 1].button)
- {
- gtk_widget_size_allocate (clist->column[last_button].button, &button_allocation);
- button_allocation.x += button_allocation.width;
- button_allocation.width = 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_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+ return;
- 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);
-
- last_button = i + 1;
- }
- else
+ case GTK_SELECTION_MULTIPLE:
+ for (i = 0, list = clist->row_list; list; i++, list = list->next)
{
- gdk_window_hide (clist->column[i].window);
+ if (((GtkCListRow *)(list->data))->state == GTK_STATE_NORMAL)
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+ i, -1, NULL);
}
+ return;
}
}
static void
-size_allocate_columns (GtkCList * clist)
+real_unselect_all (GtkCList *clist)
{
- gint i, xoffset = 0;
-
- for (i = 0; i < clist->columns; i++)
- {
- clist->column[i].area.x = xoffset + CELL_SPACING + COLUMN_INSET;
-
- if (i == clist->columns - 1)
- {
- gint width;
+ GList *list;
+ gint i;
+
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- if (clist->column[i].width_set)
- {
- width = clist->column[i].width;
- }
- else
- {
- if (clist->column[i].title)
- width = gdk_string_width (GTK_WIDGET (clist)->style->font,
- clist->column[i].title);
- else
- width = 0;
- }
+ if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+ return;
- clist->column[i].area.width = MAX (width,
- clist->clist_window_width -
- xoffset - (2 * (CELL_SPACING + COLUMN_INSET)));
-
- }
- else
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_BROWSE:
+ if (clist->focus_row >= 0)
{
- clist->column[i].area.width = clist->column[i].width;
+ gtk_signal_emit (GTK_OBJECT (clist),
+ clist_signals[SELECT_ROW],
+ clist->focus_row, -1, NULL);
+ return;
}
+ break;
+ case GTK_SELECTION_EXTENDED:
+ 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;
+ }
- xoffset += clist->column[i].area.width + CELL_SPACING + (2 * COLUMN_INSET);
+ list = clist->selection;
+ while (list)
+ {
+ i = GPOINTER_TO_INT (list->data);
+ list = list->next;
+ gtk_signal_emit (GTK_OBJECT (clist),
+ clist_signals[UNSELECT_ROW], i, -1, NULL);
}
}
-/*
- * SELECTION
- * select_row
- * real_select_row
- * real_unselect_row
- * get_selection_info
- */
static void
-toggle_row (GtkCList * clist,
- gint row,
- gint column,
- GdkEvent * event)
+fake_unselect_all (GtkCList *clist,
+ gint row)
{
- GtkCListRow *clist_row;
+ GList *list;
+ GList *work;
+ gint i;
- switch (clist->selection_mode)
+ if (row >= 0 && (work = ROW_ELEMENT (clist, row)))
{
- case GTK_SELECTION_EXTENDED:
- case GTK_SELECTION_MULTIPLE:
- case GTK_SELECTION_SINGLE:
-
- clist_row = g_list_nth (clist->row_list, row)->data;
- if (clist_row->state == GTK_STATE_SELECTED)
+ if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL &&
+ GTK_CLIST_ROW (work)->selectable)
{
- unselect_row (clist, row, column, event);
- return;
- }
-
- case GTK_SELECTION_BROWSE:
- select_row (clist, row, column, event);
- break;
+ GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
+
+ if (CLIST_UNFROZEN (clist) &&
+ gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+ GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
+ GTK_CLIST_ROW (work));
+ }
}
-}
-static void
-select_row (GtkCList * clist,
- gint row,
- gint column,
- GdkEvent * event)
-{
- gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
- row, column, event);
-}
+ clist->undo_selection = clist->selection;
+ clist->selection = NULL;
+ clist->selection_end = NULL;
-static void
-unselect_row (GtkCList * clist,
- gint row,
- gint column,
- GdkEvent * event)
-{
- gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
- row, column, event);
+ 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_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
+ if (CLIST_UNFROZEN (clist) &&
+ gtk_clist_row_is_visible (clist, i) != GTK_VISIBILITY_NONE)
+ GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, i,
+ GTK_CLIST_ROW (work));
+ }
}
static void
-real_select_row (GtkCList * clist,
- gint row,
- gint column,
- GdkEvent * event)
+real_undo_selection (GtkCList *clist)
{
- GtkCListRow *clist_row;
- GList *list;
- gint sel_row;
- gboolean row_selected;
+ GList *work;
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (row < 0 || row > (clist->rows - 1))
+ if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
+ clist->selection_mode != GTK_SELECTION_EXTENDED)
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
- gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
- sel_row, column, event);
- }
+ GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
- if (row_selected)
- return;
-
- default:
- break;
+ if (!(clist->undo_selection || clist->undo_unselection))
+ {
+ gtk_clist_unselect_all (clist);
+ return;
}
- clist_row = (g_list_nth (clist->row_list, row))->data;
+ for (work = clist->undo_selection; work; work = work->next)
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+ GPOINTER_TO_INT (work->data), -1, NULL);
- if (clist_row->state != GTK_STATE_NORMAL || !clist_row->selectable)
- return;
+ for (work = clist->undo_unselection; work; work = work->next)
+ {
+ /* g_print ("unselect %d\n",GPOINTER_TO_INT (work->data)); */
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
+ GPOINTER_TO_INT (work->data), -1, NULL);
+ }
- clist_row->state = GTK_STATE_SELECTED;
- if (!clist->selection)
+ if (GTK_WIDGET_HAS_FOCUS(clist) && clist->focus_row != clist->undo_anchor)
{
- clist->selection = g_list_append (clist->selection,
- GINT_TO_POINTER (row));
- clist->selection_end = clist->selection;
+ gtk_clist_draw_focus (GTK_WIDGET (clist));
+ clist->focus_row = clist->undo_anchor;
+ gtk_clist_draw_focus (GTK_WIDGET (clist));
}
else
- clist->selection_end =
- g_list_append (clist->selection_end, GINT_TO_POINTER (row))->next;
+ clist->focus_row = clist->undo_anchor;
- if (!GTK_CLIST_FROZEN (clist)
- && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
- GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+ 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_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+ else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+ gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
}
static void
-real_unselect_row (GtkCList * clist,
- gint row,
- gint column,
- GdkEvent * event)
+set_anchor (GtkCList *clist,
+ gboolean add_mode,
+ gint anchor,
+ gint undo_anchor)
{
- GtkCListRow *clist_row;
-
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
-
- if (row < 0 || row > (clist->rows - 1))
+
+ if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor >= 0)
return;
- clist_row = (g_list_nth (clist->row_list, row))->data;
+ g_list_free (clist->undo_selection);
+ g_list_free (clist->undo_unselection);
+ clist->undo_selection = NULL;
+ clist->undo_unselection = NULL;
- if (clist_row->state == GTK_STATE_SELECTED)
+ if (add_mode)
+ fake_toggle_row (clist, anchor);
+ else
{
- 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 (!GTK_CLIST_FROZEN (clist)
- && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
- GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+ GTK_CLIST_CLASS_FW (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 gint
-get_selection_info (GtkCList * clist,
- gint x,
- gint y,
- gint * row,
- gint * column)
+static void
+resync_selection (GtkCList *clist,
+ GdkEvent *event)
{
- gint trow, tcol;
+ gint i;
+ gint e;
+ gint row;
+ GList *list;
+ GtkCListRow *clist_row;
- g_return_val_if_fail (clist != NULL, 0);
- g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
+ if (clist->selection_mode != GTK_SELECTION_EXTENDED)
+ return;
- /* 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_clist_get_selection_info (GtkCList *clist,
- gint x,
- gint y,
- gint * row,
- gint * column)
-{
- g_return_val_if_fail (clist != NULL, 0);
- g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
- return get_selection_info (clist, x, y, row, column);
-}
-
-/*
- * RESIZE COLUMNS
- * draw_xor_line
- * new_column_width
- * resize_column
- */
-static void
-draw_xor_line (GtkCList * 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->klass->ythickness,
- clist->x_drag,
- clist->column_title_area.height + clist->clist_window_height + 1);
-}
-
-/* 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 (GtkCList * clist,
- gint column,
- gint * x,
- gint * visible)
-{
- gint cx, rx, width;
+ if (clist->anchor < 0 || clist->drag_pos < 0)
+ return;
- cx = *x;
+ gtk_clist_freeze (clist);
- /* first translate the x position from widget->window
- * to clist->clist_window */
- cx -= GTK_WIDGET (clist)->style->klass->xthickness;
+ i = MIN (clist->anchor, clist->drag_pos);
+ e = MAX (clist->anchor, clist->drag_pos);
- /* rx is x from the list beginning */
- rx = cx - clist->hoffset;
+ 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;
+ gtk_signal_emit (GTK_OBJECT (clist),
+ clist_signals[UNSELECT_ROW],
+ row, -1, event);
+ clist->undo_selection = g_list_prepend
+ (clist->undo_selection, GINT_TO_POINTER (row));
+ }
+ }
+ }
+ }
- /* you can't shrink a column to less than its minimum width */
- if (cx < (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH))
+ if (clist->anchor < clist->drag_pos)
{
- *x = cx = COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH +
- GTK_WIDGET (clist)->style->klass->xthickness;
- cx -= GTK_WIDGET (clist)->style->klass->xthickness;
- rx = cx - clist->hoffset;
+ for (list = g_list_nth (clist->row_list, i); i <= e;
+ i++, list = list->next)
+ if (GTK_CLIST_ROW (list)->selectable)
+ {
+ if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
+ {
+ if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
+ {
+ GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
+ gtk_signal_emit (GTK_OBJECT (clist),
+ clist_signals[UNSELECT_ROW],
+ i, -1, event);
+ clist->undo_selection =
+ g_list_prepend (clist->undo_selection,
+ GINT_TO_POINTER (i));
+ }
+ }
+ else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
+ {
+ GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
+ clist->undo_unselection =
+ g_list_prepend (clist->undo_unselection,
+ GINT_TO_POINTER (i));
+ }
+ }
}
-
- if (cx < 0 || cx > clist->clist_window_width)
- *visible = 0;
else
- *visible = 1;
-
- /* calculate new column width making sure it doesn't end up
- * less than the minimum width */
- width = (rx - COLUMN_LEFT (clist, column)) - COLUMN_INSET -
- ((clist->columns == (column - 1)) ? CELL_SPACING : 0);
- if (width < COLUMN_MIN_WIDTH)
- width = COLUMN_MIN_WIDTH;
-
- return width;
-}
-
-/* this will do more later */
-static void
-resize_column (GtkCList * clist,
- gint column,
- gint width)
-{
- gtk_clist_set_column_width (clist, column, width);
-}
-
-/* BUTTONS */
-static void
-column_button_create (GtkCList * clist,
- gint column)
-{
- GtkWidget *button;
-
- button = clist->column[column].button = gtk_button_new ();
- 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));
+ {
+ for (list = g_list_nth (clist->row_list, e); i <= e;
+ e--, list = list->prev)
+ if (GTK_CLIST_ROW (list)->selectable)
+ {
+ if (g_list_find (clist->selection, GINT_TO_POINTER(e)))
+ {
+ if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
+ {
+ GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
+ gtk_signal_emit (GTK_OBJECT (clist),
+ clist_signals[UNSELECT_ROW],
+ e, -1, event);
+ clist->undo_selection =
+ g_list_prepend (clist->undo_selection,
+ GINT_TO_POINTER (e));
+ }
+ }
+ else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
+ {
+ GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
+ clist->undo_unselection =
+ g_list_prepend (clist->undo_unselection,
+ GINT_TO_POINTER (e));
+ }
+ }
+ }
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) column_button_clicked,
- (gpointer) clist);
-
- gtk_widget_show (button);
-}
-
-static void
-column_button_clicked (GtkWidget * widget,
- gpointer data)
-{
- gint i;
- GtkCList *clist;
-
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_CLIST (data));
-
- clist = GTK_CLIST (data);
+ clist->undo_unselection = g_list_reverse (clist->undo_unselection);
+ for (list = clist->undo_unselection; list; list = list->next)
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+ GPOINTER_TO_INT (list->data), -1, event);
- /* find the column who's button was pressed */
- for (i = 0; i < clist->columns; i++)
- if (clist->column[i].button == widget)
- break;
+ clist->anchor = -1;
+ clist->drag_pos = -1;
- gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
+ gtk_clist_thaw (clist);
}
-/*
- * SCROLLBARS
- *
- * functions:
- * create_scrollbars
- * adjust_scrollbars
- * vadjustment_changed
- * hadjustment_changed
- * vadjustment_value_changed
- * hadjustment_value_changed
- */
static void
-create_scrollbars (GtkCList * clist)
+update_extended_selection (GtkCList *clist,
+ gint row)
{
- GtkAdjustment *adjustment;
-
- clist->vscrollbar = gtk_vscrollbar_new (NULL);
-
- adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
-
- gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
- (GtkSignalFunc) vadjustment_changed,
- (gpointer) clist);
-
- gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
- (GtkSignalFunc) vadjustment_value_changed,
- (gpointer) clist);
-
- gtk_widget_set_parent (clist->vscrollbar, GTK_WIDGET (clist));
- gtk_widget_show (clist->vscrollbar);
-
- clist->hscrollbar = gtk_hscrollbar_new (NULL);
-
- adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
-
- gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
- (GtkSignalFunc) hadjustment_changed,
- (gpointer) clist);
-
- gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
- (GtkSignalFunc) hadjustment_value_changed,
- (gpointer) clist);
+ 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;
- gtk_widget_set_parent (clist->hscrollbar, GTK_WIDGET (clist));
- gtk_widget_show (clist->hscrollbar);
-}
+ if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor == -1)
+ return;
-static void
-adjust_scrollbars (GtkCList * clist)
-{
- GTK_RANGE (clist->vscrollbar)->adjustment->page_size = clist->clist_window_height;
- GTK_RANGE (clist->vscrollbar)->adjustment->page_increment = clist->clist_window_height / 2;
- GTK_RANGE (clist->vscrollbar)->adjustment->step_increment = 10;
- GTK_RANGE (clist->vscrollbar)->adjustment->lower = 0;
- GTK_RANGE (clist->vscrollbar)->adjustment->upper = LIST_HEIGHT (clist);
+ if (row < 0)
+ row = 0;
+ if (row >= clist->rows)
+ row = clist->rows - 1;
- if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
+ /* extending downwards */
+ if (row > clist->drag_pos && clist->anchor <= clist->drag_pos)
{
- GTK_RANGE (clist->vscrollbar)->adjustment->value = MAX (0, LIST_HEIGHT (clist) -
- clist->clist_window_height);
- gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
- "value_changed");
+ s2 = clist->drag_pos + 1;
+ e2 = row;
}
-
- GTK_RANGE (clist->hscrollbar)->adjustment->page_size = clist->clist_window_width;
- GTK_RANGE (clist->hscrollbar)->adjustment->page_increment = clist->clist_window_width / 2;
- GTK_RANGE (clist->hscrollbar)->adjustment->step_increment = 10;
- GTK_RANGE (clist->hscrollbar)->adjustment->lower = 0;
- GTK_RANGE (clist->hscrollbar)->adjustment->upper = LIST_WIDTH (clist);
-
- if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
+ /* extending upwards */
+ else if (row < clist->drag_pos && clist->anchor >= clist->drag_pos)
{
- GTK_RANGE (clist->hscrollbar)->adjustment->value = MAX (0, LIST_WIDTH (clist) -
- clist->clist_window_width);
- gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
- "value_changed");
+ s2 = row;
+ e2 = clist->drag_pos - 1;
}
-
- if (LIST_HEIGHT (clist) <= clist->clist_window_height &&
- clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
+ else if (row < clist->drag_pos && clist->anchor < clist->drag_pos)
{
- if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
+ 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)
{
- gtk_widget_hide (clist->vscrollbar);
- gtk_widget_size_allocate (GTK_WIDGET (clist),
- >K_WIDGET (clist)->allocation);
+ s1 = clist->anchor + 1;
+ s2 = row;
+ e2 = clist->anchor - 1;
}
+ /* take back the selection between anchor and drag_pos */
+ else
+ s1 = row + 1;
}
- else
+ else if (row > clist->drag_pos && clist->anchor > clist->drag_pos)
{
- if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
+ 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)
{
- gtk_widget_show (clist->vscrollbar);
- gtk_widget_size_allocate (GTK_WIDGET (clist),
- >K_WIDGET (clist)->allocation);
+ e1 = clist->anchor - 1;
+ s2 = clist->anchor + 1;
+ e2 = row;
}
+ /* take back the selection between anchor and drag_pos */
+ else
+ e1 = row - 1;
}
- if (LIST_WIDTH (clist) <= clist->clist_window_width &&
- clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
+ clist->drag_pos = row;
+
+ area.x = 0;
+ area.width = clist->clist_window_width;
+
+ /* restore the elements between s1 and e1 */
+ if (s1 >= 0)
{
- if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
+ for (i = s1, list = g_list_nth (clist->row_list, i); i <= e1;
+ i++, list = list->next)
+ if (GTK_CLIST_ROW (list)->selectable)
+ {
+ if (GTK_CLIST_CLASS_FW (clist)->selection_find (clist, i, list))
+ GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
+ else
+ GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
+ }
+
+ top = ROW_TOP_YPIXEL (clist, clist->focus_row);
+
+ if (top + clist->row_height <= 0)
{
- gtk_widget_hide (clist->hscrollbar);
- gtk_widget_size_allocate (GTK_WIDGET (clist),
- >K_WIDGET (clist)->allocation);
+ area.y = 0;
+ area.height = ROW_TOP_YPIXEL (clist, e1) + clist->row_height;
+ draw_rows (clist, &area);
+ gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
}
- }
- else
- {
- if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
+ else if (top >= clist->clist_window_height)
{
- gtk_widget_show (clist->hscrollbar);
- gtk_widget_size_allocate (GTK_WIDGET (clist),
- >K_WIDGET (clist)->allocation);
+ area.y = ROW_TOP_YPIXEL (clist, s1) - 1;
+ area.height = clist->clist_window_height - area.y;
+ draw_rows (clist, &area);
+ gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
}
- }
+ else if (top < 0)
+ gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+ else if (top + clist->row_height > clist->clist_window_height)
+ gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
- gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
- gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment), "changed");
-}
+ y1 = ROW_TOP_YPIXEL (clist, s1) - 1;
+ h1 = (e1 - s1 + 1) * (clist->row_height + CELL_SPACING);
+ }
-static void
-vadjustment_changed (GtkAdjustment * adjustment,
- gpointer data)
-{
- GtkCList *clist;
+ /* 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_CLIST_ROW (list)->selectable &&
+ GTK_CLIST_ROW (list)->state != clist->anchor_state)
+ GTK_CLIST_ROW (list)->state = clist->anchor_state;
- g_return_if_fail (adjustment != NULL);
- g_return_if_fail (data != NULL);
+ top = ROW_TOP_YPIXEL (clist, clist->focus_row);
- clist = GTK_CLIST (data);
+ if (top + clist->row_height <= 0)
+ {
+ area.y = 0;
+ area.height = ROW_TOP_YPIXEL (clist, e2) + clist->row_height;
+ draw_rows (clist, &area);
+ gtk_clist_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_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+ }
+ else if (top < 0)
+ gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+ else if (top + clist->row_height > clist->clist_window_height)
+ gtk_clist_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
-hadjustment_changed (GtkAdjustment * adjustment,
- gpointer data)
+start_selection (GtkCList *clist)
{
- GtkCList *clist;
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- g_return_if_fail (adjustment != NULL);
- g_return_if_fail (data != NULL);
+ if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+ return;
- clist = GTK_CLIST (data);
+ set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
+ clist->focus_row);
}
static void
-check_exposures (GtkCList *clist)
+end_selection (GtkCList *clist)
{
- GdkEvent *event;
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- if (!GTK_WIDGET_REALIZED (clist))
+ if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS(clist))
return;
- /* Make sure graphics expose events are processed before scrolling
- * again */
- while ((event = gdk_event_get_graphics_expose (clist->clist_window)) != NULL)
- {
- gtk_widget_event (GTK_WIDGET (clist), event);
- if (event->expose.count == 0)
- {
- gdk_event_free (event);
- break;
- }
- gdk_event_free (event);
- }
+ GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
}
static void
-vadjustment_value_changed (GtkAdjustment * adjustment,
- gpointer data)
+extend_selection (GtkCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position,
+ gboolean auto_start_selection)
{
- GtkCList *clist;
- GdkRectangle area;
- gint diff, value;
-
- g_return_if_fail (adjustment != NULL);
- g_return_if_fail (data != NULL);
- g_return_if_fail (GTK_IS_CLIST (data));
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- clist = GTK_CLIST (data);
+ if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
+ clist->selection_mode != GTK_SELECTION_EXTENDED)
+ return;
- if (!GTK_WIDGET_DRAWABLE (clist))
+ if (auto_start_selection)
+ set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
+ clist->focus_row);
+ else if (clist->anchor == -1)
return;
- value = adjustment->value;
+ move_focus_row (clist, scroll_type, position);
- if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar)))
- {
- if (value > -clist->voffset)
- {
- /* scroll down */
- diff = value + clist->voffset;
+ if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
+ clist->clist_window_height)
+ gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+ else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+ gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
- /* we have to re-draw the whole screen here... */
- if (diff >= clist->clist_window_height)
- {
- clist->voffset = -value;
- draw_rows (clist, NULL);
- return;
- }
+ update_extended_selection (clist, clist->focus_row);
+}
- if ((diff != 0) && (diff != clist->clist_window_height))
- gdk_window_copy_area (clist->clist_window,
- clist->fg_gc,
- 0, 0,
- clist->clist_window,
- 0,
- diff,
- clist->clist_window_width,
- clist->clist_window_height - diff);
-
- area.x = 0;
- area.y = clist->clist_window_height - diff;
- area.width = clist->clist_window_width;
- area.height = diff;
- }
- else
- {
- /* scroll up */
- diff = -clist->voffset - value;
+static void
+sync_selection (GtkCList *clist,
+ gint row,
+ gint mode)
+{
+ GList *list;
+ gint d;
- /* we have to re-draw the whole screen here... */
- if (diff >= clist->clist_window_height)
- {
- clist->voffset = -value;
- draw_rows (clist, NULL);
- return;
- }
+ 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 (clist->focus_row >= clist->rows)
+ clist->focus_row = clist->rows - 1;
+ }
- if ((diff != 0) && (diff != clist->clist_window_height))
- gdk_window_copy_area (clist->clist_window,
- clist->fg_gc,
- 0, diff,
- clist->clist_window,
- 0,
- 0,
- clist->clist_window_width,
- clist->clist_window_height - diff);
-
- area.x = 0;
- area.y = 0;
- area.width = clist->clist_window_width;
- area.height = diff;
+ GTK_CLIST_CLASS_FW (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->voffset = -value;
- if ((diff != 0) && (diff != clist->clist_window_height))
- check_exposures (clist);
- }
+ clist->anchor = -1;
+ clist->drag_pos = -1;
+ clist->undo_anchor = clist->focus_row;
- draw_rows (clist, &area);
+ list = clist->selection;
+
+ while (list)
+ {
+ if (GPOINTER_TO_INT (list->data) >= row)
+ list->data = ((gchar*) list->data) + d;
+ list = list->next;
+ }
}
+/* GTKOBJECT
+ * gtk_clist_destroy
+ * gtk_clist_finalize
+ */
static void
-hadjustment_value_changed (GtkAdjustment * adjustment,
- gpointer data)
+gtk_clist_destroy (GtkObject *object)
{
- GtkCList *clist;
- GdkRectangle area;
gint i;
- gint y = 0;
- gint diff = 0;
- gint value;
+ GtkCList *clist;
- g_return_if_fail (adjustment != NULL);
- g_return_if_fail (data != NULL);
- g_return_if_fail (GTK_IS_CLIST (data));
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_CLIST (object));
- clist = GTK_CLIST (data);
+ clist = GTK_CLIST (object);
- if (!GTK_WIDGET_DRAWABLE (clist) ||
- adjustment != gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar)))
- return;
+ /* freeze the list */
+ clist->freeze_count++;
- value = adjustment->value;
-
- /* move the column buttons and resize windows */
- for (i = 0; i < clist->columns; i++)
+ /* get rid of all the rows */
+ gtk_clist_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)
{
- if (clist->column[i].button)
- {
- clist->column[i].button->allocation.x -= value + clist->hoffset;
-
- if (clist->column[i].button->window)
- {
- gdk_window_move (clist->column[i].button->window,
- clist->column[i].button->allocation.x,
- clist->column[i].button->allocation.y);
-
- if (clist->column[i].window)
- gdk_window_move (clist->column[i].window,
- clist->column[i].button->allocation.x +
- clist->column[i].button->allocation.width -
- (DRAG_WIDTH / 2), 0);
- }
- }
+ gtk_signal_disconnect_by_data (GTK_OBJECT (clist->hadjustment), clist);
+ gtk_object_unref (GTK_OBJECT (clist->hadjustment));
+ clist->hadjustment = NULL;
}
-
- if (value > -clist->hoffset)
+ if (clist->vadjustment)
{
- /* scroll right */
- diff = value + clist->hoffset;
-
- clist->hoffset = -value;
-
- /* we have to re-draw the whole screen here... */
- if (diff >= clist->clist_window_width)
- {
- draw_rows (clist, NULL);
- return;
- }
+ gtk_signal_disconnect_by_data (GTK_OBJECT (clist->vadjustment), clist);
+ gtk_object_unref (GTK_OBJECT (clist->vadjustment));
+ clist->vadjustment = NULL;
+ }
- if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
- GTK_CLIST_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_copy_area (clist->clist_window,
- clist->fg_gc,
- 0, 0,
- clist->clist_window,
- diff,
- 0,
- clist->clist_window_width - diff,
- clist->clist_window_height);
+ remove_grab (clist);
- area.x = clist->clist_window_width - diff;
- }
- else
- {
- /* scroll left */
- if (!(diff = -clist->hoffset - value))
- return;
+ /* 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;
+ }
- clist->hoffset = -value;
-
- /* we have to re-draw the whole screen here... */
- if (diff >= clist->clist_window_width)
- {
- draw_rows (clist, NULL);
- return;
- }
-
- if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
- GTK_CLIST_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);
- }
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
- gdk_window_copy_area (clist->clist_window,
- clist->fg_gc,
- diff, 0,
- clist->clist_window,
- 0,
- 0,
- clist->clist_window_width - diff,
- clist->clist_window_height);
-
- area.x = 0;
- }
+static void
+gtk_clist_finalize (GtkObject *object)
+{
+ GtkCList *clist;
- area.y = 0;
- area.width = diff;
- area.height = clist->clist_window_height;
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_CLIST (object));
- check_exposures (clist);
+ clist = GTK_CLIST (object);
- if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist))
- {
- if (GTK_CLIST_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
- {
- gint x0;
- gint x1;
-
- if (area.x == 0)
- {
- x0 = clist->clist_window_width - 1;
- x1 = diff;
- }
- else
- {
- x0 = 0;
- x1 = area.x - 1;
- }
-
- 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);
-
- }
- }
- draw_rows (clist, &area);
+ columns_delete (clist);
+
+ g_mem_chunk_destroy (clist->cell_mem_chunk);
+ g_mem_chunk_destroy (clist->row_mem_chunk);
+
+ if (GTK_OBJECT_CLASS (parent_class)->finalize)
+ (*GTK_OBJECT_CLASS (parent_class)->finalize) (object);
}
-/*
- * Memory Allocation/Distruction Routines for GtkCList stuctures
- *
- * functions:
- * columns_new
- * column_title_new
- * columns_delete
- * row_new
- * row_delete
- * set_cell_contents
+/* GTKWIDGET
+ * gtk_clist_realize
+ * gtk_clist_unrealize
+ * gtk_clist_map
+ * gtk_clist_unmap
+ * gtk_clist_draw
+ * gtk_clist_expose
+ * gtk_clist_style_set
+ * gtk_clist_key_press
+ * gtk_clist_button_press
+ * gtk_clist_button_release
+ * gtk_clist_motion
+ * gtk_clist_size_request
+ * gtk_clist_size_allocate
*/
-static GtkCListColumn *
-columns_new (GtkCList * clist)
+static void
+gtk_clist_realize (GtkWidget *widget)
{
+ GtkCList *clist;
+ GdkWindowAttr attributes;
+ GdkGCValues values;
+ GtkCListRow *clist_row;
+ GList *list;
+ gint attributes_mask;
+ gint border_width;
gint i;
- GtkCListColumn *column;
+ gint j;
- column = g_new (GtkCListColumn, clist->columns);
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (widget));
- 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].width_set = FALSE;
- column[i].justification = GTK_JUSTIFY_LEFT;
- }
+ clist = GTK_CLIST (widget);
- return column;
-}
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-static void
-column_title_new (GtkCList *clist,
- gint column,
- const gchar *title)
-{
- if (clist->column[column].title)
- g_free (clist->column[column].title);
+ 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_PRESS_MASK |
+ GDK_KEY_RELEASE_MASK);
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
- clist->column[column].title = g_strdup (title);
-}
+ /* main window */
+ widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, clist);
-static void
-columns_delete (GtkCList * clist)
-{
- gint i;
+ 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].title)
- g_free (clist->column[i].title);
-
- g_free (clist->column);
-}
+ if (clist->column[i].button)
+ gtk_widget_set_parent_window (clist->column[i].button,
+ clist->title_window);
-static GtkCListRow *
-row_new (GtkCList * clist)
-{
- int i;
- GtkCListRow *clist_row;
+ /* clist-window */
+ attributes.x = (clist->internal_allocation.x +
+ widget->style->klass->xthickness);
+ attributes.y = (clist->internal_allocation.y +
+ widget->style->klass->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);
- clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
- clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
+ gdk_window_set_background (clist->clist_window,
+ &widget->style->base[GTK_STATE_NORMAL]);
+ gdk_window_show (clist->clist_window);
+ gdk_window_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 |
+ GDK_KEY_PRESS_MASK);
+ attributes_mask = GDK_WA_CURSOR;
+ attributes.cursor = gdk_cursor_new (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_row->cell[i].type = GTK_CELL_EMPTY;
- clist_row->cell[i].vertical = 0;
- clist_row->cell[i].horizontal = 0;
+ clist->column[i].window = gdk_window_new (clist->title_window,
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (clist->column[i].window, clist);
}
- clist_row->fg_set = FALSE;
- clist_row->bg_set = FALSE;
- clist_row->selectable = TRUE;
- clist_row->state = GTK_STATE_NORMAL;
- clist_row->data = NULL;
- clist_row->destroy = NULL;
+ /* This is slightly less efficient than creating them with the
+ * right size to begin with, but easier
+ */
+ size_allocate_title_buttons (clist);
- return clist_row;
+ /* 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_color_alloc (colormap, &clist_row->foreground);
+ if (clist_row->bg_set)
+ gdk_color_alloc (colormap, &clist_row->background);
+ }
+
+ 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
-row_delete (GtkCList * clist,
- GtkCListRow * clist_row)
+gtk_clist_unrealize (GtkWidget *widget)
{
gint i;
+ GtkCList *clist;
- for (i = 0; i < clist->columns; i++)
- GTK_CLIST_CLASS_FW (clist)->set_cell_contents
- (clist, clist_row, i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (widget));
- if (clist_row->destroy)
- clist_row->destroy (clist_row->data);
+ clist = GTK_CLIST (widget);
- g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
- g_mem_chunk_free (clist->row_mem_chunk, clist_row);
-}
+ /* freeze the list */
+ clist->freeze_count++;
-static void
-set_cell_contents (GtkCList *clist,
- GtkCListRow *clist_row,
- gint column,
- GtkCellType type,
- const gchar *text,
- guint8 spacing,
- GdkPixmap *pixmap,
- GdkBitmap *mask)
-{
- g_return_if_fail (clist_row != NULL);
+ if (GTK_WIDGET_MAPPED (widget))
+ gtk_clist_unmap (widget);
- switch (clist_row->cell[column].type)
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+
+ /* detach optional row/cell styles */
+ if (GTK_WIDGET_REALIZED (widget))
{
- case GTK_CELL_EMPTY:
- break;
-
- case GTK_CELL_TEXT:
- g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
- break;
-
- case GTK_CELL_PIXMAP:
- gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
- if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
- gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
- break;
-
- case GTK_CELL_PIXTEXT:
- g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
- gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
- if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
- gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
- break;
+ GtkCListRow *clist_row;
+ GList *list;
+ gint j;
- case GTK_CELL_WIDGET:
- /* unimplimented */
- break;
-
- default:
- break;
+ 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);
+ }
}
- clist_row->cell[column].type = GTK_CELL_EMPTY;
+ gdk_cursor_destroy (clist->cursor_drag);
+ gdk_gc_destroy (clist->xor_gc);
+ gdk_gc_destroy (clist->fg_gc);
+ gdk_gc_destroy (clist->bg_gc);
- switch (type)
+ for (i = 0; i < clist->columns; i++)
{
- case GTK_CELL_TEXT:
- if (text)
+ if (clist->column[i].button)
+ gtk_widget_unrealize (clist->column[i].button);
+ if (clist->column[i].window)
{
- clist_row->cell[column].type = GTK_CELL_TEXT;
- GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
+ gdk_window_set_user_data (clist->column[i].window, NULL);
+ gdk_window_destroy (clist->column[i].window);
+ clist->column[i].window = NULL;
}
- break;
+ }
- case GTK_CELL_PIXMAP:
- if (pixmap)
- {
- clist_row->cell[column].type = GTK_CELL_PIXMAP;
- GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
- /* We set the mask even if it is NULL */
- GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
- }
- break;
+ gdk_window_set_user_data (clist->clist_window, NULL);
+ gdk_window_destroy (clist->clist_window);
+ clist->clist_window = NULL;
- case GTK_CELL_PIXTEXT:
- if (text && pixmap)
- {
- clist_row->cell[column].type = GTK_CELL_PIXTEXT;
- GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
- GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
- GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
- GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
- }
- break;
+ gdk_window_set_user_data (clist->title_window, NULL);
+ gdk_window_destroy (clist->title_window);
+ clist->title_window = NULL;
- default:
- break;
- }
-}
+ clist->cursor_drag = NULL;
+ clist->xor_gc = NULL;
+ clist->fg_gc = NULL;
+ clist->bg_gc = NULL;
-/* Fill in data after widget has correct style */
+ if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+ (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
-static void
-add_style_data (GtkCList * clist)
+static void
+gtk_clist_map (GtkWidget *widget)
{
- GtkWidget *widget;
+ gint i;
+ GtkCList *clist;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (widget));
- widget = GTK_WIDGET(clist);
+ clist = GTK_CLIST (widget);
- /* text properties */
- if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
- {
- clist->row_height = widget->style->font->ascent + widget->style->font->descent + 1;
- clist->row_center_offset = widget->style->font->ascent + 1.5;
- }
- else
+ if (!GTK_WIDGET_MAPPED (widget))
{
- gint text_height;
- text_height = clist->row_height - (GTK_WIDGET (clist)->style->font->ascent +
- GTK_WIDGET (clist) ->style->font->descent + 1);
- clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
- }
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
- /* Column widths */
-}
+ /* 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);
-/* focus functions */
+ /* unfreeze the list */
+ clist->freeze_count = 0;
+ }
+}
static void
-gtk_clist_draw_focus (GtkWidget *widget)
+gtk_clist_unmap (GtkWidget *widget)
{
+ gint i;
GtkCList *clist;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_CLIST (widget));
- if (!GTK_WIDGET_DRAWABLE (widget))
- return;
-
clist = GTK_CLIST (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);
+
+ if (GTK_WIDGET_MAPPED (widget))
+ {
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+
+ if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+ {
+ remove_grab (clist);
+
+ GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, NULL);
+
+ clist->click_cell.row = -1;
+ clist->click_cell.column = -1;
+ clist->drag_button = 0;
+
+ if (GTK_CLIST_IN_DRAG(clist))
+ {
+ gpointer drag_data;
+
+ GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
+ drag_data = gtk_object_get_data (GTK_OBJECT (clist),
+ "gtk-site-data");
+ if (drag_data)
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist),
+ 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 void
-gtk_clist_set_focus_child (GtkContainer *container,
- GtkWidget *child)
+gtk_clist_draw (GtkWidget *widget,
+ GdkRectangle *area)
{
- g_return_if_fail (container != NULL);
- g_return_if_fail (GTK_IS_CLIST (container));
+ GtkCList *clist;
+ gint border_width;
+ GdkRectangle child_area;
+ int i;
- if (child)
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
{
- g_return_if_fail (GTK_IS_WIDGET (child));
- GTK_CLIST_SET_FLAG (GTK_CLIST (container), CLIST_CHILD_HAS_FOCUS);
- }
+ clist = GTK_CLIST (widget);
+ border_width = GTK_CONTAINER (widget)->border_width;
- parent_class->set_focus_child (container, child);
+ gdk_window_clear_area (widget->window,
+ area->x - border_width,
+ area->y - border_width,
+ area->width, area->height);
+
+ /* draw list shadow/border */
+ gtk_draw_shadow (widget->style, widget->window,
+ GTK_STATE_NORMAL, clist->shadow_type,
+ 0, 0,
+ clist->clist_window_width +
+ (2 * widget->style->klass->xthickness),
+ clist->clist_window_height +
+ (2 * widget->style->klass->ythickness) +
+ clist->column_title_area.height);
+
+ gdk_window_clear_area (clist->clist_window, 0, 0, 0, 0);
+ draw_rows (clist, NULL);
+
+ for (i = 0; i < clist->columns; i++)
+ {
+ if (!clist->column[i].visible)
+ continue;
+ if (clist->column[i].button &&
+ gtk_widget_intersect(clist->column[i].button, area, &child_area))
+ gtk_widget_draw (clist->column[i].button, &child_area);
+ }
+ }
}
static gint
-gtk_clist_focus_in (GtkWidget *widget,
- GdkEventFocus *event)
+gtk_clist_expose (GtkWidget *widget,
+ GdkEventExpose *event)
{
GtkCList *clist;
g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
- GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
- GTK_CLIST_UNSET_FLAG (widget, CLIST_CHILD_HAS_FOCUS);
-
- clist = GTK_CLIST (widget);
-
- if (clist->selection_mode == GTK_SELECTION_BROWSE &&
- clist->selection == NULL && clist->focus_row > -1)
+ if (GTK_WIDGET_DRAWABLE (widget))
{
- GList *list;
+ clist = GTK_CLIST (widget);
- list = g_list_nth (clist->row_list, clist->focus_row);
- if (list && GTK_CLIST_ROW (list)->selectable)
- select_row (clist, clist->focus_row, -1, (GdkEvent *) event);
- else
- gtk_widget_draw_focus (widget);
+ /* draw border */
+ if (event->window == widget->window)
+ gtk_draw_shadow (widget->style, widget->window,
+ GTK_STATE_NORMAL, clist->shadow_type,
+ 0, 0,
+ clist->clist_window_width +
+ (2 * widget->style->klass->xthickness),
+ clist->clist_window_height +
+ (2 * widget->style->klass->ythickness) +
+ clist->column_title_area.height);
+
+ /* exposure events on the list */
+ if (event->window == clist->clist_window)
+ draw_rows (clist, &event->area);
}
- else
- gtk_widget_draw_focus (widget);
return FALSE;
}
-static gint
-gtk_clist_focus_out (GtkWidget *widget,
- GdkEventFocus *event)
+static void
+gtk_clist_style_set (GtkWidget *widget,
+ GtkStyle *previous_style)
{
GtkCList *clist;
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (widget));
- GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
- gtk_widget_draw_focus (widget);
-
- clist = GTK_CLIST (widget);
+ if (GTK_WIDGET_CLASS (parent_class)->style_set)
+ (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
- if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
- GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, (GdkEvent *) event);
+ clist = GTK_CLIST (widget);
- return FALSE;
-}
+ 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_SELECTED);
+ gdk_window_set_background (clist->clist_window, &widget->style->base[GTK_STATE_NORMAL]);
+ }
-static void
-toggle_add_mode (GtkCList *clist)
-{
- g_return_if_fail (clist != 0);
- g_return_if_fail (GTK_IS_CLIST (clist));
-
- if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
- clist->selection_mode != GTK_SELECTION_EXTENDED)
- return;
+ /* Fill in data after widget has correct style */
- gtk_clist_draw_focus (GTK_WIDGET (clist));
- if (!GTK_CLIST_ADD_MODE (clist))
+ /* text properties */
+ if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
{
- GTK_CLIST_SET_FLAG (clist, CLIST_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);
+ clist->row_height = (widget->style->font->ascent +
+ widget->style->font->descent + 1);
+ clist->row_center_offset = widget->style->font->ascent + 1.5;
}
else
- {
- GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
- gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
- clist->anchor_state = GTK_STATE_SELECTED;
- }
- gtk_clist_draw_focus (GTK_WIDGET (clist));
-}
-
-static void
-toggle_focus_row (GtkCList *clist)
-{
- g_return_if_fail (clist != 0);
- g_return_if_fail (GTK_IS_CLIST (clist));
-
- if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
- clist->focus_row < 0 || clist->focus_row >= clist->rows)
- return;
+ clist->row_center_offset = 1.5 + (clist->row_height +
+ widget->style->font->ascent -
+ widget->style->font->descent - 1) / 2;
- switch (clist->selection_mode)
+ /* Column widths */
+ if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
{
- case GTK_SELECTION_SINGLE:
- case GTK_SELECTION_MULTIPLE:
- toggle_row (clist, clist->focus_row, 0, NULL);
- break;
- case GTK_SELECTION_EXTENDED:
- 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_CLIST_ADD_MODE (clist))
- fake_toggle_row (clist, clist->focus_row);
- else
- GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist,clist->focus_row);
+ gint width;
+ gint i;
- GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
- break;
- default:
- break;
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].auto_resize)
+ {
+ width = gtk_clist_optimal_column_width (clist, i);
+ if (width != clist->column[i].width)
+ gtk_clist_set_column_width (clist, i, width);
+ }
}
}
-static void
-move_focus_row (GtkCList *clist,
- GtkScrollType scroll_type,
- gfloat position)
+static gint
+gtk_clist_key_press (GtkWidget *widget,
+ GdkEventKey *event)
{
- GtkWidget *widget;
-
- g_return_if_fail (clist != 0);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
- widget = GTK_WIDGET (clist);
+ if (GTK_WIDGET_CLASS (parent_class)->key_press_event &&
+ GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event))
+ return TRUE;
- switch (scroll_type)
+ switch (event->keyval)
{
- case GTK_SCROLL_STEP_BACKWARD:
- if (clist->focus_row <= 0)
- return;
- gtk_clist_draw_focus (widget);
- clist->focus_row--;
- gtk_clist_draw_focus (widget);
- break;
- case GTK_SCROLL_STEP_FORWARD:
- if (clist->focus_row >= clist->rows - 1)
- return;
- gtk_clist_draw_focus (widget);
- clist->focus_row++;
- gtk_clist_draw_focus (widget);
- break;
- case GTK_SCROLL_PAGE_BACKWARD:
- if (clist->focus_row <= 0)
- return;
- gtk_clist_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_clist_draw_focus (widget);
- break;
- case GTK_SCROLL_PAGE_FORWARD:
- if (clist->focus_row >= clist->rows - 1)
- return;
- gtk_clist_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_clist_draw_focus (widget);
- break;
- case GTK_SCROLL_JUMP:
- if (position >= 0 && position <= 1)
- {
- gtk_clist_draw_focus (widget);
- clist->focus_row = position * (clist->rows - 1);
- gtk_clist_draw_focus (widget);
- }
- break;
+ case GDK_Tab:
+ case GDK_ISO_Left_Tab:
+ if (event->state & GDK_SHIFT_MASK)
+ return gtk_container_focus (GTK_CONTAINER (widget),
+ GTK_DIR_TAB_BACKWARD);
+ else
+ return gtk_container_focus (GTK_CONTAINER (widget),
+ GTK_DIR_TAB_FORWARD);
default:
break;
}
+ return FALSE;
}
-static void
-scroll_horizontal (GtkCList *clist,
- GtkScrollType scroll_type,
- gfloat position)
+static gint
+gtk_clist_button_press (GtkWidget *widget,
+ GdkEventButton *event)
{
- gint column = 0;
-
- g_return_if_fail (clist != 0);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ gint i;
+ GtkCList *clist;
+ gint x;
+ gint y;
+ gint row;
+ gint column;
+ gint button_actions;
- if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
- return;
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
- 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 < clist->columns - 1)
- column++;
- break;
- case GTK_SCROLL_PAGE_BACKWARD:
- case GTK_SCROLL_PAGE_FORWARD:
- return;
- case GTK_SCROLL_JUMP:
- if (position >= 0 && position <= 1)
- column = position * (clist->columns - 1);
- else
- return;
- break;
- default:
- break;
- }
+ clist = GTK_CLIST (widget);
- if (COLUMN_LEFT_XPIXEL (clist, column) < CELL_SPACING + COLUMN_INSET)
- gtk_clist_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 == clist->columns - 1)
- gtk_clist_moveto (clist, -1, column, 0, 0);
- else
- gtk_clist_moveto (clist, -1, column, 0, 1);
- }
-}
+ button_actions = clist->button_actions[event->button - 1];
-static void
-scroll_vertical (GtkCList *clist,
- GtkScrollType scroll_type,
- gfloat position)
-{
- gint old_focus_row;
+ if (button_actions == GTK_BUTTON_IGNORED)
+ return FALSE;
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ /* selections on the list */
+ if (event->window == clist->clist_window)
+ {
+ x = event->x;
+ y = event->y;
- if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
- return;
+ if (get_selection_info (clist, x, y, &row, &column))
+ {
+ gint old_row = clist->focus_row;
- switch (clist->selection_mode)
- {
- case GTK_SELECTION_EXTENDED:
- if (clist->anchor >= 0)
- return;
+ if (clist->focus_row == -1)
+ old_row = row;
- case GTK_SELECTION_BROWSE:
+ if (event->type == GDK_BUTTON_PRESS)
+ {
+ GdkEventMask mask = ((1 << (4 + event->button)) |
+ GDK_POINTER_MOTION_HINT_MASK |
+ GDK_BUTTON_RELEASE_MASK);
- old_focus_row = clist->focus_row;
- move_focus_row (clist, scroll_type, position);
+ if (gdk_pointer_grab (clist->clist_window, FALSE, mask,
+ NULL, NULL, event->time))
+ return FALSE;
+ gtk_grab_add (widget);
- if (old_focus_row != clist->focus_row)
- {
- if (clist->selection_mode == GTK_SELECTION_BROWSE)
- unselect_row (clist,old_focus_row, -1, NULL);
- else if (!GTK_CLIST_ADD_MODE (clist))
+ clist->click_cell.row = row;
+ clist->click_cell.column = column;
+ clist->drag_button = event->button;
+ }
+ else
{
- gtk_clist_unselect_all (clist);
- clist->undo_anchor = old_focus_row;
+ clist->click_cell.row = -1;
+ clist->click_cell.column = -1;
+
+ clist->drag_button = 0;
+ remove_grab (clist);
}
- }
- switch (gtk_clist_row_is_visible (clist, clist->focus_row))
- {
- case GTK_VISIBILITY_NONE:
- if (old_focus_row != clist->focus_row &&
- !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
- GTK_CLIST_ADD_MODE (clist)))
- select_row (clist, clist->focus_row, -1, NULL);
- switch (scroll_type)
+ if (button_actions & GTK_BUTTON_SELECTS)
{
- case GTK_SCROLL_STEP_BACKWARD:
- case GTK_SCROLL_PAGE_BACKWARD:
- gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
- break;
- case GTK_SCROLL_STEP_FORWARD:
- case GTK_SCROLL_PAGE_FORWARD:
- gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
- break;
- case GTK_SCROLL_JUMP:
- gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
- break;
- default:
- break;
+ if (GTK_CLIST_ADD_MODE(clist))
+ {
+ GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
+ if (GTK_WIDGET_HAS_FOCUS(widget))
+ {
+ gtk_clist_draw_focus (widget);
+ gdk_gc_set_line_attributes (clist->xor_gc, 1,
+ GDK_LINE_SOLID, 0, 0);
+ clist->focus_row = row;
+ gtk_clist_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_clist_draw_focus (widget);
+ clist->focus_row = row;
+ gtk_clist_draw_focus (widget);
+ }
+ else
+ clist->focus_row = row;
+ }
}
- break;
- case GTK_VISIBILITY_PARTIAL:
- switch (scroll_type)
+ if (!GTK_WIDGET_HAS_FOCUS(widget))
+ gtk_widget_grab_focus (widget);
+
+ if (button_actions & GTK_BUTTON_SELECTS)
{
- case GTK_SCROLL_STEP_BACKWARD:
- case GTK_SCROLL_PAGE_BACKWARD:
- gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
- break;
- case GTK_SCROLL_STEP_FORWARD:
- case GTK_SCROLL_PAGE_FORWARD:
- gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
- break;
- case GTK_SCROLL_JUMP:
- gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
- break;
- default:
- break;
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_SINGLE:
+ case GTK_SELECTION_MULTIPLE:
+ if (event->type != GDK_BUTTON_PRESS)
+ {
+ gtk_signal_emit (GTK_OBJECT (clist),
+ clist_signals[SELECT_ROW],
+ row, column, event);
+ clist->anchor = -1;
+ }
+ else
+ clist->anchor = row;
+ break;
+ case GTK_SELECTION_BROWSE:
+ gtk_signal_emit (GTK_OBJECT (clist),
+ clist_signals[SELECT_ROW],
+ row, column, event);
+ break;
+ case GTK_SELECTION_EXTENDED:
+ if (event->type != GDK_BUTTON_PRESS)
+ {
+ if (clist->anchor != -1)
+ {
+ update_extended_selection (clist, clist->focus_row);
+ GTK_CLIST_CLASS_FW (clist)->resync_selection
+ (clist, (GdkEvent *) event);
+ }
+ gtk_signal_emit (GTK_OBJECT (clist),
+ clist_signals[SELECT_ROW],
+ 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 FALSE;
+ }
+
+ /* 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_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
+
+ /* block attached dnd signal handler */
+ drag_data = gtk_object_get_data (GTK_OBJECT (clist), "gtk-site-data");
+ if (drag_data)
+ gtk_signal_handler_block_by_data (GTK_OBJECT (clist), 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_CLIST_ADD_MODE(clist))
+ gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
+ draw_xor_line (clist);
+ }
+ return FALSE;
+}
+
+static gint
+gtk_clist_button_release (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkCList *clist;
+ gint button_actions;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ clist = GTK_CLIST (widget);
+
+ button_actions = clist->button_actions[event->button - 1];
+ if (button_actions == GTK_BUTTON_IGNORED)
+ return FALSE;
+
+ /* release on resize windows */
+ if (GTK_CLIST_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 = gtk_object_get_data (GTK_OBJECT (clist), "gtk-site-data");
+ if (drag_data)
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist), drag_data);
+
+ GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
+ gtk_widget_get_pointer (widget, &x, NULL);
+ gtk_grab_remove (widget);
+ gdk_pointer_ungrab (event->time);
+
+ if (clist->x_drag >= 0)
+ draw_xor_line (clist);
+
+ if (GTK_CLIST_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_clist_set_column_width (clist, i, width);
+ return FALSE;
+ }
+
+ 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_BUTTON_SELECTS)
+ {
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_EXTENDED:
+ 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_CLIST_CLASS_FW (clist)->resync_selection
+ (clist, (GdkEvent *) event);
+ break;
+ case GTK_SELECTION_SINGLE:
+ case GTK_SELECTION_MULTIPLE:
+ 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 FALSE;
+}
+
+static gint
+gtk_clist_motion (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ GtkCList *clist;
+ gint x;
+ gint y;
+ gint row;
+ gint new_width;
+ gint button_actions = 0;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+
+ clist = GTK_CLIST (widget);
+ if (!(gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)))
+ return FALSE;
+
+ if (clist->drag_button > 0)
+ button_actions = clist->button_actions[clist->drag_button - 1];
+
+ if (GTK_CLIST_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_clist_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);
+
+ if (GTK_CLIST_REORDERABLE(clist) && button_actions & GTK_BUTTON_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 = gtk_timeout_add
+ (SCROLL_TIME, (GtkFunction) 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_CLIST_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 = gtk_timeout_add (SCROLL_TIME,
+ (GtkFunction) 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_BUTTON_SELECTS &
+ !gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data"))
+ {
+ if (row == clist->focus_row)
+ return FALSE;
+
+ gtk_clist_draw_focus (widget);
+ clist->focus_row = row;
+ gtk_clist_draw_focus (widget);
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_BROWSE:
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+ clist->focus_row, -1, event);
+ break;
+ case GTK_SELECTION_EXTENDED:
+ 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_clist_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkCList *clist;
+ gint i;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (widget));
+ g_return_if_fail (requisition != NULL);
+
+ clist = GTK_CLIST (widget);
+
+ requisition->width = 0;
+ requisition->height = 0;
+
+ /* compute the size of the column title (title) area */
+ clist->column_title_area.height = 0;
+ if (GTK_CLIST_SHOW_TITLES(clist))
+ 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);
+ }
+
+ requisition->width += (widget->style->klass->xthickness +
+ GTK_CONTAINER (widget)->border_width) * 2;
+ requisition->height += (clist->column_title_area.height +
+ (widget->style->klass->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_clist_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkCList *clist;
+ GtkAllocation clist_allocation;
+ gint border_width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (widget));
+ g_return_if_fail (allocation != NULL);
+
+ clist = GTK_CLIST (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->klass->xthickness);
+ clist_allocation.y = (clist->internal_allocation.y +
+ widget->style->klass->ythickness +
+ clist->column_title_area.height);
+ clist_allocation.width = MAX (1, (gint)clist->internal_allocation.width -
+ (2 * (gint)widget->style->klass->xthickness));
+ clist_allocation.height = MAX (1, (gint)clist->internal_allocation.height -
+ (2 * (gint)widget->style->klass->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->klass->xthickness;
+ clist->column_title_area.y = widget->style->klass->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_clist_forall
+ */
+static void
+gtk_clist_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkCList *clist;
+ guint i;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_CLIST (container));
+ g_return_if_fail (callback != NULL);
+
+ if (!include_internals)
+ return;
+
+ clist = GTK_CLIST (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 (GtkCList *clist,
+ GtkCListRow *clist_row,
+ gint state,
+ gint column,
+ GtkStyle **style,
+ GdkGC **fg_gc,
+ GdkGC **bg_gc)
+{
+ gint fg_state;
+
+ if ((state == GTK_STATE_NORMAL) &&
+ (GTK_WIDGET (clist)->state == GTK_STATE_INSENSITIVE))
+ fg_state = GTK_STATE_INSENSITIVE;
+ else
+ fg_state = state;
+
+ 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_pixmap (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 (GtkCList *clist,
+ GdkRectangle *area,
+ gint row,
+ GtkCListRow *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_ACTIVE],
+ 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_ACTIVE],
+ 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_ACTIVE],
+ 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_ACTIVE],
+ 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;
+
+ gint width;
+ gint height;
+ gint pixmap_width;
+ gint offset = 0;
+ gint row_center_offset;
+
+ 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 */
+ pixmap_width = 0;
+ offset = 0;
+ switch (clist_row->cell[i].type)
+ {
+ case GTK_CELL_TEXT:
+ width = gdk_string_width (style->font,
+ GTK_CELL_TEXT (clist_row->cell[i])->text);
+ break;
+ case GTK_CELL_PIXMAP:
+ gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
+ &pixmap_width, &height);
+ width = pixmap_width;
+ break;
+ case GTK_CELL_PIXTEXT:
+ gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
+ &pixmap_width, &height);
+ width = (pixmap_width +
+ GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing +
+ gdk_string_width (style->font,
+ GTK_CELL_PIXTEXT
+ (clist_row->cell[i])->text));
+ break;
+ default:
+ continue;
+ 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_CELL_PIXMAP:
+ draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
+ GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
+ GTK_CELL_PIXMAP (clist_row->cell[i])->mask,
+ offset,
+ clip_rectangle.y + clist_row->cell[i].vertical +
+ (clip_rectangle.height - height) / 2,
+ pixmap_width, height);
+ break;
+ case GTK_CELL_PIXTEXT:
+ offset =
+ draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
+ GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
+ GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
+ offset,
+ clip_rectangle.y + clist_row->cell[i].vertical+
+ (clip_rectangle.height - height) / 2,
+ pixmap_width, height);
+ offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
+ case GTK_CELL_TEXT:
+ if (style != GTK_WIDGET (clist)->style)
+ row_center_offset = (((clist->row_height - style->font->ascent -
+ style->font->descent - 1) / 2) + 1.5 +
+ style->font->ascent);
+ else
+ row_center_offset = clist->row_center_offset;
+
+ gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
+ gdk_draw_string (clist->clist_window, style->font, fg_gc,
+ offset,
+ row_rectangle.y + row_center_offset +
+ clist_row->cell[i].vertical,
+ (clist_row->cell[i].type == GTK_CELL_PIXTEXT) ?
+ GTK_CELL_PIXTEXT (clist_row->cell[i])->text :
+ GTK_CELL_TEXT (clist_row->cell[i])->text);
+ 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 (GtkCList *clist,
+ GdkRectangle *area)
+{
+ GList *list;
+ GtkCListRow *clist_row;
+ gint i;
+ gint first_row;
+ gint last_row;
+
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (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_CLIST_CLASS_FW (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 (GtkCList *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->klass->ythickness,
+ clist->x_drag,
+ clist->column_title_area.height +
+ clist->clist_window_height + 1);
+}
+
+static void
+clist_refresh (GtkCList *clist)
+{
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
+
+ if (CLIST_UNFROZEN (clist))
+ {
+ adjust_adjustments (clist, FALSE);
+ draw_rows (clist, NULL);
+ }
+}
+
+/* get cell from coordinates
+ * get_selection_info
+ * gtk_clist_get_selection_info
+ */
+static gint
+get_selection_info (GtkCList *clist,
+ gint x,
+ gint y,
+ gint *row,
+ gint *column)
+{
+ gint trow, tcol;
+
+ g_return_val_if_fail (clist != NULL, 0);
+ g_return_val_if_fail (GTK_IS_CLIST (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_clist_get_selection_info (GtkCList *clist,
+ gint x,
+ gint y,
+ gint *row,
+ gint *column)
+{
+ g_return_val_if_fail (clist != NULL, 0);
+ g_return_val_if_fail (GTK_IS_CLIST (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 (GtkCList *clist,
+ gboolean block_resize)
+{
+ if (clist->vadjustment)
+ {
+ clist->vadjustment->page_size = clist->clist_window_height;
+ clist->vadjustment->page_increment = clist->clist_window_height / 2;
+ clist->vadjustment->step_increment = clist->row_height;
+ 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));
+ gtk_signal_emit_by_name (GTK_OBJECT (clist->vadjustment),
+ "value_changed");
+ }
+ gtk_signal_emit_by_name (GTK_OBJECT (clist->vadjustment), "changed");
+ }
+
+ if (clist->hadjustment)
+ {
+ clist->hadjustment->page_size = clist->clist_window_width;
+ clist->hadjustment->page_increment = clist->clist_window_width / 2;
+ clist->hadjustment->step_increment = 10;
+ 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));
+ gtk_signal_emit_by_name (GTK_OBJECT (clist->hadjustment),
+ "value_changed");
+ }
+ gtk_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)
+{
+ GtkCList *clist;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+
+ clist = GTK_CLIST (data);
+}
+
+static void
+hadjustment_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ GtkCList *clist;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+
+ clist = GTK_CLIST (data);
+}
+
+static void
+vadjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ GtkCList *clist;
+ GdkRectangle area;
+ gint diff, value;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+ g_return_if_fail (GTK_IS_CLIST (data));
+
+ clist = GTK_CLIST (data);
+
+ if (!GTK_WIDGET_DRAWABLE (clist) || adjustment != clist->vadjustment)
+ return;
+
+ value = adjustment->value;
+
+ if (value > -clist->voffset)
+ {
+ /* scroll down */
+ diff = value + clist->voffset;
+
+ /* we have to re-draw the whole screen here... */
+ if (diff >= clist->clist_window_height)
+ {
+ clist->voffset = -value;
+ draw_rows (clist, NULL);
+ return;
+ }
+
+ if ((diff != 0) && (diff != clist->clist_window_height))
+ gdk_window_copy_area (clist->clist_window, clist->fg_gc,
+ 0, 0, clist->clist_window, 0, diff,
+ clist->clist_window_width,
+ clist->clist_window_height - diff);
+
+ area.x = 0;
+ area.y = clist->clist_window_height - diff;
+ area.width = clist->clist_window_width;
+ area.height = diff;
+ }
+ else
+ {
+ /* scroll up */
+ diff = -clist->voffset - value;
+
+ /* we have to re-draw the whole screen here... */
+ if (diff >= clist->clist_window_height)
+ {
+ clist->voffset = -value;
+ draw_rows (clist, NULL);
+ return;
+ }
+
+ if ((diff != 0) && (diff != clist->clist_window_height))
+ gdk_window_copy_area (clist->clist_window, clist->fg_gc,
+ 0, diff, clist->clist_window, 0, 0,
+ clist->clist_window_width,
+ clist->clist_window_height - diff);
+
+ area.x = 0;
+ area.y = 0;
+ area.width = clist->clist_window_width;
+ area.height = diff;
+ }
+
+ clist->voffset = -value;
+ if ((diff != 0) && (diff != clist->clist_window_height))
+ check_exposures (clist);
+
+ draw_rows (clist, &area);
+}
+
+static void
+hadjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ GtkCList *clist;
+ GdkRectangle area;
+ gint i;
+ gint y = 0;
+ gint diff = 0;
+ gint value;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+ g_return_if_fail (GTK_IS_CLIST (data));
+
+ clist = GTK_CLIST (data);
+
+ if (!GTK_WIDGET_DRAWABLE (clist) || adjustment != clist->hadjustment)
+ return;
+
+ value = adjustment->value;
+
+ /* move the column buttons and resize windows */
+ for (i = 0; i < clist->columns; i++)
+ {
+ if (clist->column[i].button)
+ {
+ clist->column[i].button->allocation.x -= value + clist->hoffset;
+
+ if (clist->column[i].button->window)
+ {
+ gdk_window_move (clist->column[i].button->window,
+ clist->column[i].button->allocation.x,
+ clist->column[i].button->allocation.y);
+
+ if (clist->column[i].window)
+ gdk_window_move (clist->column[i].window,
+ clist->column[i].button->allocation.x +
+ clist->column[i].button->allocation.width -
+ (DRAG_WIDTH / 2), 0);
+ }
+ }
+ }
+
+ if (value > -clist->hoffset)
+ {
+ /* scroll right */
+ diff = value + clist->hoffset;
+
+ clist->hoffset = -value;
+
+ /* we have to re-draw the whole screen here... */
+ if (diff >= clist->clist_window_width)
+ {
+ draw_rows (clist, NULL);
+ return;
+ }
+
+ if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
+ !GTK_CLIST_CHILD_HAS_FOCUS(clist) && GTK_CLIST_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_copy_area (clist->clist_window,
+ clist->fg_gc,
+ 0, 0,
+ clist->clist_window,
+ diff,
+ 0,
+ clist->clist_window_width - diff,
+ clist->clist_window_height);
+
+ area.x = clist->clist_window_width - diff;
+ }
+ else
+ {
+ /* scroll left */
+ if (!(diff = -clist->hoffset - value))
+ return;
+
+ clist->hoffset = -value;
+
+ /* we have to re-draw the whole screen here... */
+ if (diff >= clist->clist_window_width)
+ {
+ draw_rows (clist, NULL);
+ return;
+ }
+
+ if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
+ !GTK_CLIST_CHILD_HAS_FOCUS(clist) && GTK_CLIST_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_copy_area (clist->clist_window,
+ clist->fg_gc,
+ diff, 0,
+ clist->clist_window,
+ 0,
+ 0,
+ clist->clist_window_width - diff,
+ clist->clist_window_height);
+
+ area.x = 0;
+ }
+
+ area.y = 0;
+ area.width = diff;
+ area.height = clist->clist_window_height;
+
+ check_exposures (clist);
+
+ if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
+ !GTK_CLIST_CHILD_HAS_FOCUS(clist))
+ {
+ if (GTK_CLIST_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
+ {
+ gint x0;
+ gint x1;
+
+ if (area.x == 0)
+ {
+ x0 = clist->clist_window_width - 1;
+ x1 = diff;
}
-
- default:
- if (old_focus_row != clist->focus_row &&
- !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
- GTK_CLIST_ADD_MODE (clist)))
- select_row (clist, clist->focus_row, -1, NULL);
- break;
+ else
+ {
+ x0 = 0;
+ x1 = area.x - 1;
+ }
+
+ 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);
+
}
- 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_clist_moveto (clist, clist->focus_row, -1, 1, 0);
- else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
- gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
- break;
}
+ draw_rows (clist, &area);
}
static void
-set_anchor (GtkCList *clist,
- gboolean add_mode,
- gint anchor,
- gint undo_anchor)
+check_exposures (GtkCList *clist)
{
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
-
- if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor >= 0)
- return;
+ GdkEvent *event;
- g_list_free (clist->undo_selection);
- g_list_free (clist->undo_unselection);
- clist->undo_selection = NULL;
- clist->undo_unselection = NULL;
+ if (!GTK_WIDGET_REALIZED (clist))
+ return;
- if (add_mode)
- fake_toggle_row (clist, anchor);
- else
+ /* Make sure graphics expose events are processed before scrolling
+ * again */
+ while ((event = gdk_event_get_graphics_expose (clist->clist_window)) != NULL)
{
- GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist, anchor);
- clist->anchor_state = GTK_STATE_SELECTED;
+ gtk_widget_event (GTK_WIDGET (clist), event);
+ if (event->expose.count == 0)
+ {
+ gdk_event_free (event);
+ break;
+ }
+ gdk_event_free (event);
}
-
- clist->anchor = anchor;
- clist->drag_pos = anchor;
- clist->undo_anchor = undo_anchor;
}
-static void
-resync_selection (GtkCList *clist,
- GdkEvent *event)
+/* PRIVATE
+ * Memory Allocation/Distruction Routines for GtkCList stuctures
+ *
+ * functions:
+ * columns_new
+ * column_title_new
+ * columns_delete
+ * row_new
+ * row_delete
+ */
+static GtkCListColumn *
+columns_new (GtkCList *clist)
{
+ GtkCListColumn *column;
gint i;
- gint e;
- gint row;
- gboolean thaw = FALSE;
- GList *list;
- GtkCListRow *clist_row;
- if (clist->anchor < 0)
- return;
+ column = g_new (GtkCListColumn, clist->columns);
- if (!GTK_CLIST_FROZEN (clist))
+ for (i = 0; i < clist->columns; i++)
{
- GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
- thaw = TRUE;
+ 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;
}
- 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;
- unselect_row (clist, row, -1, event);
- clist->undo_selection = g_list_prepend
- (clist->undo_selection, GINT_TO_POINTER (row));
- }
- }
- }
- }
-
- for (list = g_list_nth (clist->row_list, i); i <= e; i++, list = list->next)
- if (GTK_CLIST_ROW (list)->selectable)
- {
- if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
- {
- if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
- {
- GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
- unselect_row (clist, i, -1, event);
- clist->undo_selection = g_list_prepend (clist->undo_selection,
- GINT_TO_POINTER (i));
- }
- }
- else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
- {
- GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
- clist->undo_unselection = g_list_prepend (clist->undo_unselection,
- GINT_TO_POINTER (i));
- }
- }
-
- for (list = clist->undo_unselection; list; list = list->next)
- gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
- GPOINTER_TO_INT (list->data), -1, event);
+ return column;
+}
- clist->anchor = -1;
- clist->drag_pos = -1;
+static void
+column_title_new (GtkCList *clist,
+ gint column,
+ const gchar *title)
+{
+ if (clist->column[column].title)
+ g_free (clist->column[column].title);
- if (thaw)
- GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
+ clist->column[column].title = g_strdup (title);
}
static void
-update_extended_selection (GtkCList *clist,
- gint row)
+columns_delete (GtkCList *clist)
{
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_EXTENDED || clist->anchor == -1)
- return;
+ for (i = 0; i < clist->columns; i++)
+ if (clist->column[i].title)
+ g_free (clist->column[i].title);
+
+ g_free (clist->column);
+}
- if (row < 0)
- row = 0;
- if (row >= clist->rows)
- row = clist->rows - 1;
+static GtkCListRow *
+row_new (GtkCList *clist)
+{
+ int i;
+ GtkCListRow *clist_row;
- /* 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)
+ clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
+ clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
+
+ for (i = 0; i < clist->columns; i++)
{
- 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_row->cell[i].type = GTK_CELL_EMPTY;
+ clist_row->cell[i].vertical = 0;
+ clist_row->cell[i].horizontal = 0;
+ clist_row->cell[i].style = NULL;
}
- 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_CLIST_ROW (list)->selectable)
- {
- if (GTK_CLIST_CLASS_FW (clist)->selection_find (clist, i, list))
- GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
- else
- GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
- }
+ 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;
- top = ROW_TOP_YPIXEL (clist, clist->focus_row);
+ return clist_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_clist_moveto (clist, clist->focus_row, -1, 0, 0);
- }
- else if (top >= clist->clist_window_height)
+static void
+row_delete (GtkCList *clist,
+ GtkCListRow *clist_row)
+{
+ gint i;
+
+ for (i = 0; i < clist->columns; i++)
+ {
+ GTK_CLIST_CLASS_FW (clist)->set_cell_contents
+ (clist, clist_row, i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
+ if (clist_row->cell[i].style)
{
- area.y = ROW_TOP_YPIXEL (clist, s1);
- area.height = clist->clist_window_height - area.y;
- draw_rows (clist, &area);
- gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+ if (GTK_WIDGET_REALIZED (clist))
+ gtk_style_detach (clist_row->cell[i].style);
+ gtk_style_unref (clist_row->cell[i].style);
}
- else if (top < 0)
- gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
- else if (top + clist->row_height > clist->clist_window_height)
- gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
-
- y1 = ROW_TOP_YPIXEL (clist, s1);
- h1 = (e1 - s1 + 1) * (clist->row_height + CELL_SPACING);
}
- /* extend the selection between s2 and e2 */
- if (s2 >= 0)
+ if (clist_row->style)
{
- for (i = s2, list = g_list_nth (clist->row_list, i); i <= e2;
- i++, list = list->next)
- if (GTK_CLIST_ROW (list)->selectable &&
- GTK_CLIST_ROW (list)->state != clist->anchor_state)
- GTK_CLIST_ROW (list)->state = clist->anchor_state;
+ if (GTK_WIDGET_REALIZED (clist))
+ gtk_style_detach (clist_row->style);
+ gtk_style_unref (clist_row->style);
+ }
- top = ROW_TOP_YPIXEL (clist, clist->focus_row);
+ if (clist_row->destroy)
+ clist_row->destroy (clist_row->data);
- if (top + clist->row_height <= 0)
+ g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
+ g_mem_chunk_free (clist->row_mem_chunk, clist_row);
+}
+
+/* FOCUS FUNCTIONS
+ * gtk_clist_focus
+ * gtk_clist_draw_focus
+ * gtk_clist_focus_in
+ * gtk_clist_focus_out
+ * gtk_clist_set_focus_child
+ * title_focus
+ */
+static gint
+gtk_clist_focus (GtkContainer *container,
+ GtkDirectionType direction)
+{
+ GtkCList *clist;
+ GtkWidget *focus_child;
+ gint old_row;
+
+ g_return_val_if_fail (container != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CLIST (container), FALSE);
+
+ if (!GTK_WIDGET_IS_SENSITIVE (container))
+ return FALSE;
+
+ clist = GTK_CLIST (container);
+ focus_child = container->focus_child;
+ old_row = clist->focus_row;
+
+ switch (direction)
+ {
+ case GTK_DIR_LEFT:
+ case GTK_DIR_RIGHT:
+ if (GTK_CLIST_CHILD_HAS_FOCUS(clist))
{
- area.y = 0;
- area.height = ROW_TOP_YPIXEL (clist, e2) + clist->row_height;
- draw_rows (clist, &area);
- gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
- }
- else if (top >= clist->clist_window_height)
+ if (title_focus (clist, direction))
+ return TRUE;
+ gtk_container_set_focus_child (container, NULL);
+ return FALSE;
+ }
+ gtk_widget_grab_focus (GTK_WIDGET (container));
+ return TRUE;
+ case GTK_DIR_DOWN:
+ case GTK_DIR_TAB_FORWARD:
+ if (GTK_CLIST_CHILD_HAS_FOCUS(clist))
{
- area.y = ROW_TOP_YPIXEL (clist, s2);
- area.height = clist->clist_window_height - area.y;
- draw_rows (clist, &area);
- gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
- }
- else if (top < 0)
- gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
- else if (top + clist->row_height > clist->clist_window_height)
- gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+ gboolean tf = FALSE;
- y2 = ROW_TOP_YPIXEL (clist, s2);
- h2 = (e2 - s2 + 1) * (clist->row_height + CELL_SPACING);
- }
+ if (((focus_child && direction == GTK_DIR_DOWN) ||
+ !(tf = title_focus (clist, GTK_DIR_TAB_FORWARD)))
+ && clist->rows)
+ {
+ if (clist->focus_row < 0)
+ {
+ clist->focus_row = 0;
- 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);
-}
+ if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
+ clist->selection_mode == GTK_SELECTION_EXTENDED) &&
+ !clist->selection)
+ gtk_signal_emit (GTK_OBJECT (clist),
+ clist_signals[SELECT_ROW],
+ clist->focus_row, -1, NULL);
+ }
+ gtk_widget_grab_focus (GTK_WIDGET (container));
+ return TRUE;
+ }
-static void
-start_selection (GtkCList *clist)
-{
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ if (tf)
+ return TRUE;
+ }
+
+ GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
+ break;
+ case GTK_DIR_UP:
+ case GTK_DIR_TAB_BACKWARD:
+ if (!focus_child &&
+ GTK_CLIST_CHILD_HAS_FOCUS(clist) && clist->rows)
+ {
+ if (clist->focus_row < 0)
+ {
+ clist->focus_row = 0;
+ if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
+ clist->selection_mode == GTK_SELECTION_EXTENDED) &&
+ !clist->selection)
+ gtk_signal_emit (GTK_OBJECT (clist),
+ clist_signals[SELECT_ROW],
+ clist->focus_row, -1, NULL);
+ }
+ gtk_widget_grab_focus (GTK_WIDGET (container));
+ return TRUE;
+ }
- if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
- return;
+ GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
- set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
- clist->focus_row);
-}
+ if (title_focus (clist, direction))
+ return TRUE;
-static void
-end_selection (GtkCList *clist)
-{
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ break;
+ default:
+ break;
+ }
- if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)) ||
- clist->anchor == -1)
- return;
-
- GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+ gtk_container_set_focus_child (container, NULL);
+ return FALSE;
}
static void
-extend_selection (GtkCList *clist,
- GtkScrollType scroll_type,
- gfloat position,
- gboolean auto_start_selection)
+gtk_clist_draw_focus (GtkWidget *widget)
{
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ GtkCList *clist;
- if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
- clist->selection_mode != GTK_SELECTION_EXTENDED)
- return;
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (widget));
- if (auto_start_selection)
- set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
- clist->focus_row);
- else if (clist->anchor == -1)
+ if (!GTK_WIDGET_DRAWABLE (widget) || !GTK_WIDGET_CAN_FOCUS (widget))
return;
- move_focus_row (clist, scroll_type, position);
-
- if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
- clist->clist_window_height)
- gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
- else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
- gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
-
- update_extended_selection (clist, clist->focus_row);
+ clist = GTK_CLIST (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 void
-abort_column_resize (GtkCList *clist)
+static gint
+gtk_clist_focus_in (GtkWidget *widget,
+ GdkEventFocus *event)
{
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ GtkCList *clist;
- if (!GTK_CLIST_IN_DRAG (clist))
- return;
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
- GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
- gtk_grab_remove (GTK_WIDGET (clist));
- gdk_pointer_ungrab (GDK_CURRENT_TIME);
- clist->drag_pos = -1;
+ GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
+ GTK_CLIST_UNSET_FLAG (widget, CLIST_CHILD_HAS_FOCUS);
- if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
- draw_xor_line (clist);
+ clist = GTK_CLIST (widget);
- if (GTK_CLIST_ADD_MODE (clist))
+ if (clist->selection_mode == GTK_SELECTION_BROWSE &&
+ clist->selection == NULL && clist->focus_row > -1)
{
- 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);
+ GList *list;
+
+ list = g_list_nth (clist->row_list, clist->focus_row);
+ if (list && GTK_CLIST_ROW (list)->selectable)
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+ clist->focus_row, -1, event);
+ else
+ gtk_widget_draw_focus (widget);
}
+ else
+ gtk_widget_draw_focus (widget);
+
+ return FALSE;
}
static gint
-gtk_clist_key_press (GtkWidget * widget,
- GdkEventKey * event)
+gtk_clist_focus_out (GtkWidget *widget,
+ GdkEventFocus *event)
{
+ GtkCList *clist;
+
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
- if (GTK_WIDGET_CLASS (parent_class)->key_press_event &&
- GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event))
- return TRUE;
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
+ GTK_CLIST_SET_FLAG (widget, CLIST_CHILD_HAS_FOCUS);
- switch (event->keyval)
- {
- case GDK_Tab:
- case GDK_ISO_Left_Tab:
- if (event->state & GDK_SHIFT_MASK)
- return gtk_container_focus (GTK_CONTAINER (widget),
- GTK_DIR_TAB_BACKWARD);
- else
- return gtk_container_focus (GTK_CONTAINER (widget),
- GTK_DIR_TAB_FORWARD);
+ gtk_widget_draw_focus (widget);
+
+ clist = GTK_CLIST (widget);
- default:
- break;
+ GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, (GdkEvent *) event);
+
+ return FALSE;
+}
+
+static void
+gtk_clist_set_focus_child (GtkContainer *container,
+ GtkWidget *child)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_CLIST (container));
+
+ if (child)
+ {
+ g_return_if_fail (GTK_IS_WIDGET (child));
+ GTK_CLIST_SET_FLAG (container, CLIST_CHILD_HAS_FOCUS);
}
-
- return FALSE;
+
+ parent_class->set_focus_child (container, child);
}
static gboolean
-title_focus (GtkCList * clist,
- gint dir)
+title_focus (GtkCList *clist,
+ gint dir)
{
GtkWidget *focus_child;
gboolean return_val = FALSE;
+ gint last_column;
gint d = 1;
gint i = 0;
gint j;
- if (!GTK_CLIST_SHOW_TITLES (clist))
+ if (!GTK_CLIST_SHOW_TITLES(clist))
return FALSE;
focus_child = GTK_CONTAINER (clist)->focus_child;
+
+ for (last_column = clist->columns - 1;
+ last_column >= 0 && !clist->column[last_column].visible; last_column--)
+ ;
switch (dir)
{
case GTK_DIR_TAB_BACKWARD:
case GTK_DIR_UP:
- if (!focus_child || focus_child == clist->hscrollbar ||
- focus_child == clist->hscrollbar ||
- !GTK_CLIST_CHILD_HAS_FOCUS (clist))
+ if (!focus_child || !GTK_CLIST_CHILD_HAS_FOCUS(clist))
{
if (dir == GTK_DIR_UP)
i = COLUMN_FROM_XPIXEL (clist, 0);
else
- i = clist->columns - 1;
+ i = last_column;
focus_child = clist->column[i].button;
dir = GTK_DIR_TAB_FORWARD;
}
break;
case GTK_DIR_LEFT:
d = -1;
- if (!focus_child || focus_child == clist->hscrollbar ||
- focus_child == clist->hscrollbar)
+ if (!focus_child)
{
- i = clist->columns - 1;
+ i = last_column;
focus_child = clist->column[i].button;
}
break;
case GTK_DIR_RIGHT:
- if (!focus_child || focus_child == clist->hscrollbar ||
- focus_child == clist->hscrollbar)
+ if (!focus_child)
{
i = 0;
focus_child = clist->column[i].button;
if (clist->column[i].button &&
GTK_WIDGET_VISIBLE (clist->column[i].button) &&
GTK_IS_CONTAINER (clist->column[i].button) &&
- !GTK_WIDGET_HAS_FOCUS (clist->column[i].button))
+ !GTK_WIDGET_HAS_FOCUS(clist->column[i].button))
if (gtk_container_focus
(GTK_CONTAINER (clist->column[i].button), dir))
{
else if (COLUMN_LEFT_XPIXEL(clist, j) + clist->column[j].area.width >
clist->clist_window_width)
{
- if (j == clist->columns-1)
+ if (j == last_column)
gtk_clist_moveto (clist, -1, j, 0, 0);
else
gtk_clist_moveto (clist, -1, j, 0, 1);
return return_val;
}
-static gint
-gtk_clist_focus (GtkContainer * container,
- GtkDirectionType direction)
+/* 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 (GtkCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position)
{
- GtkCList *clist;
- GtkWidget *focus_child;
- gint old_row;
+ GtkWidget *widget;
- g_return_val_if_fail (container != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_CLIST (container), FALSE);
+ g_return_if_fail (clist != 0);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- if (!GTK_WIDGET_SENSITIVE (container))
- return FALSE;
-
- clist = GTK_CLIST (container);
- focus_child = container->focus_child;
- old_row = clist->focus_row;
+ widget = GTK_WIDGET (clist);
- switch (direction)
+ switch (scroll_type)
{
- case GTK_DIR_LEFT:
- case GTK_DIR_RIGHT:
- if (GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
- (!focus_child || (focus_child && focus_child != clist->vscrollbar &&
- focus_child != clist->hscrollbar)))
- {
- if (title_focus (clist, direction))
- return TRUE;
- gtk_container_set_focus_child (container, NULL);
- return FALSE;
- }
- gtk_widget_grab_focus (GTK_WIDGET (container));
- return TRUE;
- case GTK_DIR_DOWN:
- case GTK_DIR_TAB_FORWARD:
- if (GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
- (!focus_child || (focus_child != clist->vscrollbar &&
- focus_child != clist->hscrollbar)))
+ case GTK_SCROLL_STEP_BACKWARD:
+ if (clist->focus_row <= 0)
+ return;
+ gtk_clist_draw_focus (widget);
+ clist->focus_row--;
+ gtk_clist_draw_focus (widget);
+ break;
+ case GTK_SCROLL_STEP_FORWARD:
+ if (clist->focus_row >= clist->rows - 1)
+ return;
+ gtk_clist_draw_focus (widget);
+ clist->focus_row++;
+ gtk_clist_draw_focus (widget);
+ break;
+ case GTK_SCROLL_PAGE_BACKWARD:
+ if (clist->focus_row <= 0)
+ return;
+ gtk_clist_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_clist_draw_focus (widget);
+ break;
+ case GTK_SCROLL_PAGE_FORWARD:
+ if (clist->focus_row >= clist->rows - 1)
+ return;
+ gtk_clist_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_clist_draw_focus (widget);
+ break;
+ case GTK_SCROLL_JUMP:
+ if (position >= 0 && position <= 1)
{
- gboolean tf = FALSE;
+ gtk_clist_draw_focus (widget);
+ clist->focus_row = position * (clist->rows - 1);
+ gtk_clist_draw_focus (widget);
+ }
+ break;
+ default:
+ break;
+ }
+}
- if (((focus_child && direction == GTK_DIR_DOWN) ||
- !(tf = title_focus (clist, GTK_DIR_TAB_FORWARD)))
- && clist->rows)
- {
- if (clist->focus_row < 0)
- {
- clist->focus_row = 0;
+static void
+scroll_horizontal (GtkCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position)
+{
+ gint column = 0;
+ gint last_column;
- if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
- clist->selection_mode == GTK_SELECTION_EXTENDED) &&
- !clist->selection)
- select_row (clist, clist->focus_row, -1, NULL);
- }
- gtk_widget_grab_focus (GTK_WIDGET (container));
- return TRUE;
- }
+ g_return_if_fail (clist != 0);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- if (tf)
- return TRUE;
- }
-
- GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
+ if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+ return;
- if ((!GTK_CLIST_CHILD_HAS_FOCUS (clist) || !focus_child ||
- (focus_child != clist->vscrollbar &&
- focus_child != clist->hscrollbar)) &&
- GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
- GTK_WIDGET_CAN_FOCUS (clist->vscrollbar))
- {
- gtk_widget_grab_focus (clist->vscrollbar);
- return TRUE;
- }
+ for (last_column = clist->columns - 1;
+ last_column >= 0 && !clist->column[last_column].visible; last_column--)
+ ;
- if ((!GTK_CLIST_CHILD_HAS_FOCUS (clist) || !focus_child ||
- focus_child != clist->hscrollbar) &&
- GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
- GTK_WIDGET_CAN_FOCUS (clist->hscrollbar))
- {
- gtk_widget_grab_focus (clist->hscrollbar);
- return TRUE;
- }
+ 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_DIR_UP:
- case GTK_DIR_TAB_BACKWARD:
- if (!focus_child && GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
- GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
- GTK_WIDGET_CAN_FOCUS (clist->hscrollbar))
+ 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)
{
- gtk_widget_grab_focus (clist->hscrollbar);
- return TRUE;
+ 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;
}
-
- if ((!focus_child || focus_child == clist->hscrollbar) &&
- GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
- GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
- GTK_WIDGET_CAN_FOCUS (clist->vscrollbar))
+ else
+ return;
+ break;
+ default:
+ break;
+ }
+
+ if (COLUMN_LEFT_XPIXEL (clist, column) < CELL_SPACING + COLUMN_INSET)
+ gtk_clist_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_clist_moveto (clist, -1, column, 0, 0);
+ else
+ gtk_clist_moveto (clist, -1, column, 0, 1);
+ }
+}
+
+static void
+scroll_vertical (GtkCList *clist,
+ GtkScrollType scroll_type,
+ gfloat position)
+{
+ gint old_focus_row;
+
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
+
+ if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+ return;
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_EXTENDED:
+ 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)
{
- gtk_widget_grab_focus (clist->vscrollbar);
- return TRUE;
+ if (clist->selection_mode == GTK_SELECTION_BROWSE)
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
+ old_focus_row, -1, NULL);
+ else if (!GTK_CLIST_ADD_MODE(clist))
+ {
+ gtk_clist_unselect_all (clist);
+ clist->undo_anchor = old_focus_row;
+ }
}
- if ((!focus_child || focus_child == clist->hscrollbar ||
- focus_child == clist->vscrollbar) &&
- GTK_CLIST_CHILD_HAS_FOCUS (clist) && clist->rows)
+ switch (gtk_clist_row_is_visible (clist, clist->focus_row))
{
- if (clist->focus_row < 0)
+ case GTK_VISIBILITY_NONE:
+ if (old_focus_row != clist->focus_row &&
+ !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
+ GTK_CLIST_ADD_MODE(clist)))
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+ clist->focus_row, -1, NULL);
+ switch (scroll_type)
{
- clist->focus_row = 0;
- if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
- clist->selection_mode == GTK_SELECTION_EXTENDED) &&
- !clist->selection)
- select_row (clist, clist->focus_row, -1, NULL);
+ case GTK_SCROLL_STEP_BACKWARD:
+ case GTK_SCROLL_PAGE_BACKWARD:
+ gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+ break;
+ case GTK_SCROLL_STEP_FORWARD:
+ case GTK_SCROLL_PAGE_FORWARD:
+ gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+ break;
+ case GTK_SCROLL_JUMP:
+ gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
+ break;
+ default:
+ break;
}
- gtk_widget_grab_focus (GTK_WIDGET (container));
- return TRUE;
+ break;
+ case GTK_VISIBILITY_PARTIAL:
+ switch (scroll_type)
+ {
+ case GTK_SCROLL_STEP_BACKWARD:
+ case GTK_SCROLL_PAGE_BACKWARD:
+ gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+ break;
+ case GTK_SCROLL_STEP_FORWARD:
+ case GTK_SCROLL_PAGE_FORWARD:
+ gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+ break;
+ case GTK_SCROLL_JUMP:
+ gtk_clist_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_EXTENDED &&
+ GTK_CLIST_ADD_MODE(clist)))
+ gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+ clist->focus_row, -1, NULL);
+ break;
}
-
- GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
-
- if (title_focus (clist, direction))
- return TRUE;
-
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_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+ else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+ gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
break;
}
-
- gtk_container_set_focus_child (container, NULL);
- return FALSE;
}
-void
-gtk_clist_unselect_all (GtkCList * clist)
+static void
+move_horizontal (GtkCList *clist,
+ gint diff)
{
- GTK_CLIST_CLASS_FW (clist)->unselect_all (clist);
+ gfloat 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
-real_unselect_all (GtkCList * clist)
+move_vertical (GtkCList *clist,
+ gint row,
+ gfloat align)
{
- GList *list;
- gint i;
-
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ gfloat value;
- if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+ if (!clist->vadjustment)
return;
- switch (clist->selection_mode)
- {
- case GTK_SELECTION_BROWSE:
- if (clist->focus_row >= 0)
- {
- select_row (clist, clist->focus_row, -1, NULL);
- return;
- }
- break;
+ value = (ROW_TOP_YPIXEL (clist, row) - clist->voffset -
+ align * (clist->clist_window_height - clist->row_height) +
+ (2 * align - 1) * CELL_SPACING);
- case GTK_SELECTION_EXTENDED:
- g_list_free (clist->undo_selection);
- g_list_free (clist->undo_unselection);
- clist->undo_selection = NULL;
- clist->undo_unselection = NULL;
+ if (value + clist->vadjustment->page_size > clist->vadjustment->upper)
+ value = clist->vadjustment->upper - clist->vadjustment->page_size;
- clist->anchor = -1;
- clist->drag_pos = -1;
- clist->undo_anchor = clist->focus_row;
- break;
+ gtk_adjustment_set_value(clist->vadjustment, value);
+}
- default:
- break;
- }
+static gint
+horizontal_timeout (GtkCList *clist)
+{
+ GdkEventMotion event = { 0 };
- list = clist->selection;
+ GDK_THREADS_ENTER ();
- while (list)
- {
- i = GPOINTER_TO_INT (list->data);
- list = list->next;
- unselect_row (clist, i, -1, NULL);
- }
-}
+ clist->htimer = 0;
-void
-gtk_clist_select_all (GtkCList * clist)
-{
- GTK_CLIST_CLASS_FW (clist)->select_all (clist);
+ event.type = GDK_MOTION_NOTIFY;
+ event.send_event = TRUE;
+
+ gtk_clist_motion (GTK_WIDGET (clist), &event);
+
+ GDK_THREADS_LEAVE ();
+
+ return FALSE;
}
-static void
-real_select_all (GtkCList * clist)
+static gint
+vertical_timeout (GtkCList *clist)
{
- GList *list;
- gint i;
-
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ GdkEventMotion event = { 0 };
- if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
- return;
+ GDK_THREADS_ENTER ();
- switch (clist->selection_mode)
- {
- case GTK_SELECTION_SINGLE:
- case GTK_SELECTION_BROWSE:
- return;
+ clist->vtimer = 0;
- case GTK_SELECTION_EXTENDED:
- g_list_free (clist->undo_selection);
- g_list_free (clist->undo_unselection);
- clist->undo_selection = NULL;
- clist->undo_unselection = NULL;
-
- if (clist->rows &&
- ((GtkCListRow *) (clist->row_list->data))->state !=
- GTK_STATE_SELECTED)
- fake_toggle_row (clist, 0);
+ event.type = GDK_MOTION_NOTIFY;
+ event.send_event = TRUE;
- 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_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
- return;
+ gtk_clist_motion (GTK_WIDGET (clist), &event);
- case GTK_SELECTION_MULTIPLE:
- for (i = 0, list = clist->row_list; list; i++, list = list->next)
- {
- if (((GtkCListRow *)(list->data))->state == GTK_STATE_NORMAL)
- gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
- i, -1, NULL);
- }
- return;
- }
+ GDK_THREADS_LEAVE ();
+
+ return FALSE;
}
static void
-fake_unselect_all (GtkCList * clist,
- gint row)
+remove_grab (GtkCList *clist)
{
- GList *list;
- GList *work;
- gint i;
-
- if (row >= 0 && (work = g_list_nth (clist->row_list, row)))
+ if (GTK_WIDGET_HAS_GRAB (clist))
{
- if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL &&
- GTK_CLIST_ROW (work)->selectable)
- {
- GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
-
- if (!GTK_CLIST_FROZEN (clist) &&
- gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
- GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
- GTK_CLIST_ROW (work));
- }
+ gtk_grab_remove (GTK_WIDGET (clist));
+ if (gdk_pointer_is_grabbed ())
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
}
- clist->undo_selection = clist->selection;
- clist->selection = NULL;
- clist->selection_end = NULL;
-
- for (list = clist->undo_selection; list; list = list->next)
+ if (clist->htimer)
{
- if ((i = GPOINTER_TO_INT (list->data)) == row ||
- !(work = g_list_nth (clist->row_list, i)))
- continue;
+ gtk_timeout_remove (clist->htimer);
+ clist->htimer = 0;
+ }
- GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
- if (!GTK_CLIST_FROZEN (clist) &&
- gtk_clist_row_is_visible (clist, i) != GTK_VISIBILITY_NONE)
- GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, i,
- GTK_CLIST_ROW (work));
+ if (clist->vtimer)
+ {
+ gtk_timeout_remove (clist->vtimer);
+ clist->vtimer = 0;
}
}
-static void
-fake_toggle_row (GtkCList *clist,
- gint row)
+/* PUBLIC SORTING FUNCTIONS
+ * gtk_clist_sort
+ * gtk_clist_set_compare_func
+ * gtk_clist_set_auto_sort
+ * gtk_clist_set_sort_type
+ * gtk_clist_set_sort_column
+ */
+void
+gtk_clist_sort (GtkCList *clist)
{
- GList *work;
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- if (!(work = g_list_nth (clist->row_list, row))||
- !GTK_CLIST_ROW (work)->selectable)
- return;
+ GTK_CLIST_CLASS_FW (clist)->sort_list (clist);
+}
+
+void
+gtk_clist_set_compare_func (GtkCList *clist,
+ GtkCListCompareFunc cmp_func)
+{
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
+
+ clist->compare = (cmp_func) ? cmp_func : default_compare;
+}
+
+void
+gtk_clist_set_auto_sort (GtkCList *clist,
+ gboolean auto_sort)
+{
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
- clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
- else
- clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
+ if (GTK_CLIST_AUTO_SORT(clist) && !auto_sort)
+ GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_SORT);
+ else if (!GTK_CLIST_AUTO_SORT(clist) && auto_sort)
+ {
+ GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_SORT);
+ gtk_clist_sort (clist);
+ }
+}
+
+void
+gtk_clist_set_sort_type (GtkCList *clist,
+ GtkSortType sort_type)
+{
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- if (!GTK_CLIST_FROZEN (clist) &&
- gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
- GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
- GTK_CLIST_ROW (work));
+ clist->sort_type = sort_type;
}
-static GList *
-selection_find (GtkCList *clist,
- gint row_number,
- GList *row_list_element)
+void
+gtk_clist_set_sort_column (GtkCList *clist,
+ gint column)
{
- return g_list_find (clist->selection, GINT_TO_POINTER (row_number));
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
+
+ if (column < 0 || column >= clist->columns)
+ return;
+
+ clist->sort_column = column;
}
+/* PRIVATE SORTING FUNCTIONS
+ * default_compare
+ * real_sort_list
+ * gtk_clist_merge
+ * gtk_clist_mergesort
+ */
static gint
-default_compare (GtkCList *clist,
- gconstpointer ptr1,
- gconstpointer ptr2)
+default_compare (GtkCList *clist,
+ gconstpointer ptr1,
+ gconstpointer ptr2)
{
char *text1 = NULL;
char *text2 = NULL;
return strcmp (text1, text2);
}
-void
-gtk_clist_set_compare_func (GtkCList *clist,
- GtkCListCompareFunc cmp_func)
+static void
+real_sort_list (GtkCList *clist)
{
+ GList *list;
+ GList *work;
+ gint i;
+
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- clist->compare = (cmp_func) ? cmp_func : default_compare;
-}
+ if (clist->rows <= 1)
+ return;
-void
-gtk_clist_set_auto_sort (GtkCList *clist,
- gboolean auto_sort)
-{
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
-
- if (GTK_CLIST_AUTO_SORT (clist) && !auto_sort)
- GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_SORT);
- else if (!GTK_CLIST_AUTO_SORT (clist) && auto_sort)
+ if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+ return;
+
+ gtk_clist_freeze (clist);
+
+ if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
{
- GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_SORT);
- gtk_clist_sort (clist);
+ GTK_CLIST_CLASS_FW (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;
}
-}
-
-void
-gtk_clist_set_sort_type (GtkCList *clist,
- GtkSortType sort_type)
-{
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
-
- clist->sort_type = sort_type;
-}
+
+ clist->row_list = gtk_clist_mergesort (clist, clist->row_list, clist->rows);
-void
-gtk_clist_set_sort_column (GtkCList *clist,
- gint column)
-{
- g_return_if_fail (clist != NULL);
- g_return_if_fail (GTK_IS_CLIST (clist));
+ work = clist->selection;
- if (column < 0 || column >= clist->columns)
- return;
+ for (i = 0, list = clist->row_list; i < clist->rows; i++, list = list->next)
+ {
+ if (GTK_CLIST_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;
+ }
- clist->sort_column = column;
+ gtk_clist_thaw (clist);
}
static GList *
}
}
-void
-gtk_clist_sort (GtkCList *clist)
+/************************/
+
+static void
+drag_source_info_destroy (gpointer data)
{
- GTK_CLIST_CLASS_FW (clist)->sort_list (clist);
+ GtkCListCellInfo *info = data;
+
+ g_free (info);
}
static void
-real_sort_list (GtkCList *clist)
+drag_dest_info_destroy (gpointer data)
{
- GList *list;
- GList *work;
- gint i;
- gboolean thaw = FALSE;
+ GtkCListDestInfo *info = data;
+
+ g_free (info);
+}
+
+static void
+drag_dest_cell (GtkCList *clist,
+ gint x,
+ gint y,
+ GtkCListDestInfo *dest_info)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (clist);
+
+ dest_info->insert_pos = GTK_CLIST_DRAG_NONE;
+
+ y -= (GTK_CONTAINER (clist)->border_width +
+ widget->style->klass->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->klass->xthickness;
+ dest_info->cell.column = COLUMN_FROM_XPIXEL (clist, x);
+
+ if (dest_info->cell.row >= 0)
+ {
+ gint y_delta;
+ gint h = 0;
+
+ y_delta = y - ROW_TOP_YPIXEL (clist, dest_info->cell.row);
+
+ if (GTK_CLIST_DRAW_DRAG_RECT(clist))
+ {
+ dest_info->insert_pos = GTK_CLIST_DRAG_INTO;
+ h = clist->row_height / 4;
+ }
+ else if (GTK_CLIST_DRAW_DRAG_LINE(clist))
+ {
+ dest_info->insert_pos = GTK_CLIST_DRAG_BEFORE;
+ h = clist->row_height / 2;
+ }
+
+ if (GTK_CLIST_DRAW_DRAG_LINE(clist))
+ {
+ if (y_delta < h)
+ dest_info->insert_pos = GTK_CLIST_DRAG_BEFORE;
+ else if (clist->row_height - y_delta < h)
+ dest_info->insert_pos = GTK_CLIST_DRAG_AFTER;
+ }
+ }
+}
+
+static void
+gtk_clist_drag_begin (GtkWidget *widget,
+ GdkDragContext *context)
+{
+ GtkCList *clist;
+ GtkCListCellInfo *info;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (widget));
+ g_return_if_fail (context != NULL);
+
+ clist = GTK_CLIST (widget);
+
+ clist->drag_button = 0;
+ remove_grab (clist);
+
+ switch (clist->selection_mode)
+ {
+ case GTK_SELECTION_EXTENDED:
+ update_extended_selection (clist, clist->focus_row);
+ GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+ break;
+ case GTK_SELECTION_SINGLE:
+ case GTK_SELECTION_MULTIPLE:
+ clist->anchor = -1;
+ case GTK_SELECTION_BROWSE:
+ break;
+ }
+
+ info = g_dataset_get_data (context, "gtk-clist-drag-source");
+
+ if (!info)
+ {
+ info = g_new (GtkCListCellInfo, 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_CLIST_USE_DRAG_ICONS (clist))
+ gtk_drag_set_icon_default (context);
+}
+
+static void
+gtk_clist_drag_end (GtkWidget *widget,
+ GdkDragContext *context)
+{
+ GtkCList *clist;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (widget));
+ g_return_if_fail (context != NULL);
+
+ clist = GTK_CLIST (widget);
+
+ clist->click_cell.row = -1;
+ clist->click_cell.column = -1;
+}
+
+static void
+gtk_clist_drag_leave (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time)
+{
+ GtkCList *clist;
+ GtkCListDestInfo *dest_info;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (widget));
+ g_return_if_fail (context != NULL);
+
+ clist = GTK_CLIST (widget);
+
+ dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+
+ if (dest_info)
+ {
+ if (dest_info->cell.row >= 0 &&
+ GTK_CLIST_REORDERABLE(clist) &&
+ gtk_drag_get_source_widget (context) == widget)
+ {
+ GList *list;
+ GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
+
+ list = context->targets;
+ while (list)
+ {
+ if (atom == GPOINTER_TO_INT (list->data))
+ {
+ GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
+ (clist,
+ g_list_nth (clist->row_list, dest_info->cell.row)->data,
+ dest_info->cell.row, dest_info->insert_pos);
+ break;
+ }
+ list = list->next;
+ }
+ }
+ g_dataset_remove_data (context, "gtk-clist-drag-dest");
+ }
+}
+
+static gint
+gtk_clist_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time)
+{
+ GtkCList *clist;
+ GtkCListDestInfo new_info;
+ GtkCListDestInfo *dest_info;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+
+ clist = GTK_CLIST (widget);
+
+ dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+
+ if (!dest_info)
+ {
+ dest_info = g_new (GtkCListDestInfo, 1);
+
+ dest_info->insert_pos = GTK_CLIST_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_CLIST_REORDERABLE (clist))
+ {
+ GList *list;
+ GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
+
+ list = context->targets;
+ while (list)
+ {
+ if (atom == GPOINTER_TO_INT (list->data))
+ break;
+ list = list->next;
+ }
+
+ if (list)
+ {
+ if (gtk_drag_get_source_widget (context) != widget ||
+ new_info.insert_pos == GTK_CLIST_DRAG_NONE ||
+ new_info.cell.row == clist->click_cell.row ||
+ (new_info.cell.row == clist->click_cell.row - 1 &&
+ new_info.insert_pos == GTK_CLIST_DRAG_AFTER) ||
+ (new_info.cell.row == clist->click_cell.row + 1 &&
+ new_info.insert_pos == GTK_CLIST_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_CLIST_CLASS_FW (clist)->draw_drag_highlight
+ (clist, g_list_nth (clist->row_list,
+ dest_info->cell.row)->data,
+ dest_info->cell.row, dest_info->insert_pos);
+
+ dest_info->insert_pos = new_info.insert_pos;
+ dest_info->cell.row = new_info.cell.row;
+ dest_info->cell.column = new_info.cell.column;
+
+ GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
+ (clist, g_list_nth (clist->row_list,
+ dest_info->cell.row)->data,
+ dest_info->cell.row, 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_clist_drag_drop (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+ g_return_val_if_fail (context != NULL, FALSE);
+
+ if (GTK_CLIST_REORDERABLE (widget) &&
+ gtk_drag_get_source_widget (context) == widget)
+ {
+ GList *list;
+ GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
+
+ list = context->targets;
+ while (list)
+ {
+ if (atom == GPOINTER_TO_INT (list->data))
+ return TRUE;
+ list = list->next;
+ }
+ }
+ return FALSE;
+}
+
+static void
+gtk_clist_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time)
+{
+ GtkCList *clist;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (widget));
+ g_return_if_fail (context != NULL);
+ g_return_if_fail (selection_data != NULL);
+
+ clist = GTK_CLIST (widget);
+
+ if (GTK_CLIST_REORDERABLE (clist) &&
+ gtk_drag_get_source_widget (context) == widget &&
+ selection_data->target ==
+ gdk_atom_intern ("gtk-clist-drag-reorder", FALSE) &&
+ selection_data->format == GTK_TYPE_POINTER &&
+ selection_data->length == sizeof (GtkCListCellInfo))
+ {
+ GtkCListCellInfo *source_info;
+
+ source_info = (GtkCListCellInfo *)(selection_data->data);
+ if (source_info)
+ {
+ GtkCListDestInfo dest_info;
+
+ drag_dest_cell (clist, x, y, &dest_info);
+
+ if (dest_info.insert_pos == GTK_CLIST_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_clist_row_move (clist, source_info->row, dest_info.cell.row);
+
+ g_dataset_remove_data (context, "gtk-clist-drag-dest");
+ }
+ }
+}
+
+static void
+gtk_clist_drag_data_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CLIST (widget));
+ g_return_if_fail (context != NULL);
+ g_return_if_fail (selection_data != NULL);
+
+ if (selection_data->target ==
+ gdk_atom_intern ("gtk-clist-drag-reorder", FALSE))
+ {
+ GtkCListCellInfo *info;
+
+ info = g_dataset_get_data (context, "gtk-clist-drag-source");
+
+ if (info)
+ {
+ GtkCListCellInfo ret_info;
+
+ ret_info.row = info->row;
+ ret_info.column = info->column;
+
+ gtk_selection_data_set (selection_data, selection_data->target,
+ GTK_TYPE_POINTER, (guchar *) &ret_info,
+ sizeof (GtkCListCellInfo));
+ }
+ else
+ gtk_selection_data_set (selection_data, selection_data->target,
+ GTK_TYPE_POINTER, NULL, 0);
+ }
+}
+
+static void
+draw_drag_highlight (GtkCList *clist,
+ GtkCListRow *dest_row,
+ gint dest_row_number,
+ GtkCListDragPos drag_pos)
+{
+ gint y;
+
+ y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
+
+ switch (drag_pos)
+ {
+ case GTK_CLIST_DRAG_NONE:
+ break;
+ case GTK_CLIST_DRAG_AFTER:
+ y += clist->row_height + 1;
+ case GTK_CLIST_DRAG_BEFORE:
+ gdk_draw_line (clist->clist_window, clist->xor_gc,
+ 0, y, clist->clist_window_width, y);
+ break;
+ case GTK_CLIST_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_clist_set_reorderable (GtkCList *clist,
+ gboolean reorderable)
+{
+ GtkWidget *widget;
g_return_if_fail (clist != NULL);
g_return_if_fail (GTK_IS_CLIST (clist));
- if (clist->rows <= 1)
+ if ((GTK_CLIST_REORDERABLE(clist) != 0) == reorderable)
return;
- if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
- return;
+ widget = GTK_WIDGET (clist);
- if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
+ if (reorderable)
{
- GTK_CLIST_CLASS_FW (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;
+ GTK_CLIST_SET_FLAG (clist, CLIST_REORDERABLE);
+ gtk_drag_dest_set (widget,
+ GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+ &clist_target_table, 1, GDK_ACTION_MOVE);
}
-
- if (!GTK_CLIST_FROZEN (clist))
+ else
{
- gtk_clist_freeze (clist);
- thaw = TRUE;
+ GTK_CLIST_UNSET_FLAG (clist, CLIST_REORDERABLE);
+ gtk_drag_dest_unset (GTK_WIDGET (clist));
}
+}
- clist->row_list = gtk_clist_mergesort (clist, clist->row_list, clist->rows);
+void
+gtk_clist_set_use_drag_icons (GtkCList *clist,
+ gboolean use_icons)
+{
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
- work = clist->selection;
+ if (use_icons != 0)
+ GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
+ else
+ GTK_CLIST_UNSET_FLAG (clist, CLIST_USE_DRAG_ICONS);
+}
- for (i = 0, list = clist->row_list; i < clist->rows; i++, list = list->next)
+void
+gtk_clist_set_button_actions (GtkCList *clist,
+ guint button,
+ guint8 button_actions)
+{
+ g_return_if_fail (clist != NULL);
+ g_return_if_fail (GTK_IS_CLIST (clist));
+
+ if (button < MAX_BUTTON)
{
- if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
+ if (gdk_pointer_is_grabbed () || GTK_WIDGET_HAS_GRAB (clist))
{
- work->data = GINT_TO_POINTER (i);
- work = work->next;
+ remove_grab (clist);
+ clist->drag_button = 0;
}
-
- if (i == clist->rows - 1)
- clist->row_list_end = list;
- }
- if (thaw)
- gtk_clist_thaw (clist);
+ GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+
+ clist->button_actions[button] = button_actions;
+ }
}