1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, Josh MacDonald,
3 * Copyright (C) 1997-1998 Jay Painter <jpaint@serv.net><jpaint@gimp.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 #include "../config.h"
25 #include "gtkbindings.h"
26 #include <gdk/gdkkeysyms.h>
28 /* the number rows memchunk expands at a time */
29 #define CLIST_OPTIMUM_SIZE 512
31 /* the width of the column resize windows */
34 /* minimum allowed width of a column */
35 #define COLUMN_MIN_WIDTH 5
37 /* this defigns the base grid spacing */
38 #define CELL_SPACING 1
40 /* added the horizontal space at the beginning and end of a row*/
41 #define COLUMN_INSET 3
43 /* used for auto-scrolling */
44 #define SCROLL_TIME 100
46 /* scrollbar spacing class macro */
47 #define SCROLLBAR_SPACING(w) (GTK_CLIST_CLASS (GTK_OBJECT (w)->klass)->scrollbar_spacing)
49 /* gives the top pixel of the given row in context of
50 * the clist's voffset */
51 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
52 (((row) + 1) * CELL_SPACING) + \
55 /* returns the row index from a y pixel location in the
56 * context of the clist's voffset */
57 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
58 ((clist)->row_height + CELL_SPACING))
60 /* gives the left pixel of the given column in context of
61 * the clist's hoffset */
62 #define COLUMN_LEFT_XPIXEL(clist, colnum) ((clist)->column[(colnum)].area.x + \
65 /* returns the column index from a x pixel location in the
66 * context of the clist's hoffset */
68 COLUMN_FROM_XPIXEL (GtkCList * clist,
73 for (i = 0; i < clist->columns; i++)
75 cx = clist->column[i].area.x + clist->hoffset;
77 if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
78 x <= (cx + clist->column[i].area.width + COLUMN_INSET))
86 /* returns the top pixel of the given row in the context of
88 #define ROW_TOP(clist, row) (((clist)->row_height + CELL_SPACING) * (row))
90 /* returns the left pixel of the given column in the context of
92 #define COLUMN_LEFT(clist, colnum) ((clist)->column[(colnum)].area.x)
94 /* returns the total height of the list */
95 #define LIST_HEIGHT(clist) (((clist)->row_height * ((clist)->rows)) + \
96 (CELL_SPACING * ((clist)->rows + 1)))
98 /* returns the total width of the list */
99 #define LIST_WIDTH(clist) ((clist)->column[(clist)->columns - 1].area.x + \
100 (clist)->column[(clist)->columns - 1].area.width + \
101 COLUMN_INSET + CELL_SPACING)
104 #define GTK_CLIST_CLASS_FW(_widget_) GTK_CLIST_CLASS (GTK_OBJECT (_widget_)->klass)
134 typedef void (*GtkCListSignal1) (GtkObject * object,
140 typedef void (*GtkCListSignal2) (GtkObject *object,
143 typedef void (*GtkCListSignal3) (GtkObject * object,
146 typedef void (*GtkCListSignal4) (GtkObject * object,
150 typedef void (*GtkCListSignal5) (GtkObject * object,
157 static void sync_selection (GtkCList * clist,
161 /* GtkCList Methods */
162 static void gtk_clist_class_init (GtkCListClass * klass);
163 static void gtk_clist_init (GtkCList * clist);
164 static void real_clear (GtkCList * clist);
166 /* GtkObject Methods */
167 static void gtk_clist_destroy (GtkObject * object);
168 static void gtk_clist_finalize (GtkObject * object);
171 /* GtkWidget Methods */
172 static void gtk_clist_realize (GtkWidget * widget);
173 static void gtk_clist_unrealize (GtkWidget * widget);
174 static void gtk_clist_map (GtkWidget * widget);
175 static void gtk_clist_unmap (GtkWidget * widget);
176 static void gtk_clist_draw (GtkWidget * widget,
177 GdkRectangle * area);
178 static gint gtk_clist_expose (GtkWidget * widget,
179 GdkEventExpose * event);
180 static gint gtk_clist_button_press (GtkWidget * widget,
181 GdkEventButton * event);
182 static gint gtk_clist_button_release (GtkWidget * widget,
183 GdkEventButton * event);
184 static gint gtk_clist_motion (GtkWidget * widget,
185 GdkEventMotion * event);
186 static void gtk_clist_size_request (GtkWidget * widget,
187 GtkRequisition * requisition);
188 static void gtk_clist_size_allocate (GtkWidget * widget,
189 GtkAllocation * allocation);
190 static gint get_selection_info (GtkCList * clist,
196 /* GtkContainer Methods */
197 static void gtk_clist_foreach (GtkContainer * container,
198 GtkCallback callback,
199 gpointer callback_data);
202 static void draw_row (GtkCList * clist,
205 GtkCListRow * clist_row);
206 static void draw_rows (GtkCList * clist,
207 GdkRectangle * area);
209 /* Size Allocation */
210 static void size_allocate_title_buttons (GtkCList * clist);
211 static void size_allocate_columns (GtkCList * clist);
214 static void toggle_row (GtkCList * clist,
218 static void select_row (GtkCList * clist,
222 static void unselect_row (GtkCList * clist,
226 static void real_select_row (GtkCList * clist,
230 static void real_unselect_row (GtkCList * clist,
234 static void update_extended_selection (GtkCList *clist,
236 static GList * selection_find (GtkCList *clist,
238 GList *row_list_element);
239 static void real_select_all (GtkCList * clist);
240 static void real_unselect_all (GtkCList * clist);
241 static void move_vertical (GtkCList *clist,
244 static void move_horizontal (GtkCList *clist,
246 static void real_undo_selection (GtkCList * clist);
247 static void fake_unselect_all (GtkCList *clist,
249 static void fake_toggle_row (GtkCList *clist,
251 static void resync_selection (GtkCList *clist,
255 static void draw_xor_line (GtkCList * clist);
256 static gint new_column_width (GtkCList * clist,
260 static void resize_column (GtkCList * clist,
263 static void abort_column_resize (GtkCList *clist);
266 static void column_button_create (GtkCList * clist,
268 static void column_button_clicked (GtkWidget * widget,
272 static void create_scrollbars (GtkCList * clist);
273 static void adjust_scrollbars (GtkCList * clist);
274 static void check_exposures (GtkCList * clist);
275 static void vadjustment_changed (GtkAdjustment * adjustment,
277 static void vadjustment_value_changed (GtkAdjustment * adjustment,
279 static void hadjustment_changed (GtkAdjustment * adjustment,
281 static void hadjustment_value_changed (GtkAdjustment * adjustment,
284 /* Memory Allocation/Distruction Routines */
285 static GtkCListColumn *columns_new (GtkCList * clist);
287 static void column_title_new (GtkCList * clist,
290 static void columns_delete (GtkCList * clist);
292 static GtkCListRow *row_new (GtkCList * clist);
294 static void row_delete (GtkCList * clist,
295 GtkCListRow * clist_row);
296 static void cell_empty (GtkCList * clist,
297 GtkCListRow * clist_row,
299 static void cell_set_text (GtkCList * clist,
300 GtkCListRow * clist_row,
303 static void cell_set_pixmap (GtkCList * clist,
304 GtkCListRow * clist_row,
308 static void cell_set_pixtext (GtkCList * clist,
309 GtkCListRow * clist_row,
317 static void gtk_clist_draw_focus (GtkWidget *widget);
318 static gint gtk_clist_focus_in (GtkWidget *widget,
319 GdkEventFocus *event);
320 static gint gtk_clist_focus_out (GtkWidget *widget,
321 GdkEventFocus *event);
322 static gint gtk_clist_focus (GtkContainer *container,
323 GtkDirectionType direction);
324 static void gtk_clist_set_focus_child (GtkContainer *container,
326 static gint gtk_clist_key_press (GtkWidget *widget,
329 /* Selection handling */
330 static void set_anchor (GtkCList *clist,
334 static void start_selection (GtkCList *clist);
335 static void end_selection (GtkCList *clist);
337 static void toggle_add_mode (GtkCList *clist);
338 static void toggle_focus_row (GtkCList *clist);
339 static void move_focus_row (GtkCList *clist,
340 GtkScrollType scroll_type,
342 static void scroll_horizontal (GtkCList *clist,
343 GtkScrollType scroll_type,
345 static void scroll_vertical (GtkCList *clist,
346 GtkScrollType scroll_type,
348 static void extend_selection (GtkCList *clist,
349 GtkScrollType scroll_type,
351 gboolean auto_start_selection);
353 /* Fill in data after widget is realized and has style */
355 static void add_style_data (GtkCList * clist);
357 static GtkContainerClass *parent_class = NULL;
358 static guint clist_signals[LAST_SIGNAL] = {0};
362 gtk_clist_get_type (void)
364 static GtkType clist_type = 0;
368 GtkTypeInfo clist_info =
372 sizeof (GtkCListClass),
373 (GtkClassInitFunc) gtk_clist_class_init,
374 (GtkObjectInitFunc) gtk_clist_init,
375 /* reserved_1 */ NULL,
376 /* reserved_2 */ NULL,
377 (GtkClassInitFunc) NULL,
380 clist_type = gtk_type_unique (GTK_TYPE_CONTAINER, &clist_info);
387 gtk_clist_class_init (GtkCListClass * klass)
389 GtkObjectClass *object_class;
390 GtkWidgetClass *widget_class;
391 GtkContainerClass *container_class;
393 object_class = (GtkObjectClass *) klass;
394 widget_class = (GtkWidgetClass *) klass;
395 container_class = (GtkContainerClass *) klass;
397 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
399 clist_signals[SELECT_ROW] =
400 gtk_signal_new ("select_row",
403 GTK_SIGNAL_OFFSET (GtkCListClass, select_row),
404 gtk_marshal_NONE__INT_INT_POINTER,
409 clist_signals[UNSELECT_ROW] =
410 gtk_signal_new ("unselect_row",
413 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_row),
414 gtk_marshal_NONE__INT_INT_POINTER,
415 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_GDK_EVENT);
416 clist_signals[CLICK_COLUMN] =
417 gtk_signal_new ("click_column",
420 GTK_SIGNAL_OFFSET (GtkCListClass, click_column),
421 gtk_marshal_NONE__INT,
422 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
424 clist_signals[TOGGLE_FOCUS_ROW] =
425 gtk_signal_new ("toggle_focus_row",
426 GTK_RUN_LAST | GTK_RUN_ACTION,
428 GTK_SIGNAL_OFFSET (GtkCListClass, toggle_focus_row),
429 gtk_marshal_NONE__NONE,
431 clist_signals[SELECT_ALL] =
432 gtk_signal_new ("select_all",
433 GTK_RUN_LAST | GTK_RUN_ACTION,
435 GTK_SIGNAL_OFFSET (GtkCListClass, select_all),
436 gtk_marshal_NONE__NONE,
438 clist_signals[UNSELECT_ALL] =
439 gtk_signal_new ("unselect_all",
440 GTK_RUN_LAST | GTK_RUN_ACTION,
442 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_all),
443 gtk_marshal_NONE__NONE,
445 clist_signals[UNDO_SELECTION] =
446 gtk_signal_new ("undo_selection",
447 GTK_RUN_LAST | GTK_RUN_ACTION,
449 GTK_SIGNAL_OFFSET (GtkCListClass, undo_selection),
450 gtk_marshal_NONE__NONE,
452 clist_signals[START_SELECTION] =
453 gtk_signal_new ("start_selection",
454 GTK_RUN_LAST | GTK_RUN_ACTION,
456 GTK_SIGNAL_OFFSET (GtkCListClass, start_selection),
457 gtk_marshal_NONE__NONE,
459 clist_signals[END_SELECTION] =
460 gtk_signal_new ("end_selection",
461 GTK_RUN_LAST | GTK_RUN_ACTION,
463 GTK_SIGNAL_OFFSET (GtkCListClass, end_selection),
464 gtk_marshal_NONE__NONE,
466 clist_signals[TOGGLE_ADD_MODE] =
467 gtk_signal_new ("toggle_add_mode",
468 GTK_RUN_LAST | GTK_RUN_ACTION,
470 GTK_SIGNAL_OFFSET (GtkCListClass, toggle_add_mode),
471 gtk_marshal_NONE__NONE,
473 clist_signals[EXTEND_SELECTION] =
474 gtk_signal_new ("extend_selection",
475 GTK_RUN_LAST | GTK_RUN_ACTION,
477 GTK_SIGNAL_OFFSET (GtkCListClass, extend_selection),
478 gtk_marshal_NONE__ENUM_FLOAT_BOOL,
480 GTK_TYPE_ENUM, GTK_TYPE_FLOAT, GTK_TYPE_BOOL);
481 clist_signals[SCROLL_VERTICAL] =
482 gtk_signal_new ("scroll_vertical",
483 GTK_RUN_LAST | GTK_RUN_ACTION,
485 GTK_SIGNAL_OFFSET (GtkCListClass, scroll_vertical),
486 gtk_marshal_NONE__ENUM_FLOAT,
487 GTK_TYPE_NONE, 2, GTK_TYPE_ENUM, GTK_TYPE_FLOAT);
488 clist_signals[SCROLL_HORIZONTAL] =
489 gtk_signal_new ("scroll_horizontal",
490 GTK_RUN_LAST | GTK_RUN_ACTION,
492 GTK_SIGNAL_OFFSET (GtkCListClass, scroll_horizontal),
493 gtk_marshal_NONE__ENUM_FLOAT,
494 GTK_TYPE_NONE, 2, GTK_TYPE_ENUM, GTK_TYPE_FLOAT);
495 clist_signals[ABORT_COLUMN_RESIZE] =
496 gtk_signal_new ("abort_column_resize",
497 GTK_RUN_LAST | GTK_RUN_ACTION,
499 GTK_SIGNAL_OFFSET (GtkCListClass, abort_column_resize),
500 gtk_marshal_NONE__NONE,
504 gtk_object_class_add_signals (object_class, clist_signals, LAST_SIGNAL);
506 object_class->destroy = gtk_clist_destroy;
507 object_class->finalize = gtk_clist_finalize;
509 widget_class->realize = gtk_clist_realize;
510 widget_class->unrealize = gtk_clist_unrealize;
511 widget_class->map = gtk_clist_map;
512 widget_class->unmap = gtk_clist_unmap;
513 widget_class->draw = gtk_clist_draw;
514 widget_class->button_press_event = gtk_clist_button_press;
515 widget_class->button_release_event = gtk_clist_button_release;
516 widget_class->motion_notify_event = gtk_clist_motion;
517 widget_class->expose_event = gtk_clist_expose;
518 widget_class->size_request = gtk_clist_size_request;
519 widget_class->size_allocate = gtk_clist_size_allocate;
520 widget_class->key_press_event = gtk_clist_key_press;
521 widget_class->focus_in_event = gtk_clist_focus_in;
522 widget_class->focus_out_event = gtk_clist_focus_out;
523 widget_class->draw_focus = gtk_clist_draw_focus;
525 /* container_class->add = NULL; use the default GtkContainerClass warning */
526 /* container_class->remove = NULL; use the default GtkContainerClass warning */
527 container_class->foreach = gtk_clist_foreach;
528 container_class->focus = gtk_clist_focus;
529 container_class->set_focus_child = gtk_clist_set_focus_child;
531 klass->select_row = real_select_row;
532 klass->unselect_row = real_unselect_row;
533 klass->undo_selection = real_undo_selection;
534 klass->resync_selection = resync_selection;
535 klass->selection_find = selection_find;
536 klass->click_column = NULL;
537 klass->draw_row = draw_row;
538 klass->clear = real_clear;
539 klass->select_all = real_select_all;
540 klass->unselect_all = real_unselect_all;
541 klass->fake_unselect_all = fake_unselect_all;
542 klass->scroll_horizontal = scroll_horizontal;
543 klass->scroll_vertical = scroll_vertical;
544 klass->extend_selection = extend_selection;
545 klass->toggle_focus_row = toggle_focus_row;
546 klass->toggle_add_mode = toggle_add_mode;
547 klass->start_selection = start_selection;
548 klass->end_selection = end_selection;
549 klass->abort_column_resize = abort_column_resize;
551 klass->scrollbar_spacing = 5;
554 GtkBindingSet *binding_set;
556 binding_set = gtk_binding_set_by_class (klass);
557 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
558 "scroll_vertical", 2,
559 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
560 GTK_TYPE_FLOAT, 0.0);
561 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
562 "scroll_vertical", 2,
563 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
564 GTK_TYPE_FLOAT, 0.0);
565 gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
566 "scroll_vertical", 2,
567 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
568 GTK_TYPE_FLOAT, 0.0);
569 gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
570 "scroll_vertical", 2,
571 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
572 GTK_TYPE_FLOAT, 0.0);
573 gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
574 "scroll_vertical", 2,
575 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
576 GTK_TYPE_FLOAT, 0.0);
577 gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
578 "scroll_vertical", 2,
579 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
580 GTK_TYPE_FLOAT, 1.0);
582 gtk_binding_entry_add_signal (binding_set, GDK_Up, GDK_SHIFT_MASK,
583 "extend_selection", 3,
584 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
585 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
586 gtk_binding_entry_add_signal (binding_set, GDK_Down, GDK_SHIFT_MASK,
587 "extend_selection", 3,
588 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
589 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
590 gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_SHIFT_MASK,
591 "extend_selection", 3,
592 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
593 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
594 gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_SHIFT_MASK,
595 "extend_selection", 3,
596 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
597 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
598 gtk_binding_entry_add_signal (binding_set, GDK_Home,
599 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
600 "extend_selection", 3,
601 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
602 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
603 gtk_binding_entry_add_signal (binding_set, GDK_End,
604 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
605 "extend_selection", 3,
606 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
607 GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
610 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
611 "scroll_horizontal", 2,
612 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
613 GTK_TYPE_FLOAT, 0.0);
614 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
615 "scroll_horizontal", 2,
616 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
617 GTK_TYPE_FLOAT, 0.0);
618 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
619 "scroll_horizontal", 2,
620 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
621 GTK_TYPE_FLOAT, 0.0);
622 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
623 "scroll_horizontal", 2,
624 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
625 GTK_TYPE_FLOAT, 1.0);
628 gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
629 "undo_selection", 0);
630 gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
631 "abort_column_resize", 0);
632 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
633 "toggle_focus_row", 0);
634 gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
635 "toggle_add_mode", 0);
636 gtk_binding_entry_add_signal (binding_set, '/', GDK_CONTROL_MASK,
638 gtk_binding_entry_add_signal (binding_set, '\\', GDK_CONTROL_MASK,
640 gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
641 GDK_RELEASE_MASK | GDK_SHIFT_MASK,
643 gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
644 GDK_RELEASE_MASK | GDK_SHIFT_MASK,
650 GtkBindingSet *binding_set;
652 binding_set = gtk_binding_set_by_class (klass);
653 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
654 "scroll_vertical", 2,
655 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
656 GTK_TYPE_FLOAT, 0.0);
657 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
658 "scroll_vertical", 2,
659 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
660 GTK_TYPE_FLOAT, 0.0);
661 gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
662 "scroll_vertical", 2,
663 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
664 GTK_TYPE_FLOAT, 0.0);
665 gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
666 "scroll_vertical", 2,
667 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
668 GTK_TYPE_FLOAT, 0.0);
669 gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
670 "scroll_vertical", 2,
671 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
672 GTK_TYPE_FLOAT, 0.0);
673 gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
674 "scroll_vertical", 2,
675 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
678 gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
679 "extend_selection", 3,
680 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
681 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
682 gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
683 "extend_selection", 3,
684 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
685 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
686 gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, 0,
687 "extend_selection", 3,
688 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
689 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
690 gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, 0,
691 "extend_selection", 3,
692 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
693 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
694 gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
695 "extend_selection", 3,
696 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
697 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
698 gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
699 "extend_selection", 3,
700 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
701 GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
703 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
704 "scroll_horizontal", 2,
705 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
706 GTK_TYPE_FLOAT, 0.0);
707 gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
708 "scroll_horizontal", 2,
709 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
710 GTK_TYPE_FLOAT, 0.0);
711 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
712 "scroll_horizontal", 2,
713 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
714 GTK_TYPE_FLOAT, 0.0);
715 gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
716 "scroll_horizontal", 2,
717 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
718 GTK_TYPE_FLOAT, 0.0);
719 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
720 "scroll_horizontal", 2,
721 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
722 GTK_TYPE_FLOAT, 0.0);
723 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
724 "sroll_horizontal", 2,
725 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
726 GTK_TYPE_FLOAT, 1.0);
728 gtk_binding_entry_add_signal (binding_set, GDK_KP_Divide, 0,
729 "undo_selection", 0);
730 gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
731 "abort_column_resize", 0);
732 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
733 "toggle_focus_row", 0);
734 gtk_binding_entry_add_signal (binding_set, GDK_KP_Multiply, 0,
735 "toggle_add_mode", 0);
736 gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, 0,
738 gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, 0,
740 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
747 gtk_clist_init (GtkCList * clist)
751 GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
752 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
754 clist->row_mem_chunk = NULL;
755 clist->cell_mem_chunk = NULL;
758 clist->row_center_offset = 0;
759 clist->row_height = 0;
760 clist->row_list = NULL;
761 clist->row_list_end = NULL;
765 clist->title_window = NULL;
766 clist->column_title_area.x = 0;
767 clist->column_title_area.y = 0;
768 clist->column_title_area.width = 1;
769 clist->column_title_area.height = 1;
771 clist->clist_window = NULL;
772 clist->clist_window_width = 1;
773 clist->clist_window_height = 1;
778 clist->shadow_type = GTK_SHADOW_IN;
779 clist->hscrollbar_policy = GTK_POLICY_ALWAYS;
780 clist->vscrollbar_policy = GTK_POLICY_ALWAYS;
782 clist->cursor_drag = NULL;
783 clist->xor_gc = NULL;
788 clist->selection_mode = GTK_SELECTION_SINGLE;
789 clist->selection = NULL;
790 clist->selection_end = NULL;
791 clist->undo_selection = NULL;
792 clist->undo_unselection = NULL;
794 GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
795 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
796 clist->focus_row = -1;
797 clist->undo_anchor = -1;
800 clist->anchor_state = GTK_STATE_SELECTED;
801 clist->drag_pos = -1;
808 gtk_clist_construct (GtkCList * clist,
814 g_return_if_fail (clist != NULL);
815 g_return_if_fail (GTK_IS_CLIST (clist));
816 g_return_if_fail (GTK_CLIST_CONSTRUCTED (clist) == FALSE);
818 GTK_CLIST_SET_FLAG (clist, CLIST_CONSTRUCTED);
820 /* initalize memory chunks, if this has not been done by any
821 * possibly derived widget
823 if (!clist->row_mem_chunk)
824 clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
825 sizeof (GtkCListRow),
826 sizeof (GtkCListRow) * CLIST_OPTIMUM_SIZE,
829 if (!clist->cell_mem_chunk)
830 clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
831 sizeof (GtkCell) * columns,
832 sizeof (GtkCell) * columns * CLIST_OPTIMUM_SIZE,
835 /* set number of columns, allocate memory */
836 clist->columns = columns;
837 clist->column = columns_new (clist);
839 /* there needs to be at least one column button
840 * because there is alot of code that will break if it
842 column_button_create (clist, 0);
844 /* create scrollbars */
845 create_scrollbars (clist);
849 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
850 for (i = 0; i < columns; i++)
851 gtk_clist_set_column_title (clist, i, titles[i]);
855 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
860 * GTKCLIST PUBLIC INTERFACE
861 * gtk_clist_new_with_titles
865 gtk_clist_new_with_titles (gint columns,
870 g_return_val_if_fail (titles != NULL, NULL);
872 widget = gtk_type_new (GTK_TYPE_CLIST);
874 gtk_clist_construct (GTK_CLIST (widget), columns, titles);
880 gtk_clist_new (gint columns)
887 clist = gtk_type_new (GTK_TYPE_CLIST);
888 gtk_clist_construct (clist, columns, NULL);
889 return GTK_WIDGET (clist);
893 gtk_clist_set_border (GtkCList * clist,
894 GtkShadowType border)
896 g_return_if_fail (clist != NULL);
897 g_return_if_fail (GTK_IS_CLIST (clist));
899 clist->shadow_type = border;
901 if (GTK_WIDGET_VISIBLE (clist))
902 gtk_widget_queue_resize (GTK_WIDGET (clist));
906 gtk_clist_set_selection_mode (GtkCList * clist,
907 GtkSelectionMode mode)
909 g_return_if_fail (clist != NULL);
910 g_return_if_fail (GTK_IS_CLIST (clist));
912 if (mode == clist->selection_mode)
915 clist->selection_mode = mode;
917 clist->anchor_state = GTK_STATE_SELECTED;
918 clist->drag_pos = -1;
919 clist->undo_anchor = clist->focus_row;
921 g_list_free (clist->undo_selection);
922 g_list_free (clist->undo_unselection);
923 clist->undo_selection = NULL;
924 clist->undo_unselection = NULL;
928 case GTK_SELECTION_MULTIPLE:
929 case GTK_SELECTION_EXTENDED:
931 case GTK_SELECTION_BROWSE:
932 case GTK_SELECTION_SINGLE:
933 gtk_clist_unselect_all (clist);
939 gtk_clist_freeze (GtkCList * clist)
941 g_return_if_fail (clist != NULL);
942 g_return_if_fail (GTK_IS_CLIST (clist));
944 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
948 gtk_clist_thaw (GtkCList * clist)
950 g_return_if_fail (clist != NULL);
951 g_return_if_fail (GTK_IS_CLIST (clist));
953 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
955 adjust_scrollbars (clist);
956 draw_rows (clist, NULL);
960 gtk_clist_column_titles_show (GtkCList * clist)
962 g_return_if_fail (clist != NULL);
963 g_return_if_fail (GTK_IS_CLIST (clist));
965 if (!GTK_CLIST_SHOW_TITLES (clist))
967 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
968 if (clist->title_window)
969 gdk_window_show (clist->title_window);
970 gtk_widget_queue_resize (GTK_WIDGET (clist));
975 gtk_clist_column_titles_hide (GtkCList * clist)
977 g_return_if_fail (clist != NULL);
978 g_return_if_fail (GTK_IS_CLIST (clist));
980 if (GTK_CLIST_SHOW_TITLES (clist))
982 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
983 if (clist->title_window)
984 gdk_window_hide (clist->title_window);
985 gtk_widget_queue_resize (GTK_WIDGET (clist));
990 gtk_clist_column_title_active (GtkCList * clist,
993 g_return_if_fail (clist != NULL);
994 g_return_if_fail (GTK_IS_CLIST (clist));
996 if (column < 0 || column >= clist->columns)
999 if (!GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
1000 !GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
1002 GTK_WIDGET_SET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
1003 if (GTK_WIDGET_VISIBLE (clist))
1004 gtk_widget_queue_draw (clist->column[column].button);
1009 gtk_clist_column_title_passive (GtkCList * clist,
1012 g_return_if_fail (clist != NULL);
1013 g_return_if_fail (GTK_IS_CLIST (clist));
1015 if (column < 0 || column >= clist->columns)
1018 if (GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
1019 GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
1021 GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
1022 if (GTK_WIDGET_VISIBLE (clist))
1023 gtk_widget_queue_draw (clist->column[column].button);
1028 gtk_clist_column_titles_active (GtkCList * clist)
1032 g_return_if_fail (clist != NULL);
1033 g_return_if_fail (GTK_IS_CLIST (clist));
1035 for (i = 0; i < clist->columns; i++)
1036 if (clist->column[i].button)
1037 gtk_clist_column_title_active (clist, i);
1041 gtk_clist_column_titles_passive (GtkCList * clist)
1045 g_return_if_fail (clist != NULL);
1046 g_return_if_fail (GTK_IS_CLIST (clist));
1048 for (i = 0; i < clist->columns; i++)
1049 if (clist->column[i].button)
1050 gtk_clist_column_title_passive (clist, i);
1054 gtk_clist_set_column_title (GtkCList * clist,
1058 gint new_button = 0;
1059 GtkWidget *old_widget;
1060 GtkWidget *alignment = NULL;
1063 g_return_if_fail (clist != NULL);
1064 g_return_if_fail (GTK_IS_CLIST (clist));
1066 if (column < 0 || column >= clist->columns)
1069 /* if the column button doesn't currently exist,
1070 * it has to be created first */
1071 if (!clist->column[column].button)
1073 column_button_create (clist, column);
1077 column_title_new (clist, column, title);
1079 /* remove and destroy the old widget */
1080 old_widget = GTK_BIN (clist->column[column].button)->child;
1082 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
1084 /* create new alignment based no column justification */
1085 switch (clist->column[column].justification)
1087 case GTK_JUSTIFY_LEFT:
1088 alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
1091 case GTK_JUSTIFY_RIGHT:
1092 alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
1095 case GTK_JUSTIFY_CENTER:
1096 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1099 case GTK_JUSTIFY_FILL:
1100 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1104 label = gtk_label_new (clist->column[column].title);
1105 gtk_container_add (GTK_CONTAINER (alignment), label);
1106 gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
1107 gtk_widget_show (label);
1108 gtk_widget_show (alignment);
1110 /* if this button didn't previously exist, then the
1111 * column button positions have to be re-computed */
1112 if (GTK_WIDGET_VISIBLE (clist) && new_button)
1113 size_allocate_title_buttons (clist);
1117 gtk_clist_set_column_widget (GtkCList * clist,
1121 gint new_button = 0;
1122 GtkWidget *old_widget;
1124 g_return_if_fail (clist != NULL);
1125 g_return_if_fail (GTK_IS_CLIST (clist));
1127 if (column < 0 || column >= clist->columns)
1130 /* if the column button doesn't currently exist,
1131 * it has to be created first */
1132 if (!clist->column[column].button)
1134 column_button_create (clist, column);
1138 column_title_new (clist, column, NULL);
1140 /* remove and destroy the old widget */
1141 old_widget = GTK_BIN (clist->column[column].button)->child;
1143 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
1145 /* add and show the widget */
1148 gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
1149 gtk_widget_show (widget);
1152 /* if this button didn't previously exist, then the
1153 * column button positions have to be re-computed */
1154 if (GTK_WIDGET_VISIBLE (clist) && new_button)
1155 size_allocate_title_buttons (clist);
1159 gtk_clist_set_column_justification (GtkCList * clist,
1161 GtkJustification justification)
1163 GtkWidget *alignment;
1165 g_return_if_fail (clist != NULL);
1166 g_return_if_fail (GTK_IS_CLIST (clist));
1168 if (column < 0 || column >= clist->columns)
1171 clist->column[column].justification = justification;
1173 /* change the alinment of the button title if it's not a
1175 if (clist->column[column].title)
1177 alignment = GTK_BIN (clist->column[column].button)->child;
1179 switch (clist->column[column].justification)
1181 case GTK_JUSTIFY_LEFT:
1182 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
1185 case GTK_JUSTIFY_RIGHT:
1186 gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
1189 case GTK_JUSTIFY_CENTER:
1190 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1193 case GTK_JUSTIFY_FILL:
1194 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1202 if (!GTK_CLIST_FROZEN (clist))
1203 draw_rows (clist, NULL);
1207 gtk_clist_set_column_width (GtkCList * clist,
1211 g_return_if_fail (clist != NULL);
1212 g_return_if_fail (GTK_IS_CLIST (clist));
1214 if (column < 0 || column >= clist->columns)
1217 clist->column[column].width = width;
1218 clist->column[column].width_set = TRUE;
1220 /* FIXME: this is quite expensive to do if the widget hasn't
1221 * been size_allocated yet, and pointless. Should
1224 size_allocate_columns (clist);
1225 size_allocate_title_buttons (clist);
1227 if (!GTK_CLIST_FROZEN (clist))
1229 adjust_scrollbars (clist);
1230 draw_rows (clist, NULL);
1235 gtk_clist_set_row_height (GtkCList * clist,
1240 g_return_if_fail (clist != NULL);
1241 g_return_if_fail (GTK_IS_CLIST (clist));
1244 clist->row_height = height;
1248 GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
1250 if (GTK_WIDGET_REALIZED (clist))
1252 text_height = height - (GTK_WIDGET (clist)->style->font->ascent +
1253 GTK_WIDGET (clist) ->style->font->descent + 1);
1254 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
1257 if (!GTK_CLIST_FROZEN (clist))
1259 adjust_scrollbars (clist);
1260 draw_rows (clist, NULL);
1265 gtk_clist_moveto (GtkCList * clist,
1271 g_return_if_fail (clist != NULL);
1272 g_return_if_fail (GTK_IS_CLIST (clist));
1274 if (row < -1 || row >= clist->rows)
1276 if (column < -1 || column >= clist->columns)
1279 row_align = CLAMP (row_align, 0, 1);
1280 col_align = CLAMP (col_align, 0, 1);
1282 /* adjust horizontal scrollbar */
1288 adj = GTK_RANGE (clist->hscrollbar)->adjustment;
1290 x = COLUMN_LEFT (clist, column) - CELL_SPACING - COLUMN_INSET -
1291 (col_align * (clist->clist_window_width - 2 * COLUMN_INSET -
1292 CELL_SPACING - clist->column[column].area.width));
1294 gtk_adjustment_set_value (adj, 0.0);
1295 else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
1296 gtk_adjustment_set_value
1297 (adj, LIST_WIDTH (clist) - clist->clist_window_width);
1299 gtk_adjustment_set_value (adj, x);
1302 /* adjust vertical scrollbar */
1304 move_vertical (clist, row, row_align);
1308 gtk_clist_get_cell_type (GtkCList * clist,
1312 GtkCListRow *clist_row;
1314 g_return_val_if_fail (clist != NULL, -1);
1315 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
1317 if (row < 0 || row >= clist->rows)
1319 if (column < 0 || column >= clist->columns)
1322 clist_row = (g_list_nth (clist->row_list, row))->data;
1324 return clist_row->cell[column].type;
1328 gtk_clist_set_text (GtkCList * clist,
1333 GtkCListRow *clist_row;
1335 g_return_if_fail (clist != NULL);
1336 g_return_if_fail (GTK_IS_CLIST (clist));
1338 if (row < 0 || row >= clist->rows)
1340 if (column < 0 || column >= clist->columns)
1343 clist_row = (g_list_nth (clist->row_list, row))->data;
1345 /* if text is null, then the cell is empty */
1347 cell_set_text (clist, clist_row, column, text);
1349 cell_empty (clist, clist_row, column);
1351 /* redraw the list if it's not frozen */
1352 if (!GTK_CLIST_FROZEN (clist))
1354 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1355 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1360 gtk_clist_get_text (GtkCList * clist,
1365 GtkCListRow *clist_row;
1367 g_return_val_if_fail (clist != NULL, 0);
1368 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
1370 if (row < 0 || row >= clist->rows)
1372 if (column < 0 || column >= clist->columns)
1375 clist_row = (g_list_nth (clist->row_list, row))->data;
1377 if (clist_row->cell[column].type != GTK_CELL_TEXT)
1381 *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
1387 gtk_clist_set_pixmap (GtkCList * clist,
1393 GtkCListRow *clist_row;
1395 g_return_if_fail (clist != NULL);
1396 g_return_if_fail (GTK_IS_CLIST (clist));
1398 if (row < 0 || row >= clist->rows)
1400 if (column < 0 || column >= clist->columns)
1403 clist_row = (g_list_nth (clist->row_list, row))->data;
1405 gdk_pixmap_ref (pixmap);
1407 if (mask) gdk_pixmap_ref (mask);
1409 cell_set_pixmap (clist, clist_row, column, pixmap, mask);
1411 /* redraw the list if it's not frozen */
1412 if (!GTK_CLIST_FROZEN (clist))
1414 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1415 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1420 gtk_clist_get_pixmap (GtkCList * clist,
1423 GdkPixmap ** pixmap,
1426 GtkCListRow *clist_row;
1428 g_return_val_if_fail (clist != NULL, 0);
1429 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
1431 if (row < 0 || row >= clist->rows)
1433 if (column < 0 || column >= clist->columns)
1436 clist_row = (g_list_nth (clist->row_list, row))->data;
1438 if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
1443 *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
1444 /* mask can be NULL */
1445 *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
1452 gtk_clist_set_pixtext (GtkCList * clist,
1460 GtkCListRow *clist_row;
1462 g_return_if_fail (clist != NULL);
1463 g_return_if_fail (GTK_IS_CLIST (clist));
1465 if (row < 0 || row >= clist->rows)
1467 if (column < 0 || column >= clist->columns)
1470 clist_row = (g_list_nth (clist->row_list, row))->data;
1472 gdk_pixmap_ref (pixmap);
1473 if (mask) gdk_pixmap_ref (mask);
1474 cell_set_pixtext (clist, clist_row, column, text, spacing, pixmap, mask);
1476 /* redraw the list if it's not frozen */
1477 if (!GTK_CLIST_FROZEN (clist))
1479 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1480 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1485 gtk_clist_get_pixtext (GtkCList * clist,
1490 GdkPixmap ** pixmap,
1493 GtkCListRow *clist_row;
1495 g_return_val_if_fail (clist != NULL, 0);
1496 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
1498 if (row < 0 || row >= clist->rows)
1500 if (column < 0 || column >= clist->columns)
1503 clist_row = (g_list_nth (clist->row_list, row))->data;
1505 if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
1509 *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
1511 *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
1513 *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
1515 /* mask can be NULL */
1516 *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
1522 gtk_clist_set_foreground (GtkCList * clist,
1526 GtkCListRow *clist_row;
1528 g_return_if_fail (clist != NULL);
1529 g_return_if_fail (GTK_IS_CLIST (clist));
1531 if (row < 0 || row >= clist->rows)
1534 clist_row = (g_list_nth (clist->row_list, row))->data;
1538 clist_row->foreground = *color;
1539 clist_row->fg_set = TRUE;
1542 clist_row->fg_set = FALSE;
1544 if (!GTK_CLIST_FROZEN (clist)
1545 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1546 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1550 gtk_clist_set_background (GtkCList * clist,
1554 GtkCListRow *clist_row;
1556 g_return_if_fail (clist != NULL);
1557 g_return_if_fail (GTK_IS_CLIST (clist));
1559 if (row < 0 || row >= clist->rows)
1562 clist_row = (g_list_nth (clist->row_list, row))->data;
1566 clist_row->background = *color;
1567 clist_row->bg_set = TRUE;
1570 clist_row->bg_set = FALSE;
1572 if (!GTK_CLIST_FROZEN (clist)
1573 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1574 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1578 gtk_clist_set_shift (GtkCList * clist,
1584 GtkCListRow *clist_row;
1586 g_return_if_fail (clist != NULL);
1587 g_return_if_fail (GTK_IS_CLIST (clist));
1589 if (row < 0 || row >= clist->rows)
1591 if (column < 0 || column >= clist->columns)
1594 clist_row = (g_list_nth (clist->row_list, row))->data;
1596 clist_row->cell[column].vertical = vertical;
1597 clist_row->cell[column].horizontal = horizontal;
1599 if (!GTK_CLIST_FROZEN (clist)
1600 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1601 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1605 gtk_clist_append (GtkCList * clist,
1609 GtkCListRow *clist_row;
1611 g_return_val_if_fail (clist != NULL, -1);
1612 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
1614 clist_row = row_new (clist);
1617 /* set the text in the row's columns */
1619 for (i = 0; i < clist->columns; i++)
1621 cell_set_text (clist, clist_row, i, text[i]);
1623 /* keeps track of the end of the list so the list
1624 * doesn't have to be traversed every time a item is added */
1625 if (!clist->row_list)
1627 clist->row_list = g_list_append (clist->row_list, clist_row);
1628 clist->row_list_end = clist->row_list;
1630 /* check the selection mode to see if we should select
1631 * the first row automaticly */
1632 switch (clist->selection_mode)
1634 case GTK_SELECTION_BROWSE:
1635 select_row (clist, 0, -1, NULL);
1643 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
1645 /* redraw the list if it's not frozen */
1646 if (!GTK_CLIST_FROZEN (clist))
1648 adjust_scrollbars (clist);
1650 if (gtk_clist_row_is_visible (clist, clist->rows - 1) != GTK_VISIBILITY_NONE)
1651 draw_rows (clist, NULL);
1654 /* return index of the row */
1655 return clist->rows - 1;
1659 gtk_clist_insert (GtkCList * clist,
1664 GtkCListRow *clist_row;
1666 g_return_if_fail (clist != NULL);
1667 g_return_if_fail (GTK_IS_CLIST (clist));
1668 g_return_if_fail (text != NULL);
1670 /* return if out of bounds */
1671 if (row < 0 || row > clist->rows)
1674 if (clist->rows == 0)
1675 gtk_clist_append (clist, text);
1678 /* create the row */
1679 clist_row = row_new (clist);
1681 /* set the text in the row's columns */
1683 for (i = 0; i < clist->columns; i++)
1685 cell_set_text (clist, clist_row, i, text[i]);
1687 /* reset the row end pointer if we're inserting at the
1688 * end of the list */
1689 if (row == clist->rows)
1690 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
1692 clist->row_list = g_list_insert (clist->row_list, clist_row, row);
1696 if (row < ROW_FROM_YPIXEL (clist, 0))
1697 clist->voffset -= (clist->row_height + CELL_SPACING);
1699 /* syncronize the selection list */
1700 sync_selection (clist, row, SYNC_INSERT);
1703 /* redraw the list if it isn't frozen */
1704 if (!GTK_CLIST_FROZEN (clist))
1706 adjust_scrollbars (clist);
1708 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1709 draw_rows (clist, NULL);
1714 gtk_clist_remove (GtkCList * clist,
1717 gint was_visible, was_selected;
1719 GtkCListRow *clist_row;
1721 g_return_if_fail (clist != NULL);
1722 g_return_if_fail (GTK_IS_CLIST (clist));
1724 /* return if out of bounds */
1725 if (row < 0 || row > (clist->rows - 1))
1728 was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
1731 /* get the row we're going to delete */
1732 list = g_list_nth (clist->row_list, row);
1733 clist_row = list->data;
1735 /* if we're removing a selected row, we have to make sure
1736 * it's properly unselected, and then sync up the clist->selected
1737 * list to reflect the deincrimented indexies of rows after the
1739 if (clist_row->state == GTK_STATE_SELECTED)
1741 switch (clist->selection_mode)
1743 case GTK_SELECTION_SINGLE:
1744 case GTK_SELECTION_MULTIPLE:
1745 case GTK_SELECTION_EXTENDED:
1746 unselect_row (clist, row, -1, NULL);
1749 case GTK_SELECTION_BROWSE:
1750 select_row (clist, row - 1, -1, NULL);
1758 /* reset the row end pointer if we're removing at the
1759 * end of the list */
1760 if (row == clist->rows - 1)
1761 clist->row_list_end = list->prev;
1762 if (row >= clist->focus_row && clist->focus_row >=0)
1765 clist->row_list = g_list_remove (clist->row_list, clist_row);
1768 if (row < ROW_FROM_YPIXEL (clist, 0))
1769 clist->voffset += clist->row_height + CELL_SPACING;
1771 sync_selection (clist, row, SYNC_REMOVE);
1774 row_delete (clist, clist_row);
1776 /* redraw the row if it isn't frozen */
1777 if (!GTK_CLIST_FROZEN (clist))
1779 adjust_scrollbars (clist);
1782 draw_rows (clist, NULL);
1787 sync_selection (GtkCList * clist,
1794 if (mode == SYNC_INSERT)
1799 if (clist->focus_row >= row)
1801 clist->focus_row += d;
1802 if (clist->focus_row == -1 && clist->rows >= 1)
1803 clist->focus_row = 0;
1806 if (clist->selection_mode == GTK_SELECTION_BROWSE && clist->anchor != -1)
1807 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
1809 g_list_free (clist->undo_selection);
1810 g_list_free (clist->undo_unselection);
1811 clist->undo_selection = NULL;
1812 clist->undo_unselection = NULL;
1815 clist->drag_pos = -1;
1816 clist->undo_anchor = clist->focus_row;
1818 list = clist->selection;
1821 if (GPOINTER_TO_INT (list->data) >= row)
1822 list->data = ((gchar*) list->data) + d;
1828 gtk_clist_clear (GtkCList * clist)
1830 GTK_CLIST_CLASS_FW (clist)->clear (clist);
1834 real_clear (GtkCList * clist)
1838 g_return_if_fail (clist != NULL);
1839 g_return_if_fail (GTK_IS_CLIST (clist));
1841 /* remove all the rows */
1842 for (list = clist->row_list; list; list = list->next)
1843 row_delete (clist, GTK_CLIST_ROW (list));
1845 g_list_free (clist->row_list);
1847 /* free up the selection list */
1848 g_list_free (clist->selection);
1849 g_list_free (clist->undo_selection);
1850 g_list_free (clist->undo_unselection);
1852 clist->row_list = NULL;
1853 clist->row_list_end = NULL;
1854 clist->selection = NULL;
1855 clist->selection_end = NULL;
1856 clist->undo_selection = NULL;
1857 clist->undo_unselection = NULL;
1860 clist->focus_row = -1;
1862 clist->undo_anchor = -1;
1863 clist->anchor_state = GTK_STATE_SELECTED;
1864 clist->drag_pos = -1;
1866 /* zero-out the scrollbars */
1867 if (clist->vscrollbar)
1869 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
1870 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
1872 if (!GTK_CLIST_FROZEN (clist))
1873 gtk_clist_thaw (clist);
1878 gtk_clist_swap_rows (GtkCList * clist,
1883 GList *list, *link1, *link2;
1886 g_return_if_fail (clist != NULL);
1887 g_return_if_fail (GTK_IS_CLIST (clist));
1889 if (row1 < 0 || row1 > (clist->rows - 1))
1892 if (row2 < 0 || row2 > (clist->rows - 1))
1895 first = MIN (row1, row2);
1896 last = MAX (row1, row2);
1898 link1 = g_list_nth (clist->row_list, first);
1899 link2 = g_list_nth (link1, row2 - row1);
1902 link1->data = link2->data;
1905 list = clist->selection;
1908 if (GPOINTER_TO_INT (list->data) == row1)
1909 GPOINTER_TO_INT (list->data) = row2;
1911 if (GPOINTER_TO_INT (list->data) == row2)
1912 GPOINTER_TO_INT (list->data) = row1;
1917 if (!GTK_CLIST_FROZEN (clist))
1919 if (gtk_clist_row_is_visible (clist, row1) != GTK_VISIBILITY_NONE)
1920 GTK_CLIST_CLASS_FW (clist)->draw_row
1921 (clist, NULL, row1, GTK_CLIST_ROW (link2));
1923 if (gtk_clist_row_is_visible (clist, row2) != GTK_VISIBILITY_NONE)
1924 GTK_CLIST_CLASS_FW (clist)->draw_row
1925 (clist, NULL, row2, GTK_CLIST_ROW (link1));
1930 gtk_clist_set_row_data (GtkCList * clist,
1934 gtk_clist_set_row_data_full (clist, row, data, NULL);
1938 gtk_clist_set_row_data_full (GtkCList * clist,
1941 GtkDestroyNotify destroy)
1943 GtkCListRow *clist_row;
1945 g_return_if_fail (clist != NULL);
1946 g_return_if_fail (GTK_IS_CLIST (clist));
1948 if (row < 0 || row > (clist->rows - 1))
1951 clist_row = (g_list_nth (clist->row_list, row))->data;
1952 clist_row->data = data;
1953 clist_row->destroy = destroy;
1955 /* re-send the selected signal if data is changed/added
1956 * so the application can respond to the new data --
1957 * this could be questionable behavior */
1958 if (clist_row->state == GTK_STATE_SELECTED)
1959 select_row (clist, row, -1, NULL);
1963 gtk_clist_get_row_data (GtkCList * clist,
1966 GtkCListRow *clist_row;
1968 g_return_val_if_fail (clist != NULL, NULL);
1969 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1971 if (row < 0 || row > (clist->rows - 1))
1974 clist_row = (g_list_nth (clist->row_list, row))->data;
1975 return clist_row->data;
1979 gtk_clist_find_row_from_data (GtkCList * clist,
1985 g_return_val_if_fail (clist != NULL, -1);
1986 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
1988 if (clist->rows < 1)
1989 return -1; /* is this an optimization or just worthless? */
1991 for (n = 0, list = clist->row_list; list; n++, list = list->next)
1992 if (GTK_CLIST_ROW (list)->data == data)
1999 gtk_clist_select_row (GtkCList * clist,
2003 g_return_if_fail (clist != NULL);
2004 g_return_if_fail (GTK_IS_CLIST (clist));
2006 if (row < 0 || row >= clist->rows)
2009 if (column < -1 || column >= clist->columns)
2012 select_row (clist, row, column, NULL);
2016 gtk_clist_unselect_row (GtkCList * clist,
2020 g_return_if_fail (clist != NULL);
2021 g_return_if_fail (GTK_IS_CLIST (clist));
2023 if (row < 0 || row >= clist->rows)
2026 if (column < -1 || column >= clist->columns)
2029 unselect_row (clist, row, column, NULL);
2033 gtk_clist_row_is_visible (GtkCList * clist,
2038 g_return_val_if_fail (clist != NULL, 0);
2039 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
2041 if (row < 0 || row >= clist->rows)
2042 return GTK_VISIBILITY_NONE;
2044 if (clist->row_height == 0)
2045 return GTK_VISIBILITY_NONE;
2047 if (row < ROW_FROM_YPIXEL (clist, 0))
2048 return GTK_VISIBILITY_NONE;
2050 if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
2051 return GTK_VISIBILITY_NONE;
2053 top = ROW_TOP_YPIXEL (clist, row);
2056 || ((top + clist->row_height) >= clist->clist_window_height))
2057 return GTK_VISIBILITY_PARTIAL;
2059 return GTK_VISIBILITY_FULL;
2063 gtk_clist_get_vadjustment (GtkCList * clist)
2065 g_return_val_if_fail (clist != NULL, NULL);
2066 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
2068 return gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
2072 gtk_clist_get_hadjustment (GtkCList * clist)
2074 g_return_val_if_fail (clist != NULL, NULL);
2075 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
2077 return gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
2081 gtk_clist_set_policy (GtkCList * clist,
2082 GtkPolicyType vscrollbar_policy,
2083 GtkPolicyType hscrollbar_policy)
2085 g_return_if_fail (clist != NULL);
2086 g_return_if_fail (GTK_IS_CLIST (clist));
2088 if (clist->vscrollbar_policy != vscrollbar_policy)
2090 clist->vscrollbar_policy = vscrollbar_policy;
2092 if (GTK_WIDGET (clist)->parent)
2093 gtk_widget_queue_resize (GTK_WIDGET (clist));
2096 if (clist->hscrollbar_policy != hscrollbar_policy)
2098 clist->hscrollbar_policy = hscrollbar_policy;
2100 if (GTK_WIDGET (clist)->parent)
2101 gtk_widget_queue_resize (GTK_WIDGET (clist));
2106 gtk_clist_undo_selection (GtkCList *clist)
2108 g_return_if_fail (clist != NULL);
2109 g_return_if_fail (GTK_IS_CLIST (clist));
2111 if (clist->selection_mode == GTK_SELECTION_EXTENDED &&
2112 (clist->undo_selection || clist->undo_unselection))
2113 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNDO_SELECTION]);
2117 real_undo_selection (GtkCList *clist)
2121 g_return_if_fail (clist != NULL);
2122 g_return_if_fail (GTK_IS_CLIST (clist));
2124 if (gdk_pointer_is_grabbed () ||
2125 clist->selection_mode != GTK_SELECTION_EXTENDED)
2128 if (clist->anchor >= 0)
2129 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2131 if (!(clist->undo_selection || clist->undo_unselection))
2133 gtk_clist_unselect_all (clist);
2137 for (work = clist->undo_selection; work; work = work->next)
2138 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2139 GPOINTER_TO_INT (work->data), -1, NULL);
2141 for (work = clist->undo_unselection; work; work = work->next)
2142 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2143 GPOINTER_TO_INT (work->data), -1, NULL);
2145 if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
2147 gtk_clist_draw_focus (GTK_WIDGET (clist));
2148 clist->focus_row = clist->undo_anchor;
2149 gtk_clist_draw_focus (GTK_WIDGET (clist));
2152 clist->focus_row = clist->undo_anchor;
2154 clist->undo_anchor = -1;
2156 g_list_free (clist->undo_selection);
2157 g_list_free (clist->undo_unselection);
2158 clist->undo_selection = NULL;
2159 clist->undo_unselection = NULL;
2161 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
2162 clist->clist_window_height)
2163 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
2164 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
2165 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
2171 * gtk_clist_finalize
2174 gtk_clist_destroy (GtkObject * object)
2179 g_return_if_fail (object != NULL);
2180 g_return_if_fail (GTK_IS_CLIST (object));
2182 clist = GTK_CLIST (object);
2184 /* freeze the list */
2185 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
2187 /* get rid of all the rows */
2188 gtk_clist_clear (clist);
2190 /* Since we don't have a _remove method, unparent the children
2191 * instead of destroying them so the focus will be unset properly.
2192 * (For other containers, the _remove method takes care of the
2193 * unparent) The destroy will happen when the refcount drops
2197 /* destroy the scrollbars */
2198 if (clist->vscrollbar)
2200 gtk_widget_unparent (clist->vscrollbar);
2201 clist->vscrollbar = NULL;
2203 if (clist->hscrollbar)
2205 gtk_widget_unparent (clist->hscrollbar);
2206 clist->hscrollbar = NULL;
2211 gtk_timeout_remove (clist->htimer);
2216 gtk_timeout_remove (clist->vtimer);
2220 /* destroy the column buttons */
2221 for (i = 0; i < clist->columns; i++)
2222 if (clist->column[i].button)
2224 gtk_widget_unparent (clist->column[i].button);
2225 clist->column[i].button = NULL;
2228 if (GTK_OBJECT_CLASS (parent_class)->destroy)
2229 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
2233 gtk_clist_finalize (GtkObject * object)
2237 g_return_if_fail (object != NULL);
2238 g_return_if_fail (GTK_IS_CLIST (object));
2240 clist = GTK_CLIST (object);
2242 columns_delete (clist);
2244 g_mem_chunk_destroy (clist->cell_mem_chunk);
2245 g_mem_chunk_destroy (clist->row_mem_chunk);
2247 if (GTK_OBJECT_CLASS (parent_class)->finalize)
2248 (*GTK_OBJECT_CLASS (parent_class)->finalize) (object);
2254 * gtk_clist_unrealize
2259 * gtk_clist_button_press
2260 * gtk_clist_button_release
2261 * gtk_clist_button_motion
2262 * gtk_clist_size_request
2263 * gtk_clist_size_allocate
2266 gtk_clist_realize (GtkWidget * widget)
2270 GdkWindowAttr attributes;
2271 gint attributes_mask;
2275 g_return_if_fail (widget != NULL);
2276 g_return_if_fail (GTK_IS_CLIST (widget));
2278 clist = GTK_CLIST (widget);
2280 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
2282 add_style_data (clist);
2284 border_width = GTK_CONTAINER (widget)->border_width;
2286 attributes.window_type = GDK_WINDOW_CHILD;
2287 attributes.x = widget->allocation.x + border_width;
2288 attributes.y = widget->allocation.y + border_width;
2289 attributes.width = widget->allocation.width - border_width * 2;
2290 attributes.height = widget->allocation.height - border_width * 2;
2291 attributes.wclass = GDK_INPUT_OUTPUT;
2292 attributes.visual = gtk_widget_get_visual (widget);
2293 attributes.colormap = gtk_widget_get_colormap (widget);
2294 attributes.event_mask = gtk_widget_get_events (widget);
2295 attributes.event_mask |= (GDK_EXPOSURE_MASK |
2296 GDK_BUTTON_PRESS_MASK |
2297 GDK_BUTTON_RELEASE_MASK |
2298 GDK_KEY_PRESS_MASK |
2299 GDK_KEY_RELEASE_MASK);
2300 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
2303 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
2304 gdk_window_set_user_data (widget->window, clist);
2306 widget->style = gtk_style_attach (widget->style, widget->window);
2308 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
2310 /* column-title window */
2312 attributes.x = clist->column_title_area.x;
2313 attributes.y = clist->column_title_area.y;
2314 attributes.width = clist->column_title_area.width;
2315 attributes.height = clist->column_title_area.height;
2317 clist->title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2318 gdk_window_set_user_data (clist->title_window, clist);
2320 gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_SELECTED);
2321 gdk_window_show (clist->title_window);
2323 /* set things up so column buttons are drawn in title window */
2324 for (i = 0; i < clist->columns; i++)
2325 if (clist->column[i].button)
2326 gtk_widget_set_parent_window (clist->column[i].button, clist->title_window);
2329 attributes.x = clist->internal_allocation.x + widget->style->klass->xthickness;
2330 attributes.y = clist->internal_allocation.y + widget->style->klass->ythickness +
2331 clist->column_title_area.height;
2332 attributes.width = clist->clist_window_width;
2333 attributes.height = clist->clist_window_height;
2335 clist->clist_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2336 gdk_window_set_user_data (clist->clist_window, clist);
2338 gdk_window_set_background (clist->clist_window, &widget->style->bg[GTK_STATE_PRELIGHT]);
2339 gdk_window_show (clist->clist_window);
2340 gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
2341 &clist->clist_window_height);
2343 /* create resize windows */
2344 attributes.wclass = GDK_INPUT_ONLY;
2345 attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
2346 GDK_BUTTON_RELEASE_MASK |
2347 GDK_POINTER_MOTION_MASK |
2348 GDK_POINTER_MOTION_HINT_MASK |
2349 GDK_KEY_PRESS_MASK);
2350 attributes.cursor = clist->cursor_drag = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
2351 attributes_mask = GDK_WA_CURSOR;
2353 for (i = 0; i < clist->columns; i++)
2355 clist->column[i].window = gdk_window_new (clist->title_window, &attributes, attributes_mask);
2356 gdk_window_set_user_data (clist->column[i].window, clist);
2359 /* This is slightly less efficient than creating them with the
2360 * right size to begin with, but easier
2362 size_allocate_title_buttons (clist);
2365 clist->fg_gc = gdk_gc_new (widget->window);
2366 clist->bg_gc = gdk_gc_new (widget->window);
2368 /* We'll use this gc to do scrolling as well */
2369 gdk_gc_set_exposures (clist->fg_gc, TRUE);
2371 values.foreground = widget->style->white;
2372 values.function = GDK_XOR;
2373 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
2374 clist->xor_gc = gdk_gc_new_with_values (widget->window,
2382 gtk_clist_unrealize (GtkWidget * widget)
2387 g_return_if_fail (widget != NULL);
2388 g_return_if_fail (GTK_IS_CLIST (widget));
2390 clist = GTK_CLIST (widget);
2392 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
2394 gdk_cursor_destroy (clist->cursor_drag);
2395 gdk_gc_destroy (clist->xor_gc);
2396 gdk_gc_destroy (clist->fg_gc);
2397 gdk_gc_destroy (clist->bg_gc);
2399 for (i = 0; i < clist->columns; i++)
2400 if (clist->column[i].window)
2402 gdk_window_set_user_data (clist->column[i].window, NULL);
2403 gdk_window_destroy (clist->column[i].window);
2404 clist->column[i].window = NULL;
2407 gdk_window_set_user_data (clist->clist_window, NULL);
2408 gdk_window_destroy (clist->clist_window);
2409 clist->clist_window = NULL;
2411 gdk_window_set_user_data (clist->title_window, NULL);
2412 gdk_window_destroy (clist->title_window);
2413 clist->title_window = NULL;
2415 clist->cursor_drag = NULL;
2416 clist->xor_gc = NULL;
2417 clist->fg_gc = NULL;
2418 clist->bg_gc = NULL;
2420 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
2421 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
2425 gtk_clist_map (GtkWidget * widget)
2430 g_return_if_fail (widget != NULL);
2431 g_return_if_fail (GTK_IS_CLIST (widget));
2433 clist = GTK_CLIST (widget);
2435 if (!GTK_WIDGET_MAPPED (widget))
2437 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2439 gdk_window_show (widget->window);
2440 gdk_window_show (clist->title_window);
2441 gdk_window_show (clist->clist_window);
2443 /* map column buttons */
2444 for (i = 0; i < clist->columns; i++)
2445 if (clist->column[i].button &&
2446 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
2447 !GTK_WIDGET_MAPPED (clist->column[i].button))
2448 gtk_widget_map (clist->column[i].button);
2450 /* map resize windows AFTER column buttons (above) */
2451 for (i = 0; i < clist->columns; i++)
2452 if (clist->column[i].window && clist->column[i].button)
2453 gdk_window_show (clist->column[i].window);
2455 /* map vscrollbars */
2456 if (GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
2457 !GTK_WIDGET_MAPPED (clist->vscrollbar))
2458 gtk_widget_map (clist->vscrollbar);
2460 if (GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
2461 !GTK_WIDGET_MAPPED (clist->hscrollbar))
2462 gtk_widget_map (clist->hscrollbar);
2464 /* unfreeze the list */
2465 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
2470 gtk_clist_unmap (GtkWidget * widget)
2475 g_return_if_fail (widget != NULL);
2476 g_return_if_fail (GTK_IS_CLIST (widget));
2478 clist = GTK_CLIST (widget);
2480 if (GTK_WIDGET_MAPPED (widget))
2482 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
2484 for (i = 0; i < clist->columns; i++)
2485 if (clist->column[i].window)
2486 gdk_window_hide (clist->column[i].window);
2488 gdk_window_hide (clist->clist_window);
2489 gdk_window_hide (clist->title_window);
2490 gdk_window_hide (widget->window);
2492 /* unmap scrollbars */
2493 if (GTK_WIDGET_MAPPED (clist->vscrollbar))
2494 gtk_widget_unmap (clist->vscrollbar);
2496 if (GTK_WIDGET_MAPPED (clist->hscrollbar))
2497 gtk_widget_unmap (clist->hscrollbar);
2499 /* unmap column buttons */
2500 for (i = 0; i < clist->columns; i++)
2501 if (clist->column[i].button &&
2502 GTK_WIDGET_MAPPED (clist->column[i].button))
2503 gtk_widget_unmap (clist->column[i].button);
2505 /* freeze the list */
2506 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
2511 gtk_clist_draw (GtkWidget * widget,
2512 GdkRectangle * area)
2517 g_return_if_fail (widget != NULL);
2518 g_return_if_fail (GTK_IS_CLIST (widget));
2519 g_return_if_fail (area != NULL);
2521 if (GTK_WIDGET_DRAWABLE (widget))
2523 clist = GTK_CLIST (widget);
2524 border_width = GTK_CONTAINER (widget)->border_width;
2526 gdk_window_clear_area (widget->window,
2527 area->x - border_width,
2528 area->y - border_width,
2529 area->width, area->height);
2531 /* draw list shadow/border */
2532 gtk_draw_shadow (widget->style, widget->window,
2533 GTK_STATE_NORMAL, clist->shadow_type,
2535 clist->clist_window_width + (2 * widget->style->klass->xthickness),
2536 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
2537 clist->column_title_area.height);
2539 gdk_window_clear_area (clist->clist_window,
2542 draw_rows (clist, NULL);
2547 gtk_clist_expose (GtkWidget * widget,
2548 GdkEventExpose * event)
2552 g_return_val_if_fail (widget != NULL, FALSE);
2553 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2554 g_return_val_if_fail (event != NULL, FALSE);
2556 if (GTK_WIDGET_DRAWABLE (widget))
2558 clist = GTK_CLIST (widget);
2561 if (event->window == widget->window)
2562 gtk_draw_shadow (widget->style, widget->window,
2563 GTK_STATE_NORMAL, clist->shadow_type,
2565 clist->clist_window_width + (2 * widget->style->klass->xthickness),
2566 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
2567 clist->column_title_area.height);
2569 /* exposure events on the list */
2570 if (event->window == clist->clist_window)
2571 draw_rows (clist, &event->area);
2578 gtk_clist_button_press (GtkWidget * widget,
2579 GdkEventButton * event)
2588 g_return_val_if_fail (widget != NULL, FALSE);
2589 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2590 g_return_val_if_fail (event != NULL, FALSE);
2592 clist = GTK_CLIST (widget);
2594 /* we don't handle button 2 and 3 */
2595 if (event->button != 1)
2598 /* selections on the list */
2599 if (event->window == clist->clist_window)
2604 if (get_selection_info (clist, x, y, &row, &column))
2606 gint old_row = clist->focus_row;
2607 gboolean no_focus_row = FALSE;
2609 if (clist->focus_row == -1)
2612 no_focus_row = TRUE;
2615 if (event->type == GDK_BUTTON_PRESS)
2617 GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION);
2618 gdk_pointer_grab (clist->clist_window, FALSE,
2619 GDK_POINTER_MOTION_HINT_MASK |
2620 GDK_BUTTON1_MOTION_MASK |
2621 GDK_BUTTON_RELEASE_MASK,
2622 NULL, NULL, event->time);
2624 else if (gdk_pointer_is_grabbed ())
2626 GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
2627 gdk_pointer_ungrab (event->time);
2630 if (GTK_CLIST_ADD_MODE (clist))
2632 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
2633 if (GTK_WIDGET_HAS_FOCUS (widget))
2635 gtk_clist_draw_focus (widget);
2636 gdk_gc_set_line_attributes (clist->xor_gc, 1,
2637 GDK_LINE_SOLID, 0, 0);
2638 clist->focus_row = row;
2639 gtk_clist_draw_focus (widget);
2643 gdk_gc_set_line_attributes (clist->xor_gc, 1,
2644 GDK_LINE_SOLID, 0, 0);
2645 clist->focus_row = row;
2648 else if (row != clist->focus_row)
2650 if (GTK_WIDGET_HAS_FOCUS (widget))
2652 gtk_clist_draw_focus (widget);
2653 clist->focus_row = row;
2654 gtk_clist_draw_focus (widget);
2657 clist->focus_row = row;
2660 if (!GTK_WIDGET_HAS_FOCUS (widget))
2661 gtk_widget_grab_focus (widget);
2663 switch (clist->selection_mode)
2665 case GTK_SELECTION_SINGLE:
2666 case GTK_SELECTION_MULTIPLE:
2667 if (event->type != GDK_BUTTON_PRESS)
2668 select_row (clist, row, column, (GdkEvent *) event);
2670 clist->anchor = row;
2673 case GTK_SELECTION_BROWSE:
2674 select_row (clist, row, column, (GdkEvent *) event);
2677 case GTK_SELECTION_EXTENDED:
2678 if (event->type != GDK_BUTTON_PRESS)
2680 if (clist->anchor != -1)
2682 update_extended_selection (clist, clist->focus_row);
2683 GTK_CLIST_CLASS_FW (clist)->resync_selection
2684 (clist, (GdkEvent *) event);
2686 select_row (clist, row, column, (GdkEvent *) event);
2690 if (event->state & GDK_CONTROL_MASK)
2692 if (event->state & GDK_SHIFT_MASK)
2694 set_anchor (clist, TRUE, old_row, old_row);
2695 update_extended_selection (clist, clist->focus_row);
2699 if (clist->anchor == -1)
2700 set_anchor (clist, TRUE, row, old_row);
2702 update_extended_selection (clist, clist->focus_row);
2707 if (event->state & GDK_SHIFT_MASK)
2709 set_anchor (clist, FALSE, old_row, old_row);
2710 update_extended_selection (clist, clist->focus_row);
2714 if (clist->anchor == -1)
2715 set_anchor (clist, FALSE, row, old_row);
2717 update_extended_selection (clist, clist->focus_row);
2728 /* press on resize windows */
2729 for (i = 0; i < clist->columns; i++)
2730 if (clist->column[i].window && event->window == clist->column[i].window)
2732 GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
2733 gtk_widget_get_pointer (widget, &clist->x_drag, NULL);
2735 gdk_pointer_grab (clist->column[i].window, FALSE,
2736 GDK_POINTER_MOTION_HINT_MASK |
2737 GDK_BUTTON1_MOTION_MASK |
2738 GDK_BUTTON_RELEASE_MASK,
2739 NULL, NULL, event->time);
2741 if (GTK_CLIST_ADD_MODE (clist))
2742 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
2744 draw_xor_line (clist);
2752 gtk_clist_button_release (GtkWidget * widget,
2753 GdkEventButton * event)
2755 gint i, x, width, visible;
2758 g_return_val_if_fail (widget != NULL, FALSE);
2759 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2760 g_return_val_if_fail (event != NULL, FALSE);
2762 clist = GTK_CLIST (widget);
2764 /* we don't handle button 2 and 3 */
2765 if (event->button != 1)
2768 /* release on resize windows */
2769 if (GTK_CLIST_IN_DRAG (clist))
2770 for (i = 0; i < clist->columns; i++)
2771 if (clist->column[i].window && event->window == clist->column[i].window)
2773 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
2774 gtk_widget_get_pointer (widget, &x, NULL);
2775 width = new_column_width (clist, i, &x, &visible);
2776 gdk_pointer_ungrab (event->time);
2779 draw_xor_line (clist);
2781 if (GTK_CLIST_ADD_MODE (clist))
2783 gdk_gc_set_line_attributes (clist->xor_gc, 1,
2784 GDK_LINE_ON_OFF_DASH, 0, 0);
2785 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
2788 resize_column (clist, i, width);
2792 if (GTK_CLIST_DRAG_SELECTION (clist))
2797 GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
2798 gdk_pointer_ungrab (event->time);
2801 gtk_timeout_remove (clist->htimer);
2806 gtk_timeout_remove (clist->vtimer);
2809 switch (clist->selection_mode)
2811 case GTK_SELECTION_EXTENDED:
2812 if (!(event->state & GDK_SHIFT_MASK) ||
2813 event->x < 0 || event->x >= clist->clist_window_width ||
2814 event->y < 0 || event->y >= clist->clist_window_height)
2815 GTK_CLIST_CLASS_FW (clist)->resync_selection
2816 (clist, (GdkEvent *) event);
2819 case GTK_SELECTION_SINGLE:
2820 case GTK_SELECTION_MULTIPLE:
2821 if (get_selection_info (clist, event->x, event->y, &row, &column))
2823 if (clist->anchor == clist->focus_row)
2824 toggle_row (clist, row, column, (GdkEvent *) event);
2838 horizontal_timeout (GtkCList *clist)
2841 GdkEventMotion event;
2842 GdkModifierType mask;
2844 g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
2847 gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
2854 gtk_clist_motion (GTK_WIDGET (clist), &event);
2860 vertical_timeout (GtkCList *clist)
2863 GdkEventMotion event;
2864 GdkModifierType mask;
2866 g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
2869 gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
2876 gtk_clist_motion (GTK_WIDGET (clist), &event);
2882 move_vertical (GtkCList *clist,
2889 adj = GTK_RANGE (clist->vscrollbar)->adjustment;
2891 y = ROW_TOP_YPIXEL (clist, row) - clist->voffset;
2893 y = y - align * (clist->clist_window_height - clist->row_height)
2894 + (2 * align - 1) * CELL_SPACING;
2896 if (y + adj->page_size > adj->upper)
2897 adj->value = adj->upper - adj->page_size;
2901 gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
2905 move_horizontal (GtkCList *clist,
2911 adj = GTK_RANGE (clist->hscrollbar)->adjustment;
2915 upper = adj->upper - adj->page_size;
2916 adj->value = MIN (adj->value, upper);
2917 adj->value = MAX (adj->value, 0.0);
2919 gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
2923 gtk_clist_motion (GtkWidget * widget,
2924 GdkEventMotion * event)
2926 gint i, x, y, visible;
2929 g_return_val_if_fail (widget != NULL, FALSE);
2930 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2932 clist = GTK_CLIST (widget);
2934 if (GTK_CLIST_IN_DRAG (clist))
2935 for (i = 0; i < clist->columns; i++)
2936 if (clist->column[i].window && event->window == clist->column[i].window)
2938 if (event->is_hint || event->window != widget->window)
2939 gtk_widget_get_pointer (widget, &x, NULL);
2943 new_column_width (clist, i, &x, &visible);
2944 /* Welcome to my hack! I'm going to use a value of x_drage = -99999 to
2945 * indicate the the xor line is already no visible */
2946 if (!visible && clist->x_drag != -99999)
2948 draw_xor_line (clist);
2949 clist->x_drag = -99999;
2952 if (x != clist->x_drag && visible)
2954 if (clist->x_drag != -99999)
2955 draw_xor_line (clist);
2958 draw_xor_line (clist);
2962 if (GTK_CLIST_DRAG_SELECTION (clist))
2966 if (event->is_hint || event->window != clist->clist_window)
2967 gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
2969 /* horizontal autoscrolling */
2970 if (LIST_WIDTH (clist) > clist->clist_window_width &&
2971 (x < 0 || x >= clist->clist_window_width))
2973 if (clist->htimer == 0)
2975 clist->htimer = gtk_timeout_add
2976 (SCROLL_TIME, (GtkFunction) horizontal_timeout, clist);
2978 if (!((x < 0 && GTK_RANGE (clist->hscrollbar)->adjustment->value
2979 == 0) || (x >= clist->clist_window_width &&
2980 GTK_RANGE (clist->hscrollbar)->adjustment->value ==
2981 LIST_WIDTH (clist) - clist->clist_window_width)))
2984 move_horizontal (clist, -1 + (x/2));
2986 move_horizontal (clist,
2987 1 + (x - clist->clist_window_width) / 2);
2994 row = ROW_FROM_YPIXEL (clist, y);
2996 /* don't scroll on last pixel row if it's a cell spacing */
2997 if (y == clist->clist_window_height-1 &&
2998 y == ROW_TOP_YPIXEL (clist, row-1) + clist->row_height)
3001 /* vertical autoscrolling */
3002 if (LIST_HEIGHT (clist) > clist->clist_window_height &&
3003 (y < 0 || y >= clist->clist_window_height))
3005 if (clist->vtimer == 0)
3007 clist->vtimer = gtk_timeout_add (SCROLL_TIME,
3008 (GtkFunction) vertical_timeout,
3011 if ((y < 0 && clist->focus_row == 0) ||
3012 (y >= clist->clist_window_height &&
3013 clist->focus_row == clist->rows-1))
3016 if (row < 0 && clist->focus_row > 0)
3018 gtk_clist_draw_focus (widget);
3019 clist->focus_row = 0;
3020 gtk_clist_draw_focus (widget);
3022 else if (row > clist->rows - 1 && clist->focus_row
3025 gtk_clist_draw_focus (widget);
3026 clist->focus_row = clist->rows - 1;
3027 gtk_clist_draw_focus (widget);
3029 else if (row >= 0 && row <= clist->rows - 1)
3031 gtk_clist_draw_focus (widget);
3032 clist->focus_row = row;
3033 gtk_clist_draw_focus (widget);
3038 switch (clist->selection_mode)
3040 case GTK_SELECTION_BROWSE:
3041 select_row (clist, clist->focus_row, -1, (GdkEvent *) event);
3044 case GTK_SELECTION_EXTENDED:
3045 update_extended_selection (clist, clist->focus_row);
3053 move_vertical (clist, row, 0);
3055 move_vertical (clist, row, 1);
3061 if (row == clist->focus_row)
3064 /* dragging inside clist_window */
3065 if (row < 0 && clist->focus_row > 0)
3067 gtk_clist_draw_focus (widget);
3068 clist->focus_row = 0;
3069 gtk_clist_draw_focus (widget);
3071 else if (row > clist->rows-1 && clist->focus_row < clist->rows-1)
3073 gtk_clist_draw_focus (widget);
3074 clist->focus_row = clist->rows-1;
3075 gtk_clist_draw_focus (widget);
3077 else if (row >= 0 && row <= clist->rows-1)
3079 gtk_clist_draw_focus (widget);
3080 clist->focus_row = row;
3081 gtk_clist_draw_focus (widget);
3086 switch (clist->selection_mode)
3088 case GTK_SELECTION_EXTENDED:
3089 update_extended_selection (clist, clist->focus_row);
3092 case GTK_SELECTION_BROWSE:
3093 select_row (clist, clist->focus_row, -1, (GdkEvent *) event);
3100 if (ROW_TOP_YPIXEL(clist, clist->focus_row) + clist->row_height <= 0)
3101 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
3102 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
3103 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
3104 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) >=
3105 clist->clist_window_height)
3106 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
3107 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
3108 clist->clist_window_height)
3109 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
3115 gtk_clist_size_request (GtkWidget * widget,
3116 GtkRequisition * requisition)
3121 g_return_if_fail (widget != NULL);
3122 g_return_if_fail (GTK_IS_CLIST (widget));
3123 g_return_if_fail (requisition != NULL);
3125 clist = GTK_CLIST (widget);
3127 add_style_data (clist);
3129 requisition->width = 0;
3130 requisition->height = 0;
3132 /* compute the size of the column title (title) area */
3133 clist->column_title_area.height = 0;
3134 if (GTK_CLIST_SHOW_TITLES (clist))
3135 for (i = 0; i < clist->columns; i++)
3136 if (clist->column[i].button)
3138 gtk_widget_size_request (clist->column[i].button, &clist->column[i].button->requisition);
3139 clist->column_title_area.height = MAX (clist->column_title_area.height,
3140 clist->column[i].button->requisition.height);
3142 requisition->height += clist->column_title_area.height;
3144 /* add the vscrollbar space */
3145 if ((clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
3146 GTK_WIDGET_VISIBLE (clist->vscrollbar))
3148 gtk_widget_size_request (clist->vscrollbar, &clist->vscrollbar->requisition);
3150 requisition->width += clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist);
3151 requisition->height = MAX (requisition->height,
3152 clist->vscrollbar->requisition.height);
3155 /* add the hscrollbar space */
3156 if ((clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
3157 GTK_WIDGET_VISIBLE (clist->hscrollbar))
3159 gtk_widget_size_request (clist->hscrollbar, &clist->hscrollbar->requisition);
3161 requisition->height += clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist);
3162 requisition->width = MAX (clist->hscrollbar->requisition.width,
3163 requisition->width -
3164 clist->vscrollbar->requisition.width);
3168 requisition->width += widget->style->klass->xthickness * 2 +
3169 GTK_CONTAINER (widget)->border_width * 2;
3170 requisition->height += widget->style->klass->ythickness * 2 +
3171 GTK_CONTAINER (widget)->border_width * 2;
3175 gtk_clist_size_allocate (GtkWidget * widget,
3176 GtkAllocation * allocation)
3179 GtkAllocation clist_allocation;
3180 GtkAllocation child_allocation;
3181 gint i, vscrollbar_vis, hscrollbar_vis;
3183 g_return_if_fail (widget != NULL);
3184 g_return_if_fail (GTK_IS_CLIST (widget));
3185 g_return_if_fail (allocation != NULL);
3187 clist = GTK_CLIST (widget);
3188 widget->allocation = *allocation;
3190 if (GTK_WIDGET_REALIZED (widget))
3192 gdk_window_move_resize (widget->window,
3193 allocation->x + GTK_CONTAINER (widget)->border_width,
3194 allocation->y + GTK_CONTAINER (widget)->border_width,
3195 allocation->width - GTK_CONTAINER (widget)->border_width * 2,
3196 allocation->height - GTK_CONTAINER (widget)->border_width * 2);
3199 /* use internal allocation structure for all the math
3200 * because it's easier than always subtracting the container
3202 clist->internal_allocation.x = 0;
3203 clist->internal_allocation.y = 0;
3204 clist->internal_allocation.width = MAX (1, allocation->width -
3205 GTK_CONTAINER (widget)->border_width * 2);
3206 clist->internal_allocation.height = MAX (1, allocation->height -
3207 GTK_CONTAINER (widget)->border_width * 2);
3209 /* allocate clist window assuming no scrollbars */
3210 clist_allocation.x = clist->internal_allocation.x + widget->style->klass->xthickness;
3211 clist_allocation.y = clist->internal_allocation.y + widget->style->klass->ythickness +
3212 clist->column_title_area.height;
3213 clist_allocation.width = MAX (1, clist->internal_allocation.width -
3214 (2 * widget->style->klass->xthickness));
3215 clist_allocation.height = MAX (1, clist->internal_allocation.height -
3216 (2 * widget->style->klass->ythickness) -
3217 clist->column_title_area.height);
3220 * here's where we decide to show/not show the scrollbars
3225 for (i = 0; i <= 1; i++)
3227 if (LIST_HEIGHT (clist) <= clist_allocation.height &&
3228 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
3234 if (!vscrollbar_vis)
3237 clist_allocation.width = MAX (1, clist_allocation.width -
3238 (clist->vscrollbar->requisition.width +
3239 SCROLLBAR_SPACING (clist)));
3243 if (LIST_WIDTH (clist) <= clist_allocation.width &&
3244 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
3250 if (!hscrollbar_vis)
3253 clist_allocation.height = MAX (1, clist_allocation.height -
3254 (clist->hscrollbar->requisition.height +
3255 SCROLLBAR_SPACING (clist)));
3260 clist->clist_window_width = clist_allocation.width;
3261 clist->clist_window_height = clist_allocation.height;
3263 if (GTK_WIDGET_REALIZED (widget))
3265 gdk_window_move_resize (clist->clist_window,
3268 clist_allocation.width,
3269 clist_allocation.height);
3272 /* position the window which holds the column title buttons */
3273 clist->column_title_area.x = widget->style->klass->xthickness;
3274 clist->column_title_area.y = widget->style->klass->ythickness;
3275 clist->column_title_area.width = clist_allocation.width;
3277 if (GTK_WIDGET_REALIZED (widget))
3279 gdk_window_move_resize (clist->title_window,
3280 clist->column_title_area.x,
3281 clist->column_title_area.y,
3282 clist->column_title_area.width,
3283 clist->column_title_area.height);
3286 /* column button allocation */
3287 size_allocate_columns (clist);
3289 if (GTK_WIDGET_REALIZED (widget))
3290 size_allocate_title_buttons (clist);
3292 adjust_scrollbars (clist);
3294 /* allocate the vscrollbar */
3297 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
3298 gtk_widget_show (clist->vscrollbar);
3300 child_allocation.x = clist->internal_allocation.x +
3301 clist->internal_allocation.width -
3302 clist->vscrollbar->requisition.width;
3303 child_allocation.y = clist->internal_allocation.y;
3304 child_allocation.width = clist->vscrollbar->requisition.width;
3305 child_allocation.height = MAX (1, clist->internal_allocation.height -
3306 (hscrollbar_vis ? (clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist)) : 0));
3308 gtk_widget_size_allocate (clist->vscrollbar, &child_allocation);
3312 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
3313 gtk_widget_hide (clist->vscrollbar);
3318 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
3319 gtk_widget_show (clist->hscrollbar);
3321 child_allocation.x = clist->internal_allocation.x;
3322 child_allocation.y = clist->internal_allocation.y +
3323 clist->internal_allocation.height -
3324 clist->hscrollbar->requisition.height;
3325 child_allocation.width = MAX (1, clist->internal_allocation.width -
3326 (vscrollbar_vis ? (clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist)) : 0));
3327 child_allocation.height = clist->hscrollbar->requisition.height;
3329 gtk_widget_size_allocate (clist->hscrollbar, &child_allocation);
3333 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
3334 gtk_widget_hide (clist->hscrollbar);
3337 /* set the vscrollbar adjustments */
3338 adjust_scrollbars (clist);
3346 gtk_clist_foreach (GtkContainer * container,
3347 GtkCallback callback,
3348 gpointer callback_data)
3353 g_return_if_fail (container != NULL);
3354 g_return_if_fail (GTK_IS_CLIST (container));
3355 g_return_if_fail (callback != NULL);
3357 clist = GTK_CLIST (container);
3359 /* callback for the column buttons */
3360 for (i = 0; i < clist->columns; i++)
3361 if (clist->column[i].button)
3362 (*callback) (clist->column[i].button, callback_data);
3364 /* callbacks for the scrollbars */
3365 if (clist->vscrollbar)
3366 (*callback) (clist->vscrollbar, callback_data);
3367 if (clist->hscrollbar)
3368 (*callback) (clist->hscrollbar, callback_data);
3377 draw_row (GtkCList * clist,
3378 GdkRectangle * area,
3380 GtkCListRow * clist_row)
3383 GdkGC *fg_gc, *bg_gc;
3384 GdkRectangle row_rectangle, cell_rectangle, clip_rectangle, intersect_rectangle,
3386 gint i, offset = 0, width, height, pixmap_width = 0;
3387 gint xsrc, ysrc, xdest, ydest;
3389 g_return_if_fail (clist != NULL);
3391 /* bail now if we arn't drawable yet */
3392 if (!GTK_WIDGET_DRAWABLE (clist))
3395 if (row < 0 || row >= clist->rows)
3398 widget = GTK_WIDGET (clist);
3400 /* if the function is passed the pointer to the row instead of null,
3401 * it avoids this expensive lookup */
3403 clist_row = (g_list_nth (clist->row_list, row))->data;
3405 /* rectangle of the entire row */
3406 row_rectangle.x = 0;
3407 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
3408 row_rectangle.width = clist->clist_window_width;
3409 row_rectangle.height = clist->row_height;
3411 /* rectangle of the cell spacing above the row */
3412 cell_rectangle.x = 0;
3413 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
3414 cell_rectangle.width = row_rectangle.width;
3415 cell_rectangle.height = CELL_SPACING;
3417 /* rectangle used to clip drawing operations, it's y and height
3418 * positions only need to be set once, so we set them once here.
3419 * the x and width are set withing the drawing loop below once per
3421 clip_rectangle.y = row_rectangle.y;
3422 clip_rectangle.height = row_rectangle.height;
3424 /* select GC for background rectangle */
3425 if (clist_row->state == GTK_STATE_SELECTED)
3427 fg_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
3428 bg_gc = widget->style->bg_gc[GTK_STATE_SELECTED];
3432 if (clist_row->fg_set)
3434 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
3435 fg_gc = clist->fg_gc;
3438 fg_gc = widget->style->fg_gc[GTK_STATE_NORMAL];
3440 if (clist_row->bg_set)
3442 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
3443 bg_gc = clist->bg_gc;
3446 bg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
3449 /* draw the cell borders and background */
3452 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
3453 gdk_draw_rectangle (clist->clist_window,
3454 widget->style->base_gc[GTK_STATE_NORMAL],
3456 intersect_rectangle.x,
3457 intersect_rectangle.y,
3458 intersect_rectangle.width,
3459 intersect_rectangle.height);
3461 /* the last row has to clear it's bottom cell spacing too */
3462 if (clist_row == clist->row_list_end->data)
3464 cell_rectangle.y += clist->row_height + CELL_SPACING;
3466 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
3467 gdk_draw_rectangle (clist->clist_window,
3468 widget->style->base_gc[GTK_STATE_NORMAL],
3470 intersect_rectangle.x,
3471 intersect_rectangle.y,
3472 intersect_rectangle.width,
3473 intersect_rectangle.height);
3476 if (!gdk_rectangle_intersect (area, &row_rectangle, &intersect_rectangle))
3479 if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
3480 gdk_draw_rectangle (clist->clist_window,
3483 intersect_rectangle.x,
3484 intersect_rectangle.y,
3485 intersect_rectangle.width,
3486 intersect_rectangle.height);
3488 gdk_window_clear_area (clist->clist_window,
3489 intersect_rectangle.x,
3490 intersect_rectangle.y,
3491 intersect_rectangle.width,
3492 intersect_rectangle.height);
3496 gdk_draw_rectangle (clist->clist_window,
3497 widget->style->base_gc[GTK_STATE_NORMAL],
3501 cell_rectangle.width,
3502 cell_rectangle.height);
3504 /* the last row has to clear it's bottom cell spacing too */
3505 if (clist_row == clist->row_list_end->data)
3507 cell_rectangle.y += clist->row_height + CELL_SPACING;
3509 gdk_draw_rectangle (clist->clist_window,
3510 widget->style->base_gc[GTK_STATE_NORMAL],
3514 cell_rectangle.width,
3515 cell_rectangle.height);
3518 if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
3519 gdk_draw_rectangle (clist->clist_window,
3524 row_rectangle.width,
3525 row_rectangle.height);
3527 gdk_window_clear_area (clist->clist_window,
3530 row_rectangle.width,
3531 row_rectangle.height);
3534 /* iterate and draw all the columns (row cells) and draw their contents */
3535 for (i = 0; i < clist->columns; i++)
3537 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
3538 clip_rectangle.width = clist->column[i].area.width;
3540 /* calculate clipping region clipping region */
3543 rect = &clip_rectangle;
3547 if (!gdk_rectangle_intersect (area, &clip_rectangle,
3548 &intersect_rectangle))
3550 rect = &intersect_rectangle;
3553 /* calculate real width for column justification */
3554 switch (clist_row->cell[i].type)
3556 case GTK_CELL_EMPTY:
3561 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
3562 GTK_CELL_TEXT (clist_row->cell[i])->text);
3565 case GTK_CELL_PIXMAP:
3566 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &width, &height);
3567 pixmap_width = width;
3570 case GTK_CELL_PIXTEXT:
3571 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap, &width, &height);
3572 pixmap_width = width;
3573 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
3574 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
3575 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
3578 case GTK_CELL_WIDGET:
3588 switch (clist->column[i].justification)
3590 case GTK_JUSTIFY_LEFT:
3591 offset = clip_rectangle.x;
3594 case GTK_JUSTIFY_RIGHT:
3595 offset = (clip_rectangle.x + clip_rectangle.width) - width;
3598 case GTK_JUSTIFY_CENTER:
3599 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
3602 case GTK_JUSTIFY_FILL:
3603 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
3611 /* Draw Text or Pixmap */
3612 switch (clist_row->cell[i].type)
3614 case GTK_CELL_EMPTY:
3619 gdk_gc_set_clip_rectangle (fg_gc, rect);
3621 gdk_draw_string (clist->clist_window,
3622 widget->style->font,
3624 offset + clist_row->cell[i].horizontal,
3625 row_rectangle.y + clist->row_center_offset +
3626 clist_row->cell[i].vertical,
3627 GTK_CELL_TEXT (clist_row->cell[i])->text);
3629 gdk_gc_set_clip_rectangle (fg_gc, NULL);
3632 case GTK_CELL_PIXMAP:
3635 xdest = offset + clist_row->cell[i].horizontal;
3636 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
3637 clist_row->cell[i].vertical;
3639 if (xdest < clip_rectangle.x)
3641 xsrc = clip_rectangle.x - xdest;
3642 pixmap_width -= xsrc;
3643 xdest = clip_rectangle.x;
3646 if (xdest + pixmap_width > clip_rectangle.x + clip_rectangle.width)
3647 pixmap_width = (clip_rectangle.x + clip_rectangle.width) - xdest;
3649 if (ydest < clip_rectangle.y)
3651 ysrc = clip_rectangle.y - ydest;
3653 ydest = clip_rectangle.y;
3656 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
3657 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
3659 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
3661 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXMAP (clist_row->cell[i])->mask);
3662 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
3664 gdk_draw_pixmap (clist->clist_window,
3666 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
3669 pixmap_width, height);
3671 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
3673 gdk_gc_set_clip_origin (fg_gc, 0, 0);
3674 gdk_gc_set_clip_mask (fg_gc, NULL);
3678 case GTK_CELL_PIXTEXT:
3679 /* draw the pixmap */
3682 xdest = offset + clist_row->cell[i].horizontal;
3683 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
3684 clist_row->cell[i].vertical;
3686 if (xdest < clip_rectangle.x)
3688 xsrc = clip_rectangle.x - xdest;
3689 pixmap_width -= xsrc;
3690 xdest = clip_rectangle.x;
3693 if (xdest + pixmap_width > clip_rectangle.x + clip_rectangle.width)
3694 pixmap_width = (clip_rectangle.x + clip_rectangle.width) - xdest;
3696 if (ydest < clip_rectangle.y)
3698 ysrc = clip_rectangle.y - ydest;
3700 ydest = clip_rectangle.y;
3703 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
3704 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
3706 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask)
3708 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
3709 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
3712 gdk_draw_pixmap (clist->clist_window,
3714 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
3718 pixmap_width, height);
3720 gdk_gc_set_clip_origin (fg_gc, 0, 0);
3722 offset += pixmap_width + GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
3724 /* draw the string */
3725 gdk_gc_set_clip_rectangle (fg_gc, rect);
3727 gdk_draw_string (clist->clist_window,
3728 widget->style->font,
3730 offset + clist_row->cell[i].horizontal,
3731 row_rectangle.y + clist->row_center_offset +
3732 clist_row->cell[i].vertical,
3733 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
3735 gdk_gc_set_clip_rectangle (fg_gc, NULL);
3738 case GTK_CELL_WIDGET:
3748 if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget))
3752 if (gdk_rectangle_intersect (area, &row_rectangle,
3753 &intersect_rectangle))
3755 gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
3756 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
3757 row_rectangle.x, row_rectangle.y,
3758 row_rectangle.width - 1,
3759 row_rectangle.height - 1);
3760 gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
3764 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
3765 row_rectangle.x, row_rectangle.y,
3766 row_rectangle.width - 1, row_rectangle.height - 1);
3771 draw_rows (GtkCList * clist,
3772 GdkRectangle * area)
3775 GtkCListRow *clist_row;
3776 int i, first_row, last_row;
3778 g_return_if_fail (clist != NULL);
3779 g_return_if_fail (GTK_IS_CLIST (clist));
3781 if (clist->row_height == 0 ||
3782 !GTK_WIDGET_DRAWABLE (clist))
3787 first_row = ROW_FROM_YPIXEL (clist, area->y);
3788 last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
3792 first_row = ROW_FROM_YPIXEL (clist, 0);
3793 last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
3796 /* this is a small special case which exposes the bottom cell line
3797 * on the last row -- it might go away if I change the wall the cell spacings
3799 if (clist->rows == first_row)
3802 list = g_list_nth (clist->row_list, first_row);
3806 clist_row = list->data;
3812 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, area, i, clist_row);
3817 gdk_window_clear_area (clist->clist_window, 0, ROW_TOP_YPIXEL (clist, i), -1, -1);
3822 * size_allocate_title_buttons
3823 * size_allocate_columns
3826 size_allocate_title_buttons (GtkCList * clist)
3828 gint i, last_button = 0;
3829 GtkAllocation button_allocation;
3831 if (!GTK_WIDGET_REALIZED (clist))
3834 button_allocation.x = clist->hoffset;
3835 button_allocation.y = 0;
3836 button_allocation.width = 0;
3837 button_allocation.height = clist->column_title_area.height;
3839 for (i = 0; i < clist->columns; i++)
3841 button_allocation.width += clist->column[i].area.width;
3843 if (i == clist->columns - 1)
3844 button_allocation.width += 2 * (CELL_SPACING + COLUMN_INSET);
3846 button_allocation.width += CELL_SPACING + (2 * COLUMN_INSET);
3848 if (i == (clist->columns - 1) || clist->column[i + 1].button)
3850 gtk_widget_size_allocate (clist->column[last_button].button, &button_allocation);
3851 button_allocation.x += button_allocation.width;
3852 button_allocation.width = 0;
3854 gdk_window_show (clist->column[last_button].window);
3855 gdk_window_move_resize (clist->column[last_button].window,
3856 button_allocation.x - (DRAG_WIDTH / 2),
3857 0, DRAG_WIDTH, clist->column_title_area.height);
3859 last_button = i + 1;
3863 gdk_window_hide (clist->column[i].window);
3869 size_allocate_columns (GtkCList * clist)
3871 gint i, xoffset = 0;
3873 for (i = 0; i < clist->columns; i++)
3875 clist->column[i].area.x = xoffset + CELL_SPACING + COLUMN_INSET;
3877 if (i == clist->columns - 1)
3881 if (clist->column[i].width_set)
3883 width = clist->column[i].width;
3887 if (clist->column[i].title)
3888 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
3889 clist->column[i].title);
3894 clist->column[i].area.width = MAX (width,
3895 clist->clist_window_width -
3896 xoffset - (2 * (CELL_SPACING + COLUMN_INSET)));
3901 clist->column[i].area.width = clist->column[i].width;
3904 xoffset += clist->column[i].area.width + CELL_SPACING + (2 * COLUMN_INSET);
3913 * get_selection_info
3916 toggle_row (GtkCList * clist,
3921 GtkCListRow *clist_row;
3923 switch (clist->selection_mode)
3925 case GTK_SELECTION_EXTENDED:
3926 case GTK_SELECTION_MULTIPLE:
3927 case GTK_SELECTION_SINGLE:
3929 clist_row = g_list_nth (clist->row_list, row)->data;
3930 if (clist_row->state == GTK_STATE_SELECTED)
3932 unselect_row (clist, row, column, event);
3936 case GTK_SELECTION_BROWSE:
3937 select_row (clist, row, column, event);
3943 select_row (GtkCList * clist,
3948 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3949 row, column, event);
3953 unselect_row (GtkCList * clist,
3958 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3959 row, column, event);
3963 real_select_row (GtkCList * clist,
3968 GtkCListRow *clist_row;
3971 gboolean row_selected;
3973 g_return_if_fail (clist != NULL);
3974 g_return_if_fail (GTK_IS_CLIST (clist));
3976 if (row < 0 || row > (clist->rows - 1))
3979 switch (clist->selection_mode)
3981 case GTK_SELECTION_SINGLE:
3982 case GTK_SELECTION_BROWSE:
3984 row_selected = FALSE;
3985 list = clist->selection;
3989 sel_row = GPOINTER_TO_INT (list->data);
3993 row_selected = TRUE;
3995 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3996 sel_row, column, event);
4006 clist_row = (g_list_nth (clist->row_list, row))->data;
4008 if (clist_row->state != GTK_STATE_NORMAL)
4011 clist_row->state = GTK_STATE_SELECTED;
4012 if (!clist->selection)
4014 clist->selection = g_list_append (clist->selection,
4015 GINT_TO_POINTER (row));
4016 clist->selection_end = clist->selection;
4019 clist->selection_end =
4020 g_list_append (clist->selection_end, GINT_TO_POINTER (row))->next;
4022 if (!GTK_CLIST_FROZEN (clist)
4023 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
4024 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
4028 real_unselect_row (GtkCList * clist,
4033 GtkCListRow *clist_row;
4035 g_return_if_fail (clist != NULL);
4036 g_return_if_fail (GTK_IS_CLIST (clist));
4038 if (row < 0 || row > (clist->rows - 1))
4041 clist_row = (g_list_nth (clist->row_list, row))->data;
4043 if (clist_row->state == GTK_STATE_SELECTED)
4045 clist_row->state = GTK_STATE_NORMAL;
4047 if (clist->selection_end &&
4048 clist->selection_end->data == GINT_TO_POINTER (row))
4049 clist->selection_end = clist->selection_end->prev;
4051 clist->selection = g_list_remove (clist->selection,
4052 GINT_TO_POINTER (row));
4054 if (!GTK_CLIST_FROZEN (clist)
4055 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
4056 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
4061 get_selection_info (GtkCList * clist,
4069 g_return_val_if_fail (clist != NULL, 0);
4070 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
4072 /* bounds checking, return false if the user clicked
4073 * on a blank area */
4074 trow = ROW_FROM_YPIXEL (clist, y);
4075 if (trow >= clist->rows)
4081 tcol = COLUMN_FROM_XPIXEL (clist, x);
4082 if (tcol >= clist->columns)
4092 gtk_clist_get_selection_info (GtkCList *clist,
4098 g_return_val_if_fail (clist != NULL, 0);
4099 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
4100 return get_selection_info (clist, x, y, row, column);
4110 draw_xor_line (GtkCList * clist)
4114 g_return_if_fail (clist != NULL);
4116 widget = GTK_WIDGET (clist);
4118 gdk_draw_line (widget->window, clist->xor_gc,
4120 widget->style->klass->ythickness,
4122 clist->column_title_area.height + clist->clist_window_height + 1);
4125 /* this function returns the new width of the column being resized given
4126 * the column and x position of the cursor; the x cursor position is passed
4127 * in as a pointer and automagicly corrected if it's beyond min/max limits */
4129 new_column_width (GtkCList * clist,
4138 /* first translate the x position from widget->window
4139 * to clist->clist_window */
4140 cx -= GTK_WIDGET (clist)->style->klass->xthickness;
4142 /* rx is x from the list beginning */
4143 rx = cx - clist->hoffset;
4145 /* you can't shrink a column to less than its minimum width */
4146 if (cx < (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH))
4148 *x = cx = COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH +
4149 GTK_WIDGET (clist)->style->klass->xthickness;
4150 cx -= GTK_WIDGET (clist)->style->klass->xthickness;
4151 rx = cx - clist->hoffset;
4154 if (cx > clist->clist_window_width)
4159 /* calculate new column width making sure it doesn't end up
4160 * less than the minimum width */
4161 width = (rx - COLUMN_LEFT (clist, column)) - COLUMN_INSET -
4162 ((clist->columns == (column - 1)) ? CELL_SPACING : 0);
4163 if (width < COLUMN_MIN_WIDTH)
4164 width = COLUMN_MIN_WIDTH;
4169 /* this will do more later */
4171 resize_column (GtkCList * clist,
4175 gtk_clist_set_column_width (clist, column, width);
4180 column_button_create (GtkCList * clist,
4185 button = clist->column[column].button = gtk_button_new ();
4186 gtk_widget_set_parent (button, GTK_WIDGET (clist));
4187 if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
4188 gtk_widget_set_parent_window (clist->column[column].button, clist->title_window);
4190 gtk_signal_connect (GTK_OBJECT (button), "clicked",
4191 (GtkSignalFunc) column_button_clicked,
4194 gtk_widget_show (button);
4198 column_button_clicked (GtkWidget * widget,
4204 g_return_if_fail (widget != NULL);
4205 g_return_if_fail (GTK_IS_CLIST (data));
4207 clist = GTK_CLIST (data);
4209 /* find the column who's button was pressed */
4210 for (i = 0; i < clist->columns; i++)
4211 if (clist->column[i].button == widget)
4214 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
4223 * vadjustment_changed
4224 * hadjustment_changed
4225 * vadjustment_value_changed
4226 * hadjustment_value_changed
4229 create_scrollbars (GtkCList * clist)
4231 GtkAdjustment *adjustment;
4233 clist->vscrollbar = gtk_vscrollbar_new (NULL);
4235 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
4237 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
4238 (GtkSignalFunc) vadjustment_changed,
4241 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
4242 (GtkSignalFunc) vadjustment_value_changed,
4245 gtk_widget_set_parent (clist->vscrollbar, GTK_WIDGET (clist));
4246 gtk_widget_show (clist->vscrollbar);
4248 clist->hscrollbar = gtk_hscrollbar_new (NULL);
4250 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
4252 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
4253 (GtkSignalFunc) hadjustment_changed,
4256 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
4257 (GtkSignalFunc) hadjustment_value_changed,
4260 gtk_widget_set_parent (clist->hscrollbar, GTK_WIDGET (clist));
4261 gtk_widget_show (clist->hscrollbar);
4265 adjust_scrollbars (GtkCList * clist)
4267 GTK_RANGE (clist->vscrollbar)->adjustment->page_size = clist->clist_window_height;
4268 GTK_RANGE (clist->vscrollbar)->adjustment->page_increment = clist->clist_window_height / 2;
4269 GTK_RANGE (clist->vscrollbar)->adjustment->step_increment = 10;
4270 GTK_RANGE (clist->vscrollbar)->adjustment->lower = 0;
4271 GTK_RANGE (clist->vscrollbar)->adjustment->upper = LIST_HEIGHT (clist);
4273 if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
4275 GTK_RANGE (clist->vscrollbar)->adjustment->value = MAX (0, LIST_HEIGHT (clist) -
4276 clist->clist_window_height);
4277 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
4281 GTK_RANGE (clist->hscrollbar)->adjustment->page_size = clist->clist_window_width;
4282 GTK_RANGE (clist->hscrollbar)->adjustment->page_increment = clist->clist_window_width / 2;
4283 GTK_RANGE (clist->hscrollbar)->adjustment->step_increment = 10;
4284 GTK_RANGE (clist->hscrollbar)->adjustment->lower = 0;
4285 GTK_RANGE (clist->hscrollbar)->adjustment->upper = LIST_WIDTH (clist);
4287 if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
4289 GTK_RANGE (clist->hscrollbar)->adjustment->value = MAX (0, LIST_WIDTH (clist) -
4290 clist->clist_window_width);
4291 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
4295 if (LIST_HEIGHT (clist) <= clist->clist_window_height &&
4296 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
4298 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
4300 gtk_widget_hide (clist->vscrollbar);
4301 gtk_widget_queue_resize (GTK_WIDGET (clist));
4306 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
4308 gtk_widget_show (clist->vscrollbar);
4309 gtk_widget_queue_resize (GTK_WIDGET (clist));
4313 if (LIST_WIDTH (clist) <= clist->clist_window_width &&
4314 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
4316 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
4318 gtk_widget_hide (clist->hscrollbar);
4319 gtk_widget_queue_resize (GTK_WIDGET (clist));
4324 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
4326 gtk_widget_show (clist->hscrollbar);
4327 gtk_widget_queue_resize (GTK_WIDGET (clist));
4331 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
4332 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment), "changed");
4336 vadjustment_changed (GtkAdjustment * adjustment,
4341 g_return_if_fail (adjustment != NULL);
4342 g_return_if_fail (data != NULL);
4344 clist = GTK_CLIST (data);
4348 hadjustment_changed (GtkAdjustment * adjustment,
4353 g_return_if_fail (adjustment != NULL);
4354 g_return_if_fail (data != NULL);
4356 clist = GTK_CLIST (data);
4360 check_exposures (GtkCList *clist)
4364 if (!GTK_WIDGET_REALIZED (clist))
4367 /* Make sure graphics expose events are processed before scrolling
4369 while ((event = gdk_event_get_graphics_expose (clist->clist_window)) != NULL)
4371 gtk_widget_event (GTK_WIDGET (clist), event);
4372 if (event->expose.count == 0)
4374 gdk_event_free (event);
4377 gdk_event_free (event);
4382 vadjustment_value_changed (GtkAdjustment * adjustment,
4389 g_return_if_fail (adjustment != NULL);
4390 g_return_if_fail (data != NULL);
4391 g_return_if_fail (GTK_IS_CLIST (data));
4393 clist = GTK_CLIST (data);
4395 if (!GTK_WIDGET_DRAWABLE (clist))
4398 value = adjustment->value;
4400 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar)))
4402 if (value > -clist->voffset)
4405 diff = value + clist->voffset;
4407 /* we have to re-draw the whole screen here... */
4408 if (diff >= clist->clist_window_height)
4410 clist->voffset = -value;
4411 draw_rows (clist, NULL);
4415 if ((diff != 0) && (diff != clist->clist_window_height))
4416 gdk_window_copy_area (clist->clist_window,
4419 clist->clist_window,
4422 clist->clist_window_width,
4423 clist->clist_window_height - diff);
4426 area.y = clist->clist_window_height - diff;
4427 area.width = clist->clist_window_width;
4433 diff = -clist->voffset - value;
4435 /* we have to re-draw the whole screen here... */
4436 if (diff >= clist->clist_window_height)
4438 clist->voffset = -value;
4439 draw_rows (clist, NULL);
4443 if ((diff != 0) && (diff != clist->clist_window_height))
4444 gdk_window_copy_area (clist->clist_window,
4447 clist->clist_window,
4450 clist->clist_window_width,
4451 clist->clist_window_height - diff);
4455 area.width = clist->clist_window_width;
4460 clist->voffset = -value;
4461 if ((diff != 0) && (diff != clist->clist_window_height))
4462 check_exposures (clist);
4465 draw_rows (clist, &area);
4469 hadjustment_value_changed (GtkAdjustment * adjustment,
4479 g_return_if_fail (adjustment != NULL);
4480 g_return_if_fail (data != NULL);
4481 g_return_if_fail (GTK_IS_CLIST (data));
4483 clist = GTK_CLIST (data);
4485 if (!GTK_WIDGET_DRAWABLE (clist) ||
4486 adjustment != gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar)))
4489 value = adjustment->value;
4491 /* move the column buttons and resize windows */
4492 for (i = 0; i < clist->columns; i++)
4494 if (clist->column[i].button)
4496 clist->column[i].button->allocation.x -= value + clist->hoffset;
4498 if (clist->column[i].button->window)
4500 gdk_window_move (clist->column[i].button->window,
4501 clist->column[i].button->allocation.x,
4502 clist->column[i].button->allocation.y);
4504 if (clist->column[i].window)
4505 gdk_window_move (clist->column[i].window,
4506 clist->column[i].button->allocation.x +
4507 clist->column[i].button->allocation.width -
4508 (DRAG_WIDTH / 2), 0);
4513 if (value > -clist->hoffset)
4516 diff = value + clist->hoffset;
4518 clist->hoffset = -value;
4520 /* we have to re-draw the whole screen here... */
4521 if (diff >= clist->clist_window_width)
4523 draw_rows (clist, NULL);
4527 if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
4528 GTK_CLIST_ADD_MODE (clist))
4530 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
4532 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
4533 clist->clist_window_width - 1,
4534 clist->row_height - 1);
4536 gdk_window_copy_area (clist->clist_window,
4539 clist->clist_window,
4542 clist->clist_window_width - diff,
4543 clist->clist_window_height);
4545 area.x = clist->clist_window_width - diff;
4550 if (!(diff = -clist->hoffset - value))
4553 clist->hoffset = -value;
4555 /* we have to re-draw the whole screen here... */
4556 if (diff >= clist->clist_window_width)
4558 draw_rows (clist, NULL);
4562 if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
4563 GTK_CLIST_ADD_MODE (clist))
4565 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
4567 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
4568 clist->clist_window_width - 1,
4569 clist->row_height - 1);
4572 gdk_window_copy_area (clist->clist_window,
4575 clist->clist_window,
4578 clist->clist_window_width - diff,
4579 clist->clist_window_height);
4586 area.height = clist->clist_window_height;
4588 check_exposures (clist);
4590 if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist))
4592 if (GTK_CLIST_ADD_MODE (clist))
4596 focus_row = clist->focus_row;
4597 clist->focus_row = -1;
4598 draw_rows (clist, &area);
4599 clist->focus_row = focus_row;
4601 gdk_draw_rectangle (clist->clist_window, clist->xor_gc,
4602 FALSE, 0, y, clist->clist_window_width - 1,
4603 clist->row_height - 1);
4613 x0 = clist->clist_window_width - 1;
4622 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
4623 gdk_draw_line (clist->clist_window, clist->xor_gc,
4624 x0, y + 1, x0, y + clist->row_height - 2);
4625 gdk_draw_line (clist->clist_window, clist->xor_gc,
4626 x1, y + 1, x1, y + clist->row_height - 2);
4630 draw_rows (clist, &area);
4634 * Memory Allocation/Distruction Routines for GtkCList stuctures
4646 static GtkCListColumn *
4647 columns_new (GtkCList * clist)
4650 GtkCListColumn *column;
4652 column = g_new (GtkCListColumn, clist->columns);
4654 for (i = 0; i < clist->columns; i++)
4656 column[i].area.x = 0;
4657 column[i].area.y = 0;
4658 column[i].area.width = 0;
4659 column[i].area.height = 0;
4660 column[i].title = NULL;
4661 column[i].button = NULL;
4662 column[i].window = NULL;
4663 column[i].width = 0;
4664 column[i].width_set = FALSE;
4665 column[i].justification = GTK_JUSTIFY_LEFT;
4672 column_title_new (GtkCList * clist,
4676 if (clist->column[column].title)
4677 g_free (clist->column[column].title);
4679 clist->column[column].title = g_strdup (title);
4683 columns_delete (GtkCList * clist)
4687 for (i = 0; i < clist->columns; i++)
4688 if (clist->column[i].title)
4689 g_free (clist->column[i].title);
4691 g_free (clist->column);
4694 static GtkCListRow *
4695 row_new (GtkCList * clist)
4698 GtkCListRow *clist_row;
4700 clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
4701 clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
4703 for (i = 0; i < clist->columns; i++)
4705 clist_row->cell[i].type = GTK_CELL_EMPTY;
4706 clist_row->cell[i].vertical = 0;
4707 clist_row->cell[i].horizontal = 0;
4710 clist_row->fg_set = FALSE;
4711 clist_row->bg_set = FALSE;
4712 clist_row->state = GTK_STATE_NORMAL;
4713 clist_row->data = NULL;
4714 clist_row->destroy = NULL;
4720 row_delete (GtkCList * clist,
4721 GtkCListRow * clist_row)
4725 for (i = 0; i < clist->columns; i++)
4726 cell_empty (clist, clist_row, i);
4728 if (clist_row->destroy)
4729 clist_row->destroy (clist_row->data);
4731 g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
4732 g_mem_chunk_free (clist->row_mem_chunk, clist_row);
4736 cell_empty (GtkCList * clist,
4737 GtkCListRow * clist_row,
4740 switch (clist_row->cell[column].type)
4742 case GTK_CELL_EMPTY:
4746 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
4749 case GTK_CELL_PIXMAP:
4750 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
4751 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
4752 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
4755 case GTK_CELL_PIXTEXT:
4756 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
4757 gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
4758 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
4759 gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
4762 case GTK_CELL_WIDGET:
4770 clist_row->cell[column].type = GTK_CELL_EMPTY;
4774 cell_set_text (GtkCList * clist,
4775 GtkCListRow * clist_row,
4779 cell_empty (clist, clist_row, column);
4783 clist_row->cell[column].type = GTK_CELL_TEXT;
4784 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
4789 cell_set_pixmap (GtkCList * clist,
4790 GtkCListRow * clist_row,
4795 cell_empty (clist, clist_row, column);
4799 clist_row->cell[column].type = GTK_CELL_PIXMAP;
4800 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
4801 /* We set the mask even if it is NULL */
4802 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
4807 cell_set_pixtext (GtkCList * clist,
4808 GtkCListRow * clist_row,
4815 cell_empty (clist, clist_row, column);
4819 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
4820 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
4821 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
4822 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
4823 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
4827 /* Fill in data after widget has correct style */
4830 add_style_data (GtkCList * clist)
4834 widget = GTK_WIDGET(clist);
4836 /* text properties */
4837 if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
4839 clist->row_height = widget->style->font->ascent + widget->style->font->descent + 1;
4840 clist->row_center_offset = widget->style->font->ascent + 1.5;
4845 text_height = clist->row_height - (GTK_WIDGET (clist)->style->font->ascent +
4846 GTK_WIDGET (clist) ->style->font->descent + 1);
4847 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
4854 /* focus functions */
4857 gtk_clist_draw_focus (GtkWidget *widget)
4861 g_return_if_fail (widget != NULL);
4862 g_return_if_fail (GTK_IS_CLIST (widget));
4864 if (!GTK_WIDGET_DRAWABLE (widget))
4867 clist = GTK_CLIST (widget);
4868 if (clist->focus_row >= 0)
4869 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
4870 0, ROW_TOP_YPIXEL(clist, clist->focus_row),
4871 clist->clist_window_width - 1,
4872 clist->row_height - 1);
4876 gtk_clist_set_focus_child (GtkContainer *container,
4879 g_return_if_fail (container != NULL);
4880 g_return_if_fail (GTK_IS_CLIST (container));
4884 g_return_if_fail (GTK_IS_WIDGET (child));
4885 GTK_CLIST_SET_FLAG (GTK_CLIST (container), CLIST_CHILD_HAS_FOCUS);
4888 parent_class->set_focus_child (container, child);
4892 gtk_clist_focus_in (GtkWidget *widget,
4893 GdkEventFocus *event)
4897 g_return_val_if_fail (widget != NULL, FALSE);
4898 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
4899 g_return_val_if_fail (event != NULL, FALSE);
4901 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4902 GTK_CLIST_UNSET_FLAG (widget, CLIST_CHILD_HAS_FOCUS);
4904 clist = GTK_CLIST (widget);
4906 if (clist->selection_mode == GTK_SELECTION_BROWSE &&
4907 clist->selection == NULL && clist->focus_row > -1)
4908 select_row (clist, clist->focus_row, -1, (GdkEvent *) event);
4910 gtk_widget_draw_focus (widget);
4916 gtk_clist_focus_out (GtkWidget *widget,
4917 GdkEventFocus *event)
4921 g_return_val_if_fail (widget != NULL, FALSE);
4922 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
4923 g_return_val_if_fail (event != NULL, FALSE);
4925 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4926 gtk_widget_draw_focus (widget);
4928 clist = GTK_CLIST (widget);
4930 if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
4931 GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, (GdkEvent *) event);
4937 toggle_add_mode (GtkCList *clist)
4939 g_return_if_fail (clist != 0);
4940 g_return_if_fail (GTK_IS_CLIST (clist));
4942 if (gdk_pointer_is_grabbed () ||
4943 clist->selection_mode != GTK_SELECTION_EXTENDED)
4946 gtk_clist_draw_focus (GTK_WIDGET (clist));
4947 if (!GTK_CLIST_ADD_MODE (clist))
4949 GTK_CLIST_SET_FLAG (clist, CLIST_ADD_MODE);
4950 gdk_gc_set_line_attributes (clist->xor_gc, 1,
4951 GDK_LINE_ON_OFF_DASH, 0, 0);
4952 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
4956 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
4957 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
4958 clist->anchor_state = GTK_STATE_SELECTED;
4960 gtk_clist_draw_focus (GTK_WIDGET (clist));
4964 toggle_focus_row (GtkCList *clist)
4966 g_return_if_fail (clist != 0);
4967 g_return_if_fail (GTK_IS_CLIST (clist));
4969 if (gdk_pointer_is_grabbed ())
4972 switch (clist->selection_mode)
4974 case GTK_SELECTION_SINGLE:
4975 case GTK_SELECTION_MULTIPLE:
4977 toggle_row (clist, clist->focus_row, 0, NULL);
4980 case GTK_SELECTION_EXTENDED:
4981 g_list_free (clist->undo_selection);
4982 g_list_free (clist->undo_unselection);
4983 clist->undo_selection = NULL;
4984 clist->undo_unselection = NULL;
4986 if (GTK_CLIST_ADD_MODE (clist))
4988 clist->anchor = clist->focus_row;
4989 clist->drag_pos = clist->focus_row;
4990 clist->undo_anchor = clist->focus_row;
4991 fake_toggle_row (clist, clist->focus_row);
4992 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
4996 clist->anchor = clist->focus_row;
4997 clist->drag_pos = clist->focus_row;
4998 clist->undo_anchor = clist->focus_row;
4999 GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist,
5001 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5011 move_focus_row (GtkCList *clist,
5012 GtkScrollType scroll_type,
5017 g_return_if_fail (clist != 0);
5018 g_return_if_fail (GTK_IS_CLIST (clist));
5020 widget = GTK_WIDGET (clist);
5022 switch (scroll_type)
5024 case GTK_SCROLL_STEP_BACKWARD:
5025 if (clist->focus_row <= 0)
5027 gtk_clist_draw_focus (widget);
5029 gtk_clist_draw_focus (widget);
5031 case GTK_SCROLL_STEP_FORWARD:
5032 if (clist->focus_row >= clist->rows - 1)
5034 gtk_clist_draw_focus (widget);
5036 gtk_clist_draw_focus (widget);
5038 case GTK_SCROLL_PAGE_BACKWARD:
5039 if (clist->focus_row <= 0)
5041 gtk_clist_draw_focus (widget);
5042 clist->focus_row = MAX (0, clist->focus_row -
5043 (2 * clist->clist_window_height -
5044 clist->row_height - CELL_SPACING) /
5045 (2 * (clist->row_height + CELL_SPACING)));
5046 gtk_clist_draw_focus (widget);
5048 case GTK_SCROLL_PAGE_FORWARD:
5049 if (clist->focus_row >= clist->rows - 1)
5051 gtk_clist_draw_focus (widget);
5052 clist->focus_row = MIN (clist->rows - 1, clist->focus_row +
5053 (2 * clist->clist_window_height -
5054 clist->row_height - CELL_SPACING) /
5055 (2 * (clist->row_height + CELL_SPACING)));
5056 gtk_clist_draw_focus (widget);
5058 case GTK_SCROLL_JUMP:
5059 if (position >= 0 && position <= 1)
5061 gtk_clist_draw_focus (widget);
5062 clist->focus_row = position * (clist->rows - 1);
5063 gtk_clist_draw_focus (widget);
5072 scroll_horizontal (GtkCList *clist,
5073 GtkScrollType scroll_type,
5078 g_return_if_fail (clist != 0);
5079 g_return_if_fail (GTK_IS_CLIST (clist));
5081 if (gdk_pointer_is_grabbed ())
5084 switch (scroll_type)
5086 case GTK_SCROLL_STEP_BACKWARD:
5087 column = COLUMN_FROM_XPIXEL (clist, 0);
5088 if (COLUMN_LEFT_XPIXEL (clist, column) - CELL_SPACING - COLUMN_INSET >= 0
5092 case GTK_SCROLL_STEP_FORWARD:
5093 column = COLUMN_FROM_XPIXEL (clist, clist->clist_window_width);
5096 if (COLUMN_LEFT_XPIXEL (clist, column) + clist->column[column].area.width
5097 + CELL_SPACING + COLUMN_INSET - 1 <= clist->clist_window_width &&
5098 column < clist->columns - 1)
5101 case GTK_SCROLL_PAGE_BACKWARD:
5102 case GTK_SCROLL_PAGE_FORWARD:
5104 case GTK_SCROLL_JUMP:
5105 if (position >= 0 && position <= 1)
5106 column = position * (clist->columns - 1);
5114 if (COLUMN_LEFT_XPIXEL (clist, column) < CELL_SPACING + COLUMN_INSET)
5115 gtk_clist_moveto (clist, -1, column, 0, 0);
5116 else if (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET - 1
5117 + clist->column[column].area.width > clist->clist_window_width)
5119 if (column == clist->columns - 1)
5120 gtk_clist_moveto (clist, -1, column, 0, 0);
5122 gtk_clist_moveto (clist, -1, column, 0, 1);
5127 scroll_vertical (GtkCList *clist,
5128 GtkScrollType scroll_type,
5133 g_return_if_fail (clist != NULL);
5134 g_return_if_fail (GTK_IS_CLIST (clist));
5136 if (gdk_pointer_is_grabbed ())
5139 switch (clist->selection_mode)
5141 case GTK_SELECTION_EXTENDED:
5142 if (clist->anchor >= 0)
5145 case GTK_SELECTION_BROWSE:
5147 old_focus_row = clist->focus_row;
5148 move_focus_row (clist, scroll_type, position);
5150 if (old_focus_row != clist->focus_row)
5152 if (clist->selection_mode == GTK_SELECTION_BROWSE)
5153 unselect_row (clist,old_focus_row, -1, NULL);
5154 else if (!GTK_CLIST_ADD_MODE (clist))
5156 gtk_clist_unselect_all (clist);
5157 clist->undo_anchor = old_focus_row;
5161 switch (gtk_clist_row_is_visible (clist, clist->focus_row))
5163 case GTK_VISIBILITY_NONE:
5164 if (old_focus_row != clist->focus_row &&
5165 !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
5166 GTK_CLIST_ADD_MODE (clist)))
5167 select_row (clist, clist->focus_row, -1, NULL);
5168 switch (scroll_type)
5170 case GTK_SCROLL_STEP_BACKWARD:
5171 case GTK_SCROLL_PAGE_BACKWARD:
5172 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5174 case GTK_SCROLL_STEP_FORWARD:
5175 case GTK_SCROLL_PAGE_FORWARD:
5176 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5178 case GTK_SCROLL_JUMP:
5179 gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
5186 case GTK_VISIBILITY_PARTIAL:
5187 switch (scroll_type)
5189 case GTK_SCROLL_STEP_BACKWARD:
5190 case GTK_SCROLL_PAGE_BACKWARD:
5191 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5193 case GTK_SCROLL_STEP_FORWARD:
5194 case GTK_SCROLL_PAGE_FORWARD:
5195 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5197 case GTK_SCROLL_JUMP:
5198 gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
5205 if (old_focus_row != clist->focus_row &&
5206 !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
5207 GTK_CLIST_ADD_MODE (clist)))
5208 select_row (clist, clist->focus_row, -1, NULL);
5214 move_focus_row (clist, scroll_type, position);
5216 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
5217 clist->clist_window_height)
5218 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5219 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
5220 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5226 set_anchor (GtkCList *clist,
5231 g_return_if_fail (clist != NULL);
5232 g_return_if_fail (GTK_IS_CLIST (clist));
5234 if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor >= 0)
5237 g_list_free (clist->undo_selection);
5238 g_list_free (clist->undo_unselection);
5239 clist->undo_selection = NULL;
5240 clist->undo_unselection = NULL;
5243 fake_toggle_row (clist, anchor);
5246 GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist, anchor);
5247 clist->anchor_state = GTK_STATE_SELECTED;
5250 clist->anchor = anchor;
5251 clist->drag_pos = anchor;
5252 clist->undo_anchor = undo_anchor;
5256 resync_selection (GtkCList *clist,
5262 gboolean thaw = FALSE;
5264 GtkCListRow *clist_row;
5266 if (clist->anchor < 0)
5269 if (!GTK_CLIST_FROZEN (clist))
5271 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
5275 i = MIN (clist->anchor, clist->drag_pos);
5276 e = MAX (clist->anchor, clist->drag_pos);
5278 if (clist->undo_selection)
5281 list = clist->selection;
5282 clist->selection = clist->undo_selection;
5283 clist->selection_end = g_list_last (clist->selection);
5284 clist->undo_selection = list;
5285 list = clist->selection;
5288 row = GPOINTER_TO_INT (list->data);
5290 if (row < i || row > e)
5292 clist_row = g_list_nth (clist->row_list, row)->data;
5293 clist_row->state = GTK_STATE_SELECTED;
5294 unselect_row (clist, row, -1, event);
5295 clist->undo_selection = g_list_prepend
5296 (clist->undo_selection, GINT_TO_POINTER (row));
5301 for (list = g_list_nth (clist->row_list, i); i <= e; i++, list = list->next)
5302 if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
5304 if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
5306 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
5307 unselect_row (clist, i, -1, event);
5308 clist->undo_selection = g_list_prepend (clist->undo_selection,
5309 GINT_TO_POINTER (i));
5312 else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
5314 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
5315 clist->undo_unselection = g_list_prepend (clist->undo_unselection,
5316 GINT_TO_POINTER (i));
5319 for (list = clist->undo_unselection; list; list = list->next)
5320 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
5321 GPOINTER_TO_INT (list->data), -1, event);
5324 clist->drag_pos = -1;
5327 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
5331 update_extended_selection (GtkCList *clist,
5341 gint y1 = clist->clist_window_height;
5342 gint y2 = clist->clist_window_height;
5347 if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor == -1)
5352 if (row >= clist->rows)
5353 row = clist->rows - 1;
5355 /* extending downwards */
5356 if (row > clist->drag_pos && clist->anchor <= clist->drag_pos)
5358 s2 = clist->drag_pos + 1;
5361 /* extending upwards */
5362 else if (row < clist->drag_pos && clist->anchor >= clist->drag_pos)
5365 e2 = clist->drag_pos - 1;
5367 else if (row < clist->drag_pos && clist->anchor < clist->drag_pos)
5369 e1 = clist->drag_pos;
5370 /* row and drag_pos on different sides of anchor :
5371 take back the selection between anchor and drag_pos,
5372 select between anchor and row */
5373 if (row < clist->anchor)
5375 s1 = clist->anchor + 1;
5377 e2 = clist->anchor - 1;
5379 /* take back the selection between anchor and drag_pos */
5383 else if (row > clist->drag_pos && clist->anchor > clist->drag_pos)
5385 s1 = clist->drag_pos;
5386 /* row and drag_pos on different sides of anchor :
5387 take back the selection between anchor and drag_pos,
5388 select between anchor and row */
5389 if (row > clist->anchor)
5391 e1 = clist->anchor - 1;
5392 s2 = clist->anchor + 1;
5395 /* take back the selection between anchor and drag_pos */
5400 clist->drag_pos = row;
5403 area.width = clist->clist_window_width;
5405 /* restore the elements between s1 and e1 */
5408 for (i = s1, list = g_list_nth (clist->row_list, i); i <= e1;
5409 i++, list = list->next)
5411 if (GTK_CLIST_CLASS_FW (clist)->selection_find (clist, i, list))
5412 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
5414 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
5417 top = ROW_TOP_YPIXEL (clist, clist->focus_row);
5419 if (top + clist->row_height <= 0)
5422 area.height = ROW_TOP_YPIXEL (clist, e1) + clist->row_height;
5423 draw_rows (clist, &area);
5424 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5426 else if (top >= clist->clist_window_height)
5428 area.y = ROW_TOP_YPIXEL (clist, s1);
5429 area.height = clist->clist_window_height - area.y;
5430 draw_rows (clist, &area);
5431 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5434 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5435 else if (top + clist->row_height > clist->clist_window_height)
5436 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5438 y1 = ROW_TOP_YPIXEL (clist, s1);
5439 h1 = (e1 - s1 + 1) * (clist->row_height + CELL_SPACING);
5442 /* extend the selection between s2 and e2 */
5445 for (i = s2, list = g_list_nth (clist->row_list, i); i <= e2;
5446 i++, list = list->next)
5447 if (GTK_CLIST_ROW (list)->state != clist->anchor_state)
5448 GTK_CLIST_ROW (list)->state = clist->anchor_state;
5450 top = ROW_TOP_YPIXEL (clist, clist->focus_row);
5452 if (top + clist->row_height <= 0)
5455 area.height = ROW_TOP_YPIXEL (clist, e2) + clist->row_height;
5456 draw_rows (clist, &area);
5457 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5459 else if (top >= clist->clist_window_height)
5461 area.y = ROW_TOP_YPIXEL (clist, s2);
5462 area.height = clist->clist_window_height - area.y;
5463 draw_rows (clist, &area);
5464 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5467 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5468 else if (top + clist->row_height > clist->clist_window_height)
5469 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5471 y2 = ROW_TOP_YPIXEL (clist, s2);
5472 h2 = (e2-s2+1) * (clist->row_height + CELL_SPACING);
5475 area.y = MAX (0, MIN (y1, y2));
5476 if (area.y > clist->clist_window_height)
5478 area.height = MIN (clist->clist_window_height, h1 + h2);
5479 if (s1 >= 0 && s2 >= 0)
5480 area.height += (clist->row_height + CELL_SPACING);
5481 draw_rows (clist, &area);
5485 start_selection (GtkCList *clist)
5487 g_return_if_fail (clist != NULL);
5488 g_return_if_fail (GTK_IS_CLIST (clist));
5490 if (gdk_pointer_is_grabbed ())
5493 set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
5498 end_selection (GtkCList *clist)
5500 g_return_if_fail (clist != NULL);
5501 g_return_if_fail (GTK_IS_CLIST (clist));
5503 if (gdk_pointer_is_grabbed () || clist->anchor == -1)
5506 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5510 extend_selection (GtkCList *clist,
5511 GtkScrollType scroll_type,
5513 gboolean auto_start_selection)
5515 g_return_if_fail (clist != NULL);
5516 g_return_if_fail (GTK_IS_CLIST (clist));
5518 if (gdk_pointer_is_grabbed () ||
5519 clist->selection_mode != GTK_SELECTION_EXTENDED)
5522 if (auto_start_selection)
5523 set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
5525 else if (clist->anchor == -1)
5528 move_focus_row (clist, scroll_type, position);
5530 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
5531 clist->clist_window_height)
5532 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5533 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
5534 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5536 update_extended_selection (clist, clist->focus_row);
5540 abort_column_resize (GtkCList *clist)
5542 g_return_if_fail (clist != NULL);
5543 g_return_if_fail (GTK_IS_CLIST (clist));
5545 if (!GTK_CLIST_IN_DRAG (clist))
5548 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
5549 gdk_pointer_ungrab (gdk_time_get());
5551 if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
5552 draw_xor_line (clist);
5554 if (GTK_CLIST_ADD_MODE (clist))
5556 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0);
5557 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
5562 gtk_clist_key_press (GtkWidget * widget,
5563 GdkEventKey * event)
5566 gboolean handled = FALSE;
5568 g_return_val_if_fail (widget != NULL, FALSE);
5569 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
5570 g_return_val_if_fail (event != NULL, FALSE);
5572 clist = GTK_CLIST (widget);
5575 if (event->keyval == GDK_Escape && GTK_CLIST_IN_DRAG (clist))
5577 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
5578 gdk_pointer_ungrab (event->time);
5580 if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
5581 draw_xor_line (clist);
5583 if (GTK_CLIST_ADD_MODE (clist))
5585 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH,
5587 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
5592 if (GTK_WIDGET_CLASS (parent_class)->key_press_event)
5593 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
5598 switch (event->keyval)
5601 case GDK_ISO_Left_Tab:
5602 if (event->state & GDK_SHIFT_MASK)
5603 return gtk_container_focus (GTK_CONTAINER (widget),
5604 GTK_DIR_TAB_BACKWARD);
5606 return gtk_container_focus (GTK_CONTAINER (widget),
5607 GTK_DIR_TAB_FORWARD);
5617 title_focus (GtkCList * clist,
5620 GtkWidget *focus_child;
5621 gboolean return_val = FALSE;
5626 if (!GTK_CLIST_SHOW_TITLES (clist))
5629 focus_child = GTK_CONTAINER (clist)->focus_child;
5633 case GTK_DIR_TAB_BACKWARD:
5635 if (!focus_child || focus_child == clist->hscrollbar ||
5636 focus_child == clist->hscrollbar ||
5637 !GTK_CLIST_CHILD_HAS_FOCUS (clist))
5639 if (dir == GTK_DIR_UP)
5640 i = COLUMN_FROM_XPIXEL (clist, 0);
5642 i = clist->columns - 1;
5643 focus_child = clist->column[i].button;
5644 dir = GTK_DIR_TAB_FORWARD;
5651 if (!focus_child || focus_child == clist->hscrollbar ||
5652 focus_child == clist->hscrollbar)
5654 i = clist->columns - 1;
5655 focus_child = clist->column[i].button;
5659 if (!focus_child || focus_child == clist->hscrollbar ||
5660 focus_child == clist->hscrollbar)
5663 focus_child = clist->column[i].button;
5669 while (i < clist->columns)
5671 if (clist->column[i].button == focus_child)
5673 if (clist->column[i].button &&
5674 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
5675 GTK_IS_CONTAINER (clist->column[i].button) &&
5676 !GTK_WIDGET_HAS_FOCUS (clist->column[i].button))
5677 if (gtk_container_focus
5678 (GTK_CONTAINER (clist->column[i].button), dir))
5683 if (!return_val && dir == GTK_DIR_UP)
5694 while (j >= 0 && j < clist->columns)
5696 if (clist->column[j].button &&
5697 GTK_WIDGET_VISIBLE (clist->column[j].button))
5699 if (GTK_IS_CONTAINER (clist->column[j].button) &&
5701 (GTK_CONTAINER (clist->column[j].button), dir))
5706 else if (GTK_WIDGET_CAN_FOCUS (clist->column[j].button))
5708 gtk_widget_grab_focus (clist->column[j].button);
5718 if (COLUMN_LEFT_XPIXEL (clist, j) < CELL_SPACING + COLUMN_INSET)
5719 gtk_clist_moveto (clist, -1, j, 0, 0);
5720 else if (COLUMN_LEFT_XPIXEL(clist, j) + clist->column[j].area.width >
5721 clist->clist_window_width)
5723 if (j == clist->columns-1)
5724 gtk_clist_moveto (clist, -1, j, 0, 0);
5726 gtk_clist_moveto (clist, -1, j, 0, 1);
5733 gtk_clist_focus (GtkContainer * container,
5734 GtkDirectionType direction)
5737 GtkWidget *focus_child;
5740 g_return_val_if_fail (container != NULL, FALSE);
5741 g_return_val_if_fail (GTK_IS_CLIST (container), FALSE);
5743 if (!GTK_WIDGET_SENSITIVE (container))
5746 clist = GTK_CLIST (container);
5747 focus_child = container->focus_child;
5748 old_row = clist->focus_row;
5754 if (GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
5755 (!focus_child || (focus_child && focus_child != clist->vscrollbar &&
5756 focus_child != clist->hscrollbar)))
5758 if (title_focus (clist, direction))
5760 gtk_container_set_focus_child (container, NULL);
5763 gtk_widget_grab_focus (GTK_WIDGET (container));
5766 case GTK_DIR_TAB_FORWARD:
5767 if (GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
5768 (!focus_child || (focus_child != clist->vscrollbar &&
5769 focus_child != clist->hscrollbar)))
5771 gboolean tf = FALSE;
5773 if (((focus_child && direction == GTK_DIR_DOWN) ||
5774 !(tf = title_focus (clist, GTK_DIR_TAB_FORWARD)))
5777 if (clist->focus_row < 0)
5779 clist->focus_row = 0;
5781 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
5782 clist->selection_mode == GTK_SELECTION_EXTENDED) &&
5784 select_row (clist, clist->focus_row, -1, NULL);
5786 gtk_widget_grab_focus (GTK_WIDGET (container));
5794 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
5796 if ((!GTK_CLIST_CHILD_HAS_FOCUS (clist) || !focus_child ||
5797 (focus_child != clist->vscrollbar &&
5798 focus_child != clist->hscrollbar)) &&
5799 GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
5800 GTK_WIDGET_CAN_FOCUS (clist->vscrollbar))
5802 gtk_widget_grab_focus (clist->vscrollbar);
5806 if ((!GTK_CLIST_CHILD_HAS_FOCUS (clist) || !focus_child ||
5807 focus_child != clist->hscrollbar) &&
5808 GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
5809 GTK_WIDGET_CAN_FOCUS (clist->hscrollbar))
5811 gtk_widget_grab_focus (clist->hscrollbar);
5816 case GTK_DIR_TAB_BACKWARD:
5817 if (!focus_child && GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
5818 GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
5819 GTK_WIDGET_CAN_FOCUS (clist->hscrollbar))
5821 gtk_widget_grab_focus (clist->hscrollbar);
5825 if ((!focus_child || focus_child == clist->hscrollbar) &&
5826 GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
5827 GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
5828 GTK_WIDGET_CAN_FOCUS (clist->vscrollbar))
5830 gtk_widget_grab_focus (clist->vscrollbar);
5834 if ((!focus_child || focus_child == clist->hscrollbar ||
5835 focus_child == clist->vscrollbar) &&
5836 GTK_CLIST_CHILD_HAS_FOCUS (clist) && clist->rows)
5838 if (clist->focus_row < 0)
5840 clist->focus_row = 0;
5841 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
5842 clist->selection_mode == GTK_SELECTION_EXTENDED) &&
5844 select_row (clist, clist->focus_row, -1, NULL);
5846 gtk_widget_grab_focus (GTK_WIDGET (container));
5850 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
5852 if (title_focus (clist, direction))
5861 gtk_container_set_focus_child (container, NULL);
5866 gtk_clist_unselect_all (GtkCList * clist)
5868 GTK_CLIST_CLASS_FW (clist)->unselect_all (clist);
5872 real_unselect_all (GtkCList * clist)
5877 g_return_if_fail (clist != NULL);
5878 g_return_if_fail (GTK_IS_CLIST (clist));
5880 if (gdk_pointer_is_grabbed ())
5883 switch (clist->selection_mode)
5885 case GTK_SELECTION_BROWSE:
5886 if (clist->focus_row >= 0)
5888 select_row (clist, clist->focus_row, -1, NULL);
5893 case GTK_SELECTION_EXTENDED:
5894 g_list_free (clist->undo_selection);
5895 g_list_free (clist->undo_unselection);
5896 clist->undo_selection = NULL;
5897 clist->undo_unselection = NULL;
5900 clist->drag_pos = -1;
5901 clist->undo_anchor = clist->focus_row;
5908 list = clist->selection;
5912 i = GPOINTER_TO_INT (list->data);
5914 unselect_row (clist, i, -1, NULL);
5919 gtk_clist_select_all (GtkCList * clist)
5921 GTK_CLIST_CLASS_FW (clist)->select_all (clist);
5925 real_select_all (GtkCList * clist)
5930 g_return_if_fail (clist != NULL);
5931 g_return_if_fail (GTK_IS_CLIST (clist));
5933 if (gdk_pointer_is_grabbed ())
5936 switch (clist->selection_mode)
5938 case GTK_SELECTION_SINGLE:
5939 case GTK_SELECTION_BROWSE:
5942 case GTK_SELECTION_EXTENDED:
5943 g_list_free (clist->undo_selection);
5944 g_list_free (clist->undo_unselection);
5945 clist->undo_selection = NULL;
5946 clist->undo_unselection = NULL;
5949 ((GtkCListRow *) (clist->row_list->data))->state !=
5951 fake_toggle_row (clist, 0);
5953 clist->anchor_state = GTK_STATE_SELECTED;
5955 clist->drag_pos = 0;
5956 clist->undo_anchor = clist->focus_row;
5957 update_extended_selection (clist, clist->rows);
5958 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5961 case GTK_SELECTION_MULTIPLE:
5962 for (i = 0, list = clist->row_list; list; i++, list = list->next)
5964 if (((GtkCListRow *)(list->data))->state == GTK_STATE_NORMAL)
5965 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
5973 fake_unselect_all (GtkCList * clist,
5980 if (row >= 0 && (work = g_list_nth (clist->row_list, row)))
5982 if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
5984 GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
5986 if (!GTK_CLIST_FROZEN (clist) &&
5987 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
5988 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
5989 GTK_CLIST_ROW (work));
5993 clist->undo_selection = clist->selection;
5994 clist->selection = NULL;
5995 clist->selection_end = NULL;
5997 for (list = clist->undo_selection; list; list = list->next)
5999 if ((i = GPOINTER_TO_INT (list->data)) == row ||
6000 !(work = g_list_nth (clist->row_list, i)))
6003 GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
6004 if (!GTK_CLIST_FROZEN (clist) &&
6005 gtk_clist_row_is_visible (clist, i) != GTK_VISIBILITY_NONE)
6006 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, i,
6007 GTK_CLIST_ROW (work));
6012 fake_toggle_row (GtkCList *clist,
6017 if (!(work = g_list_nth (clist->row_list, row)))
6020 if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
6021 clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
6023 clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
6025 if (!GTK_CLIST_FROZEN (clist) &&
6026 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
6027 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
6028 GTK_CLIST_ROW (work));
6032 selection_find (GtkCList *clist,
6034 GList *row_list_element)
6036 return g_list_find (clist->selection, GINT_TO_POINTER (row_number));