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_SCROLL_TYPE, 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_SCROLL_TYPE, 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_SCROLL_TYPE, 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,
646 gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
647 GDK_RELEASE_MASK | GDK_SHIFT_MASK |
650 gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
651 GDK_RELEASE_MASK | GDK_SHIFT_MASK |
658 GtkBindingSet *binding_set;
660 binding_set = gtk_binding_set_by_class (klass);
661 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
662 "scroll_vertical", 2,
663 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
664 GTK_TYPE_FLOAT, 0.0);
665 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
666 "scroll_vertical", 2,
667 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
668 GTK_TYPE_FLOAT, 0.0);
669 gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
670 "scroll_vertical", 2,
671 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
672 GTK_TYPE_FLOAT, 0.0);
673 gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
674 "scroll_vertical", 2,
675 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
676 GTK_TYPE_FLOAT, 0.0);
677 gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
678 "scroll_vertical", 2,
679 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
680 GTK_TYPE_FLOAT, 0.0);
681 gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
682 "scroll_vertical", 2,
683 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
686 gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
687 "extend_selection", 3,
688 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
689 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
690 gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
691 "extend_selection", 3,
692 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
693 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
694 gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, 0,
695 "extend_selection", 3,
696 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
697 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
698 gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, 0,
699 "extend_selection", 3,
700 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
701 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
702 gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
703 "extend_selection", 3,
704 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
705 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
706 gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
707 "extend_selection", 3,
708 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
709 GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
711 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
712 "scroll_horizontal", 2,
713 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
714 GTK_TYPE_FLOAT, 0.0);
715 gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
716 "scroll_horizontal", 2,
717 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
718 GTK_TYPE_FLOAT, 0.0);
719 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
720 "scroll_horizontal", 2,
721 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
722 GTK_TYPE_FLOAT, 0.0);
723 gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
724 "scroll_horizontal", 2,
725 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
726 GTK_TYPE_FLOAT, 0.0);
727 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
728 "scroll_horizontal", 2,
729 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
730 GTK_TYPE_FLOAT, 0.0);
731 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
732 "sroll_horizontal", 2,
733 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
734 GTK_TYPE_FLOAT, 1.0);
736 gtk_binding_entry_add_signal (binding_set, GDK_KP_Divide, 0,
737 "undo_selection", 0);
738 gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
739 "abort_column_resize", 0);
740 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
741 "toggle_focus_row", 0);
742 gtk_binding_entry_add_signal (binding_set, GDK_KP_Multiply, 0,
743 "toggle_add_mode", 0);
744 gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, 0,
746 gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, 0,
748 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
755 gtk_clist_init (GtkCList * clist)
759 GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
760 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
762 clist->row_mem_chunk = NULL;
763 clist->cell_mem_chunk = NULL;
766 clist->row_center_offset = 0;
767 clist->row_height = 0;
768 clist->row_list = NULL;
769 clist->row_list_end = NULL;
773 clist->title_window = NULL;
774 clist->column_title_area.x = 0;
775 clist->column_title_area.y = 0;
776 clist->column_title_area.width = 1;
777 clist->column_title_area.height = 1;
779 clist->clist_window = NULL;
780 clist->clist_window_width = 1;
781 clist->clist_window_height = 1;
786 clist->shadow_type = GTK_SHADOW_IN;
787 clist->hscrollbar_policy = GTK_POLICY_ALWAYS;
788 clist->vscrollbar_policy = GTK_POLICY_ALWAYS;
790 clist->cursor_drag = NULL;
791 clist->xor_gc = NULL;
796 clist->selection_mode = GTK_SELECTION_SINGLE;
797 clist->selection = NULL;
798 clist->selection_end = NULL;
799 clist->undo_selection = NULL;
800 clist->undo_unselection = NULL;
802 GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
803 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
804 clist->focus_row = -1;
805 clist->undo_anchor = -1;
808 clist->anchor_state = GTK_STATE_SELECTED;
809 clist->drag_pos = -1;
816 gtk_clist_construct (GtkCList * clist,
822 g_return_if_fail (clist != NULL);
823 g_return_if_fail (GTK_IS_CLIST (clist));
824 g_return_if_fail (GTK_CLIST_CONSTRUCTED (clist) == FALSE);
826 GTK_CLIST_SET_FLAG (clist, CLIST_CONSTRUCTED);
828 /* initalize memory chunks, if this has not been done by any
829 * possibly derived widget
831 if (!clist->row_mem_chunk)
832 clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
833 sizeof (GtkCListRow),
834 sizeof (GtkCListRow) * CLIST_OPTIMUM_SIZE,
837 if (!clist->cell_mem_chunk)
838 clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
839 sizeof (GtkCell) * columns,
840 sizeof (GtkCell) * columns * CLIST_OPTIMUM_SIZE,
843 /* set number of columns, allocate memory */
844 clist->columns = columns;
845 clist->column = columns_new (clist);
847 /* there needs to be at least one column button
848 * because there is alot of code that will break if it
850 column_button_create (clist, 0);
852 /* create scrollbars */
853 create_scrollbars (clist);
857 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
858 for (i = 0; i < columns; i++)
859 gtk_clist_set_column_title (clist, i, titles[i]);
863 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
868 * GTKCLIST PUBLIC INTERFACE
869 * gtk_clist_new_with_titles
873 gtk_clist_new_with_titles (gint columns,
878 g_return_val_if_fail (titles != NULL, NULL);
880 widget = gtk_type_new (GTK_TYPE_CLIST);
882 gtk_clist_construct (GTK_CLIST (widget), columns, titles);
888 gtk_clist_new (gint columns)
895 clist = gtk_type_new (GTK_TYPE_CLIST);
896 gtk_clist_construct (clist, columns, NULL);
897 return GTK_WIDGET (clist);
901 gtk_clist_set_border (GtkCList * clist,
902 GtkShadowType border)
904 g_return_if_fail (clist != NULL);
905 g_return_if_fail (GTK_IS_CLIST (clist));
907 clist->shadow_type = border;
909 if (GTK_WIDGET_VISIBLE (clist))
910 gtk_widget_queue_resize (GTK_WIDGET (clist));
914 gtk_clist_set_selection_mode (GtkCList * clist,
915 GtkSelectionMode mode)
917 g_return_if_fail (clist != NULL);
918 g_return_if_fail (GTK_IS_CLIST (clist));
920 if (mode == clist->selection_mode)
923 clist->selection_mode = mode;
925 clist->anchor_state = GTK_STATE_SELECTED;
926 clist->drag_pos = -1;
927 clist->undo_anchor = clist->focus_row;
929 g_list_free (clist->undo_selection);
930 g_list_free (clist->undo_unselection);
931 clist->undo_selection = NULL;
932 clist->undo_unselection = NULL;
936 case GTK_SELECTION_MULTIPLE:
937 case GTK_SELECTION_EXTENDED:
939 case GTK_SELECTION_BROWSE:
940 case GTK_SELECTION_SINGLE:
941 gtk_clist_unselect_all (clist);
947 gtk_clist_freeze (GtkCList * clist)
949 g_return_if_fail (clist != NULL);
950 g_return_if_fail (GTK_IS_CLIST (clist));
952 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
956 gtk_clist_thaw (GtkCList * clist)
958 g_return_if_fail (clist != NULL);
959 g_return_if_fail (GTK_IS_CLIST (clist));
961 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
963 adjust_scrollbars (clist);
964 draw_rows (clist, NULL);
968 gtk_clist_column_titles_show (GtkCList * clist)
970 g_return_if_fail (clist != NULL);
971 g_return_if_fail (GTK_IS_CLIST (clist));
973 if (!GTK_CLIST_SHOW_TITLES (clist))
975 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
976 if (clist->title_window)
977 gdk_window_show (clist->title_window);
978 gtk_widget_queue_resize (GTK_WIDGET (clist));
983 gtk_clist_column_titles_hide (GtkCList * clist)
985 g_return_if_fail (clist != NULL);
986 g_return_if_fail (GTK_IS_CLIST (clist));
988 if (GTK_CLIST_SHOW_TITLES (clist))
990 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
991 if (clist->title_window)
992 gdk_window_hide (clist->title_window);
993 gtk_widget_queue_resize (GTK_WIDGET (clist));
998 gtk_clist_column_title_active (GtkCList * clist,
1001 g_return_if_fail (clist != NULL);
1002 g_return_if_fail (GTK_IS_CLIST (clist));
1004 if (column < 0 || column >= clist->columns)
1007 if (!GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
1008 !GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
1010 GTK_WIDGET_SET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
1011 if (GTK_WIDGET_VISIBLE (clist))
1012 gtk_widget_queue_draw (clist->column[column].button);
1017 gtk_clist_column_title_passive (GtkCList * clist,
1020 g_return_if_fail (clist != NULL);
1021 g_return_if_fail (GTK_IS_CLIST (clist));
1023 if (column < 0 || column >= clist->columns)
1026 if (GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
1027 GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
1029 GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
1030 if (GTK_WIDGET_VISIBLE (clist))
1031 gtk_widget_queue_draw (clist->column[column].button);
1036 gtk_clist_column_titles_active (GtkCList * clist)
1040 g_return_if_fail (clist != NULL);
1041 g_return_if_fail (GTK_IS_CLIST (clist));
1043 for (i = 0; i < clist->columns; i++)
1044 if (clist->column[i].button)
1045 gtk_clist_column_title_active (clist, i);
1049 gtk_clist_column_titles_passive (GtkCList * clist)
1053 g_return_if_fail (clist != NULL);
1054 g_return_if_fail (GTK_IS_CLIST (clist));
1056 for (i = 0; i < clist->columns; i++)
1057 if (clist->column[i].button)
1058 gtk_clist_column_title_passive (clist, i);
1062 gtk_clist_set_column_title (GtkCList * clist,
1066 gint new_button = 0;
1067 GtkWidget *old_widget;
1068 GtkWidget *alignment = NULL;
1071 g_return_if_fail (clist != NULL);
1072 g_return_if_fail (GTK_IS_CLIST (clist));
1074 if (column < 0 || column >= clist->columns)
1077 /* if the column button doesn't currently exist,
1078 * it has to be created first */
1079 if (!clist->column[column].button)
1081 column_button_create (clist, column);
1085 column_title_new (clist, column, title);
1087 /* remove and destroy the old widget */
1088 old_widget = GTK_BIN (clist->column[column].button)->child;
1090 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
1092 /* create new alignment based no column justification */
1093 switch (clist->column[column].justification)
1095 case GTK_JUSTIFY_LEFT:
1096 alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
1099 case GTK_JUSTIFY_RIGHT:
1100 alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
1103 case GTK_JUSTIFY_CENTER:
1104 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1107 case GTK_JUSTIFY_FILL:
1108 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1112 label = gtk_label_new (clist->column[column].title);
1113 gtk_container_add (GTK_CONTAINER (alignment), label);
1114 gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
1115 gtk_widget_show (label);
1116 gtk_widget_show (alignment);
1118 /* if this button didn't previously exist, then the
1119 * column button positions have to be re-computed */
1120 if (GTK_WIDGET_VISIBLE (clist) && new_button)
1121 size_allocate_title_buttons (clist);
1125 gtk_clist_set_column_widget (GtkCList * clist,
1129 gint new_button = 0;
1130 GtkWidget *old_widget;
1132 g_return_if_fail (clist != NULL);
1133 g_return_if_fail (GTK_IS_CLIST (clist));
1135 if (column < 0 || column >= clist->columns)
1138 /* if the column button doesn't currently exist,
1139 * it has to be created first */
1140 if (!clist->column[column].button)
1142 column_button_create (clist, column);
1146 column_title_new (clist, column, NULL);
1148 /* remove and destroy the old widget */
1149 old_widget = GTK_BIN (clist->column[column].button)->child;
1151 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
1153 /* add and show the widget */
1156 gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
1157 gtk_widget_show (widget);
1160 /* if this button didn't previously exist, then the
1161 * column button positions have to be re-computed */
1162 if (GTK_WIDGET_VISIBLE (clist) && new_button)
1163 size_allocate_title_buttons (clist);
1167 gtk_clist_set_column_justification (GtkCList * clist,
1169 GtkJustification justification)
1171 GtkWidget *alignment;
1173 g_return_if_fail (clist != NULL);
1174 g_return_if_fail (GTK_IS_CLIST (clist));
1176 if (column < 0 || column >= clist->columns)
1179 clist->column[column].justification = justification;
1181 /* change the alinment of the button title if it's not a
1183 if (clist->column[column].title)
1185 alignment = GTK_BIN (clist->column[column].button)->child;
1187 switch (clist->column[column].justification)
1189 case GTK_JUSTIFY_LEFT:
1190 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
1193 case GTK_JUSTIFY_RIGHT:
1194 gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
1197 case GTK_JUSTIFY_CENTER:
1198 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1201 case GTK_JUSTIFY_FILL:
1202 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1210 if (!GTK_CLIST_FROZEN (clist))
1211 draw_rows (clist, NULL);
1215 gtk_clist_set_column_width (GtkCList * clist,
1219 g_return_if_fail (clist != NULL);
1220 g_return_if_fail (GTK_IS_CLIST (clist));
1222 if (column < 0 || column >= clist->columns)
1225 clist->column[column].width = width;
1226 clist->column[column].width_set = TRUE;
1228 /* FIXME: this is quite expensive to do if the widget hasn't
1229 * been size_allocated yet, and pointless. Should
1232 size_allocate_columns (clist);
1233 size_allocate_title_buttons (clist);
1235 if (!GTK_CLIST_FROZEN (clist))
1237 adjust_scrollbars (clist);
1238 draw_rows (clist, NULL);
1243 gtk_clist_set_row_height (GtkCList * clist,
1248 g_return_if_fail (clist != NULL);
1249 g_return_if_fail (GTK_IS_CLIST (clist));
1252 clist->row_height = height;
1256 GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
1258 if (GTK_WIDGET_REALIZED (clist))
1260 text_height = height - (GTK_WIDGET (clist)->style->font->ascent +
1261 GTK_WIDGET (clist) ->style->font->descent + 1);
1262 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
1265 if (!GTK_CLIST_FROZEN (clist))
1267 adjust_scrollbars (clist);
1268 draw_rows (clist, NULL);
1273 gtk_clist_moveto (GtkCList * clist,
1279 g_return_if_fail (clist != NULL);
1280 g_return_if_fail (GTK_IS_CLIST (clist));
1282 if (row < -1 || row >= clist->rows)
1284 if (column < -1 || column >= clist->columns)
1287 row_align = CLAMP (row_align, 0, 1);
1288 col_align = CLAMP (col_align, 0, 1);
1290 /* adjust horizontal scrollbar */
1296 adj = GTK_RANGE (clist->hscrollbar)->adjustment;
1298 x = COLUMN_LEFT (clist, column) - CELL_SPACING - COLUMN_INSET -
1299 (col_align * (clist->clist_window_width - 2 * COLUMN_INSET -
1300 CELL_SPACING - clist->column[column].area.width));
1302 gtk_adjustment_set_value (adj, 0.0);
1303 else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
1304 gtk_adjustment_set_value
1305 (adj, LIST_WIDTH (clist) - clist->clist_window_width);
1307 gtk_adjustment_set_value (adj, x);
1310 /* adjust vertical scrollbar */
1312 move_vertical (clist, row, row_align);
1316 gtk_clist_get_cell_type (GtkCList * clist,
1320 GtkCListRow *clist_row;
1322 g_return_val_if_fail (clist != NULL, -1);
1323 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
1325 if (row < 0 || row >= clist->rows)
1327 if (column < 0 || column >= clist->columns)
1330 clist_row = (g_list_nth (clist->row_list, row))->data;
1332 return clist_row->cell[column].type;
1336 gtk_clist_set_text (GtkCList * clist,
1341 GtkCListRow *clist_row;
1343 g_return_if_fail (clist != NULL);
1344 g_return_if_fail (GTK_IS_CLIST (clist));
1346 if (row < 0 || row >= clist->rows)
1348 if (column < 0 || column >= clist->columns)
1351 clist_row = (g_list_nth (clist->row_list, row))->data;
1353 /* if text is null, then the cell is empty */
1355 cell_set_text (clist, clist_row, column, text);
1357 cell_empty (clist, clist_row, column);
1359 /* redraw the list if it's not frozen */
1360 if (!GTK_CLIST_FROZEN (clist))
1362 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1363 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1368 gtk_clist_get_text (GtkCList * clist,
1373 GtkCListRow *clist_row;
1375 g_return_val_if_fail (clist != NULL, 0);
1376 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
1378 if (row < 0 || row >= clist->rows)
1380 if (column < 0 || column >= clist->columns)
1383 clist_row = (g_list_nth (clist->row_list, row))->data;
1385 if (clist_row->cell[column].type != GTK_CELL_TEXT)
1389 *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
1395 gtk_clist_set_pixmap (GtkCList * clist,
1401 GtkCListRow *clist_row;
1403 g_return_if_fail (clist != NULL);
1404 g_return_if_fail (GTK_IS_CLIST (clist));
1406 if (row < 0 || row >= clist->rows)
1408 if (column < 0 || column >= clist->columns)
1411 clist_row = (g_list_nth (clist->row_list, row))->data;
1413 gdk_pixmap_ref (pixmap);
1415 if (mask) gdk_pixmap_ref (mask);
1417 cell_set_pixmap (clist, clist_row, column, pixmap, mask);
1419 /* redraw the list if it's not frozen */
1420 if (!GTK_CLIST_FROZEN (clist))
1422 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1423 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1428 gtk_clist_get_pixmap (GtkCList * clist,
1431 GdkPixmap ** pixmap,
1434 GtkCListRow *clist_row;
1436 g_return_val_if_fail (clist != NULL, 0);
1437 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
1439 if (row < 0 || row >= clist->rows)
1441 if (column < 0 || column >= clist->columns)
1444 clist_row = (g_list_nth (clist->row_list, row))->data;
1446 if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
1451 *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
1452 /* mask can be NULL */
1453 *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
1460 gtk_clist_set_pixtext (GtkCList * clist,
1468 GtkCListRow *clist_row;
1470 g_return_if_fail (clist != NULL);
1471 g_return_if_fail (GTK_IS_CLIST (clist));
1473 if (row < 0 || row >= clist->rows)
1475 if (column < 0 || column >= clist->columns)
1478 clist_row = (g_list_nth (clist->row_list, row))->data;
1480 gdk_pixmap_ref (pixmap);
1481 if (mask) gdk_pixmap_ref (mask);
1482 cell_set_pixtext (clist, clist_row, column, text, spacing, pixmap, mask);
1484 /* redraw the list if it's not frozen */
1485 if (!GTK_CLIST_FROZEN (clist))
1487 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1488 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1493 gtk_clist_get_pixtext (GtkCList * clist,
1498 GdkPixmap ** pixmap,
1501 GtkCListRow *clist_row;
1503 g_return_val_if_fail (clist != NULL, 0);
1504 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
1506 if (row < 0 || row >= clist->rows)
1508 if (column < 0 || column >= clist->columns)
1511 clist_row = (g_list_nth (clist->row_list, row))->data;
1513 if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
1517 *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
1519 *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
1521 *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
1523 /* mask can be NULL */
1524 *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
1530 gtk_clist_set_foreground (GtkCList * clist,
1534 GtkCListRow *clist_row;
1536 g_return_if_fail (clist != NULL);
1537 g_return_if_fail (GTK_IS_CLIST (clist));
1539 if (row < 0 || row >= clist->rows)
1542 clist_row = (g_list_nth (clist->row_list, row))->data;
1546 clist_row->foreground = *color;
1547 clist_row->fg_set = TRUE;
1550 clist_row->fg_set = FALSE;
1552 if (!GTK_CLIST_FROZEN (clist)
1553 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1554 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1558 gtk_clist_set_background (GtkCList * clist,
1562 GtkCListRow *clist_row;
1564 g_return_if_fail (clist != NULL);
1565 g_return_if_fail (GTK_IS_CLIST (clist));
1567 if (row < 0 || row >= clist->rows)
1570 clist_row = (g_list_nth (clist->row_list, row))->data;
1574 clist_row->background = *color;
1575 clist_row->bg_set = TRUE;
1578 clist_row->bg_set = FALSE;
1580 if (!GTK_CLIST_FROZEN (clist)
1581 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1582 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1586 gtk_clist_set_shift (GtkCList * clist,
1592 GtkCListRow *clist_row;
1594 g_return_if_fail (clist != NULL);
1595 g_return_if_fail (GTK_IS_CLIST (clist));
1597 if (row < 0 || row >= clist->rows)
1599 if (column < 0 || column >= clist->columns)
1602 clist_row = (g_list_nth (clist->row_list, row))->data;
1604 clist_row->cell[column].vertical = vertical;
1605 clist_row->cell[column].horizontal = horizontal;
1607 if (!GTK_CLIST_FROZEN (clist)
1608 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1609 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1613 gtk_clist_append (GtkCList * clist,
1617 GtkCListRow *clist_row;
1619 g_return_val_if_fail (clist != NULL, -1);
1620 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
1622 clist_row = row_new (clist);
1625 /* set the text in the row's columns */
1627 for (i = 0; i < clist->columns; i++)
1629 cell_set_text (clist, clist_row, i, text[i]);
1631 /* keeps track of the end of the list so the list
1632 * doesn't have to be traversed every time a item is added */
1633 if (!clist->row_list)
1635 clist->row_list = g_list_append (clist->row_list, clist_row);
1636 clist->row_list_end = clist->row_list;
1638 /* check the selection mode to see if we should select
1639 * the first row automaticly */
1640 switch (clist->selection_mode)
1642 case GTK_SELECTION_BROWSE:
1643 select_row (clist, 0, -1, NULL);
1651 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
1653 /* redraw the list if it's not frozen */
1654 if (!GTK_CLIST_FROZEN (clist))
1656 adjust_scrollbars (clist);
1658 if (gtk_clist_row_is_visible (clist, clist->rows - 1) != GTK_VISIBILITY_NONE)
1659 draw_rows (clist, NULL);
1662 /* return index of the row */
1663 return clist->rows - 1;
1667 gtk_clist_insert (GtkCList * clist,
1672 GtkCListRow *clist_row;
1674 g_return_if_fail (clist != NULL);
1675 g_return_if_fail (GTK_IS_CLIST (clist));
1676 g_return_if_fail (text != NULL);
1678 /* return if out of bounds */
1679 if (row < 0 || row > clist->rows)
1682 if (clist->rows == 0)
1683 gtk_clist_append (clist, text);
1686 /* create the row */
1687 clist_row = row_new (clist);
1689 /* set the text in the row's columns */
1691 for (i = 0; i < clist->columns; i++)
1693 cell_set_text (clist, clist_row, i, text[i]);
1695 /* reset the row end pointer if we're inserting at the
1696 * end of the list */
1697 if (row == clist->rows)
1698 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
1700 clist->row_list = g_list_insert (clist->row_list, clist_row, row);
1704 if (row < ROW_FROM_YPIXEL (clist, 0))
1705 clist->voffset -= (clist->row_height + CELL_SPACING);
1707 /* syncronize the selection list */
1708 sync_selection (clist, row, SYNC_INSERT);
1711 /* redraw the list if it isn't frozen */
1712 if (!GTK_CLIST_FROZEN (clist))
1714 adjust_scrollbars (clist);
1716 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1717 draw_rows (clist, NULL);
1722 gtk_clist_remove (GtkCList * clist,
1725 gint was_visible, was_selected;
1727 GtkCListRow *clist_row;
1729 g_return_if_fail (clist != NULL);
1730 g_return_if_fail (GTK_IS_CLIST (clist));
1732 /* return if out of bounds */
1733 if (row < 0 || row > (clist->rows - 1))
1736 was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
1739 /* get the row we're going to delete */
1740 list = g_list_nth (clist->row_list, row);
1741 clist_row = list->data;
1743 /* if we're removing a selected row, we have to make sure
1744 * it's properly unselected, and then sync up the clist->selected
1745 * list to reflect the deincrimented indexies of rows after the
1747 if (clist_row->state == GTK_STATE_SELECTED)
1749 switch (clist->selection_mode)
1751 case GTK_SELECTION_SINGLE:
1752 case GTK_SELECTION_MULTIPLE:
1753 case GTK_SELECTION_EXTENDED:
1754 unselect_row (clist, row, -1, NULL);
1757 case GTK_SELECTION_BROWSE:
1758 select_row (clist, row - 1, -1, NULL);
1766 /* reset the row end pointer if we're removing at the
1767 * end of the list */
1768 if (row == clist->rows - 1)
1769 clist->row_list_end = list->prev;
1770 if (row >= clist->focus_row && clist->focus_row >=0)
1773 clist->row_list = g_list_remove (clist->row_list, clist_row);
1776 if (row < ROW_FROM_YPIXEL (clist, 0))
1777 clist->voffset += clist->row_height + CELL_SPACING;
1779 sync_selection (clist, row, SYNC_REMOVE);
1782 row_delete (clist, clist_row);
1784 /* redraw the row if it isn't frozen */
1785 if (!GTK_CLIST_FROZEN (clist))
1787 adjust_scrollbars (clist);
1790 draw_rows (clist, NULL);
1795 sync_selection (GtkCList * clist,
1802 if (mode == SYNC_INSERT)
1807 if (clist->focus_row >= row)
1809 clist->focus_row += d;
1810 if (clist->focus_row == -1 && clist->rows >= 1)
1811 clist->focus_row = 0;
1814 if (clist->selection_mode == GTK_SELECTION_BROWSE && clist->anchor != -1)
1815 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
1817 g_list_free (clist->undo_selection);
1818 g_list_free (clist->undo_unselection);
1819 clist->undo_selection = NULL;
1820 clist->undo_unselection = NULL;
1823 clist->drag_pos = -1;
1824 clist->undo_anchor = clist->focus_row;
1826 list = clist->selection;
1829 if (GPOINTER_TO_INT (list->data) >= row)
1830 list->data = ((gchar*) list->data) + d;
1836 gtk_clist_clear (GtkCList * clist)
1838 GTK_CLIST_CLASS_FW (clist)->clear (clist);
1842 real_clear (GtkCList * clist)
1846 g_return_if_fail (clist != NULL);
1847 g_return_if_fail (GTK_IS_CLIST (clist));
1849 /* remove all the rows */
1850 for (list = clist->row_list; list; list = list->next)
1851 row_delete (clist, GTK_CLIST_ROW (list));
1853 g_list_free (clist->row_list);
1855 /* free up the selection list */
1856 g_list_free (clist->selection);
1857 g_list_free (clist->undo_selection);
1858 g_list_free (clist->undo_unselection);
1860 clist->row_list = NULL;
1861 clist->row_list_end = NULL;
1862 clist->selection = NULL;
1863 clist->selection_end = NULL;
1864 clist->undo_selection = NULL;
1865 clist->undo_unselection = NULL;
1868 clist->focus_row = -1;
1870 clist->undo_anchor = -1;
1871 clist->anchor_state = GTK_STATE_SELECTED;
1872 clist->drag_pos = -1;
1874 /* zero-out the scrollbars */
1875 if (clist->vscrollbar)
1877 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
1878 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
1880 if (!GTK_CLIST_FROZEN (clist))
1881 gtk_clist_thaw (clist);
1886 gtk_clist_swap_rows (GtkCList * clist,
1891 GList *list, *link1, *link2;
1894 g_return_if_fail (clist != NULL);
1895 g_return_if_fail (GTK_IS_CLIST (clist));
1897 if (row1 < 0 || row1 > (clist->rows - 1))
1900 if (row2 < 0 || row2 > (clist->rows - 1))
1903 first = MIN (row1, row2);
1904 last = MAX (row1, row2);
1906 link1 = g_list_nth (clist->row_list, first);
1907 link2 = g_list_nth (link1, row2 - row1);
1910 link1->data = link2->data;
1913 list = clist->selection;
1916 if (GPOINTER_TO_INT (list->data) == row1)
1917 GPOINTER_TO_INT (list->data) = row2;
1919 if (GPOINTER_TO_INT (list->data) == row2)
1920 GPOINTER_TO_INT (list->data) = row1;
1925 if (!GTK_CLIST_FROZEN (clist))
1927 if (gtk_clist_row_is_visible (clist, row1) != GTK_VISIBILITY_NONE)
1928 GTK_CLIST_CLASS_FW (clist)->draw_row
1929 (clist, NULL, row1, GTK_CLIST_ROW (link2));
1931 if (gtk_clist_row_is_visible (clist, row2) != GTK_VISIBILITY_NONE)
1932 GTK_CLIST_CLASS_FW (clist)->draw_row
1933 (clist, NULL, row2, GTK_CLIST_ROW (link1));
1938 gtk_clist_set_row_data (GtkCList * clist,
1942 gtk_clist_set_row_data_full (clist, row, data, NULL);
1946 gtk_clist_set_row_data_full (GtkCList * clist,
1949 GtkDestroyNotify destroy)
1951 GtkCListRow *clist_row;
1953 g_return_if_fail (clist != NULL);
1954 g_return_if_fail (GTK_IS_CLIST (clist));
1956 if (row < 0 || row > (clist->rows - 1))
1959 clist_row = (g_list_nth (clist->row_list, row))->data;
1960 clist_row->data = data;
1961 clist_row->destroy = destroy;
1963 /* re-send the selected signal if data is changed/added
1964 * so the application can respond to the new data --
1965 * this could be questionable behavior */
1966 if (clist_row->state == GTK_STATE_SELECTED)
1967 select_row (clist, row, -1, NULL);
1971 gtk_clist_get_row_data (GtkCList * clist,
1974 GtkCListRow *clist_row;
1976 g_return_val_if_fail (clist != NULL, NULL);
1977 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1979 if (row < 0 || row > (clist->rows - 1))
1982 clist_row = (g_list_nth (clist->row_list, row))->data;
1983 return clist_row->data;
1987 gtk_clist_find_row_from_data (GtkCList * clist,
1993 g_return_val_if_fail (clist != NULL, -1);
1994 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
1996 if (clist->rows < 1)
1997 return -1; /* is this an optimization or just worthless? */
1999 for (n = 0, list = clist->row_list; list; n++, list = list->next)
2000 if (GTK_CLIST_ROW (list)->data == data)
2007 gtk_clist_select_row (GtkCList * clist,
2011 g_return_if_fail (clist != NULL);
2012 g_return_if_fail (GTK_IS_CLIST (clist));
2014 if (row < 0 || row >= clist->rows)
2017 if (column < -1 || column >= clist->columns)
2020 select_row (clist, row, column, NULL);
2024 gtk_clist_unselect_row (GtkCList * clist,
2028 g_return_if_fail (clist != NULL);
2029 g_return_if_fail (GTK_IS_CLIST (clist));
2031 if (row < 0 || row >= clist->rows)
2034 if (column < -1 || column >= clist->columns)
2037 unselect_row (clist, row, column, NULL);
2041 gtk_clist_row_is_visible (GtkCList * clist,
2046 g_return_val_if_fail (clist != NULL, 0);
2047 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
2049 if (row < 0 || row >= clist->rows)
2050 return GTK_VISIBILITY_NONE;
2052 if (clist->row_height == 0)
2053 return GTK_VISIBILITY_NONE;
2055 if (row < ROW_FROM_YPIXEL (clist, 0))
2056 return GTK_VISIBILITY_NONE;
2058 if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
2059 return GTK_VISIBILITY_NONE;
2061 top = ROW_TOP_YPIXEL (clist, row);
2064 || ((top + clist->row_height) >= clist->clist_window_height))
2065 return GTK_VISIBILITY_PARTIAL;
2067 return GTK_VISIBILITY_FULL;
2071 gtk_clist_get_vadjustment (GtkCList * clist)
2073 g_return_val_if_fail (clist != NULL, NULL);
2074 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
2076 return gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
2080 gtk_clist_get_hadjustment (GtkCList * clist)
2082 g_return_val_if_fail (clist != NULL, NULL);
2083 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
2085 return gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
2089 gtk_clist_set_policy (GtkCList * clist,
2090 GtkPolicyType vscrollbar_policy,
2091 GtkPolicyType hscrollbar_policy)
2093 g_return_if_fail (clist != NULL);
2094 g_return_if_fail (GTK_IS_CLIST (clist));
2096 if (clist->vscrollbar_policy != vscrollbar_policy)
2098 clist->vscrollbar_policy = vscrollbar_policy;
2100 if (GTK_WIDGET (clist)->parent)
2101 gtk_widget_queue_resize (GTK_WIDGET (clist));
2104 if (clist->hscrollbar_policy != hscrollbar_policy)
2106 clist->hscrollbar_policy = hscrollbar_policy;
2108 if (GTK_WIDGET (clist)->parent)
2109 gtk_widget_queue_resize (GTK_WIDGET (clist));
2114 gtk_clist_undo_selection (GtkCList *clist)
2116 g_return_if_fail (clist != NULL);
2117 g_return_if_fail (GTK_IS_CLIST (clist));
2119 if (clist->selection_mode == GTK_SELECTION_EXTENDED &&
2120 (clist->undo_selection || clist->undo_unselection))
2121 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNDO_SELECTION]);
2125 real_undo_selection (GtkCList *clist)
2129 g_return_if_fail (clist != NULL);
2130 g_return_if_fail (GTK_IS_CLIST (clist));
2132 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
2133 clist->selection_mode != GTK_SELECTION_EXTENDED)
2136 if (clist->anchor >= 0)
2137 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2139 if (!(clist->undo_selection || clist->undo_unselection))
2141 gtk_clist_unselect_all (clist);
2145 for (work = clist->undo_selection; work; work = work->next)
2146 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2147 GPOINTER_TO_INT (work->data), -1, NULL);
2149 for (work = clist->undo_unselection; work; work = work->next)
2150 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2151 GPOINTER_TO_INT (work->data), -1, NULL);
2153 if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
2155 gtk_clist_draw_focus (GTK_WIDGET (clist));
2156 clist->focus_row = clist->undo_anchor;
2157 gtk_clist_draw_focus (GTK_WIDGET (clist));
2160 clist->focus_row = clist->undo_anchor;
2162 clist->undo_anchor = -1;
2164 g_list_free (clist->undo_selection);
2165 g_list_free (clist->undo_unselection);
2166 clist->undo_selection = NULL;
2167 clist->undo_unselection = NULL;
2169 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
2170 clist->clist_window_height)
2171 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
2172 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
2173 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
2179 * gtk_clist_finalize
2182 gtk_clist_destroy (GtkObject * object)
2187 g_return_if_fail (object != NULL);
2188 g_return_if_fail (GTK_IS_CLIST (object));
2190 clist = GTK_CLIST (object);
2192 /* freeze the list */
2193 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
2195 /* get rid of all the rows */
2196 gtk_clist_clear (clist);
2198 /* Since we don't have a _remove method, unparent the children
2199 * instead of destroying them so the focus will be unset properly.
2200 * (For other containers, the _remove method takes care of the
2201 * unparent) The destroy will happen when the refcount drops
2205 /* destroy the scrollbars */
2206 if (clist->vscrollbar)
2208 gtk_widget_unparent (clist->vscrollbar);
2209 clist->vscrollbar = NULL;
2211 if (clist->hscrollbar)
2213 gtk_widget_unparent (clist->hscrollbar);
2214 clist->hscrollbar = NULL;
2219 gtk_timeout_remove (clist->htimer);
2224 gtk_timeout_remove (clist->vtimer);
2228 /* destroy the column buttons */
2229 for (i = 0; i < clist->columns; i++)
2230 if (clist->column[i].button)
2232 gtk_widget_unparent (clist->column[i].button);
2233 clist->column[i].button = NULL;
2236 if (GTK_OBJECT_CLASS (parent_class)->destroy)
2237 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
2241 gtk_clist_finalize (GtkObject * object)
2245 g_return_if_fail (object != NULL);
2246 g_return_if_fail (GTK_IS_CLIST (object));
2248 clist = GTK_CLIST (object);
2250 columns_delete (clist);
2252 g_mem_chunk_destroy (clist->cell_mem_chunk);
2253 g_mem_chunk_destroy (clist->row_mem_chunk);
2255 if (GTK_OBJECT_CLASS (parent_class)->finalize)
2256 (*GTK_OBJECT_CLASS (parent_class)->finalize) (object);
2262 * gtk_clist_unrealize
2267 * gtk_clist_button_press
2268 * gtk_clist_button_release
2270 * gtk_clist_size_request
2271 * gtk_clist_size_allocate
2274 gtk_clist_realize (GtkWidget * widget)
2278 GdkWindowAttr attributes;
2279 gint attributes_mask;
2283 g_return_if_fail (widget != NULL);
2284 g_return_if_fail (GTK_IS_CLIST (widget));
2286 clist = GTK_CLIST (widget);
2288 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
2290 add_style_data (clist);
2292 border_width = GTK_CONTAINER (widget)->border_width;
2294 attributes.window_type = GDK_WINDOW_CHILD;
2295 attributes.x = widget->allocation.x + border_width;
2296 attributes.y = widget->allocation.y + border_width;
2297 attributes.width = widget->allocation.width - border_width * 2;
2298 attributes.height = widget->allocation.height - border_width * 2;
2299 attributes.wclass = GDK_INPUT_OUTPUT;
2300 attributes.visual = gtk_widget_get_visual (widget);
2301 attributes.colormap = gtk_widget_get_colormap (widget);
2302 attributes.event_mask = gtk_widget_get_events (widget);
2303 attributes.event_mask |= (GDK_EXPOSURE_MASK |
2304 GDK_BUTTON_PRESS_MASK |
2305 GDK_BUTTON_RELEASE_MASK |
2306 GDK_KEY_PRESS_MASK |
2307 GDK_KEY_RELEASE_MASK);
2308 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
2311 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
2312 gdk_window_set_user_data (widget->window, clist);
2314 widget->style = gtk_style_attach (widget->style, widget->window);
2316 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
2318 /* column-title window */
2320 attributes.x = clist->column_title_area.x;
2321 attributes.y = clist->column_title_area.y;
2322 attributes.width = clist->column_title_area.width;
2323 attributes.height = clist->column_title_area.height;
2325 clist->title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2326 gdk_window_set_user_data (clist->title_window, clist);
2328 gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_SELECTED);
2329 gdk_window_show (clist->title_window);
2331 /* set things up so column buttons are drawn in title window */
2332 for (i = 0; i < clist->columns; i++)
2333 if (clist->column[i].button)
2334 gtk_widget_set_parent_window (clist->column[i].button, clist->title_window);
2337 attributes.x = clist->internal_allocation.x + widget->style->klass->xthickness;
2338 attributes.y = clist->internal_allocation.y + widget->style->klass->ythickness +
2339 clist->column_title_area.height;
2340 attributes.width = clist->clist_window_width;
2341 attributes.height = clist->clist_window_height;
2343 clist->clist_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2344 gdk_window_set_user_data (clist->clist_window, clist);
2346 gdk_window_set_background (clist->clist_window, &widget->style->bg[GTK_STATE_PRELIGHT]);
2347 gdk_window_show (clist->clist_window);
2348 gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
2349 &clist->clist_window_height);
2351 /* create resize windows */
2352 attributes.wclass = GDK_INPUT_ONLY;
2353 attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
2354 GDK_BUTTON_RELEASE_MASK |
2355 GDK_POINTER_MOTION_MASK |
2356 GDK_POINTER_MOTION_HINT_MASK |
2357 GDK_KEY_PRESS_MASK);
2358 attributes.cursor = clist->cursor_drag = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
2359 attributes_mask = GDK_WA_CURSOR;
2361 for (i = 0; i < clist->columns; i++)
2363 clist->column[i].window = gdk_window_new (clist->title_window, &attributes, attributes_mask);
2364 gdk_window_set_user_data (clist->column[i].window, clist);
2367 /* This is slightly less efficient than creating them with the
2368 * right size to begin with, but easier
2370 size_allocate_title_buttons (clist);
2373 clist->fg_gc = gdk_gc_new (widget->window);
2374 clist->bg_gc = gdk_gc_new (widget->window);
2376 /* We'll use this gc to do scrolling as well */
2377 gdk_gc_set_exposures (clist->fg_gc, TRUE);
2379 values.foreground = widget->style->white;
2380 values.function = GDK_XOR;
2381 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
2382 clist->xor_gc = gdk_gc_new_with_values (widget->window,
2390 gtk_clist_unrealize (GtkWidget * widget)
2395 g_return_if_fail (widget != NULL);
2396 g_return_if_fail (GTK_IS_CLIST (widget));
2398 clist = GTK_CLIST (widget);
2400 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
2402 gdk_cursor_destroy (clist->cursor_drag);
2403 gdk_gc_destroy (clist->xor_gc);
2404 gdk_gc_destroy (clist->fg_gc);
2405 gdk_gc_destroy (clist->bg_gc);
2407 for (i = 0; i < clist->columns; i++)
2408 if (clist->column[i].window)
2410 gdk_window_set_user_data (clist->column[i].window, NULL);
2411 gdk_window_destroy (clist->column[i].window);
2412 clist->column[i].window = NULL;
2415 gdk_window_set_user_data (clist->clist_window, NULL);
2416 gdk_window_destroy (clist->clist_window);
2417 clist->clist_window = NULL;
2419 gdk_window_set_user_data (clist->title_window, NULL);
2420 gdk_window_destroy (clist->title_window);
2421 clist->title_window = NULL;
2423 clist->cursor_drag = NULL;
2424 clist->xor_gc = NULL;
2425 clist->fg_gc = NULL;
2426 clist->bg_gc = NULL;
2428 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
2429 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
2433 gtk_clist_map (GtkWidget * widget)
2438 g_return_if_fail (widget != NULL);
2439 g_return_if_fail (GTK_IS_CLIST (widget));
2441 clist = GTK_CLIST (widget);
2443 if (!GTK_WIDGET_MAPPED (widget))
2445 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2447 gdk_window_show (widget->window);
2448 gdk_window_show (clist->title_window);
2449 gdk_window_show (clist->clist_window);
2451 /* map column buttons */
2452 for (i = 0; i < clist->columns; i++)
2453 if (clist->column[i].button &&
2454 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
2455 !GTK_WIDGET_MAPPED (clist->column[i].button))
2456 gtk_widget_map (clist->column[i].button);
2458 /* map resize windows AFTER column buttons (above) */
2459 for (i = 0; i < clist->columns; i++)
2460 if (clist->column[i].window && clist->column[i].button)
2461 gdk_window_show (clist->column[i].window);
2463 /* map vscrollbars */
2464 if (GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
2465 !GTK_WIDGET_MAPPED (clist->vscrollbar))
2466 gtk_widget_map (clist->vscrollbar);
2468 if (GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
2469 !GTK_WIDGET_MAPPED (clist->hscrollbar))
2470 gtk_widget_map (clist->hscrollbar);
2472 /* unfreeze the list */
2473 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
2478 gtk_clist_unmap (GtkWidget * widget)
2483 g_return_if_fail (widget != NULL);
2484 g_return_if_fail (GTK_IS_CLIST (widget));
2486 clist = GTK_CLIST (widget);
2488 if (GTK_WIDGET_MAPPED (widget))
2490 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
2492 for (i = 0; i < clist->columns; i++)
2493 if (clist->column[i].window)
2494 gdk_window_hide (clist->column[i].window);
2496 gdk_window_hide (clist->clist_window);
2497 gdk_window_hide (clist->title_window);
2498 gdk_window_hide (widget->window);
2500 /* unmap scrollbars */
2501 if (GTK_WIDGET_MAPPED (clist->vscrollbar))
2502 gtk_widget_unmap (clist->vscrollbar);
2504 if (GTK_WIDGET_MAPPED (clist->hscrollbar))
2505 gtk_widget_unmap (clist->hscrollbar);
2507 /* unmap column buttons */
2508 for (i = 0; i < clist->columns; i++)
2509 if (clist->column[i].button &&
2510 GTK_WIDGET_MAPPED (clist->column[i].button))
2511 gtk_widget_unmap (clist->column[i].button);
2513 /* freeze the list */
2514 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
2519 gtk_clist_draw (GtkWidget * widget,
2520 GdkRectangle * area)
2525 g_return_if_fail (widget != NULL);
2526 g_return_if_fail (GTK_IS_CLIST (widget));
2527 g_return_if_fail (area != NULL);
2529 if (GTK_WIDGET_DRAWABLE (widget))
2531 clist = GTK_CLIST (widget);
2532 border_width = GTK_CONTAINER (widget)->border_width;
2534 gdk_window_clear_area (widget->window,
2535 area->x - border_width,
2536 area->y - border_width,
2537 area->width, area->height);
2539 /* draw list shadow/border */
2540 gtk_draw_shadow (widget->style, widget->window,
2541 GTK_STATE_NORMAL, clist->shadow_type,
2543 clist->clist_window_width + (2 * widget->style->klass->xthickness),
2544 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
2545 clist->column_title_area.height);
2547 gdk_window_clear_area (clist->clist_window,
2550 draw_rows (clist, NULL);
2555 gtk_clist_expose (GtkWidget * widget,
2556 GdkEventExpose * event)
2560 g_return_val_if_fail (widget != NULL, FALSE);
2561 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2562 g_return_val_if_fail (event != NULL, FALSE);
2564 if (GTK_WIDGET_DRAWABLE (widget))
2566 clist = GTK_CLIST (widget);
2569 if (event->window == widget->window)
2570 gtk_draw_shadow (widget->style, widget->window,
2571 GTK_STATE_NORMAL, clist->shadow_type,
2573 clist->clist_window_width + (2 * widget->style->klass->xthickness),
2574 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
2575 clist->column_title_area.height);
2577 /* exposure events on the list */
2578 if (event->window == clist->clist_window)
2579 draw_rows (clist, &event->area);
2586 gtk_clist_button_press (GtkWidget * widget,
2587 GdkEventButton * event)
2596 g_return_val_if_fail (widget != NULL, FALSE);
2597 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2598 g_return_val_if_fail (event != NULL, FALSE);
2600 clist = GTK_CLIST (widget);
2602 /* we don't handle button 2 and 3 */
2603 if (event->button != 1)
2606 /* selections on the list */
2607 if (event->window == clist->clist_window)
2612 if (get_selection_info (clist, x, y, &row, &column))
2614 gint old_row = clist->focus_row;
2616 if (clist->focus_row == -1)
2619 if (event->type == GDK_BUTTON_PRESS)
2621 GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION);
2622 gdk_pointer_grab (clist->clist_window, FALSE,
2623 GDK_POINTER_MOTION_HINT_MASK |
2624 GDK_BUTTON1_MOTION_MASK |
2625 GDK_BUTTON_RELEASE_MASK,
2626 NULL, NULL, event->time);
2627 gtk_grab_add (widget);
2629 else if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (widget))
2631 GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
2632 gtk_grab_remove (widget);
2633 gdk_pointer_ungrab (event->time);
2636 if (GTK_CLIST_ADD_MODE (clist))
2638 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
2639 if (GTK_WIDGET_HAS_FOCUS (widget))
2641 gtk_clist_draw_focus (widget);
2642 gdk_gc_set_line_attributes (clist->xor_gc, 1,
2643 GDK_LINE_SOLID, 0, 0);
2644 clist->focus_row = row;
2645 gtk_clist_draw_focus (widget);
2649 gdk_gc_set_line_attributes (clist->xor_gc, 1,
2650 GDK_LINE_SOLID, 0, 0);
2651 clist->focus_row = row;
2654 else if (row != clist->focus_row)
2656 if (GTK_WIDGET_HAS_FOCUS (widget))
2658 gtk_clist_draw_focus (widget);
2659 clist->focus_row = row;
2660 gtk_clist_draw_focus (widget);
2663 clist->focus_row = row;
2666 if (!GTK_WIDGET_HAS_FOCUS (widget))
2667 gtk_widget_grab_focus (widget);
2669 switch (clist->selection_mode)
2671 case GTK_SELECTION_SINGLE:
2672 case GTK_SELECTION_MULTIPLE:
2673 if (event->type != GDK_BUTTON_PRESS)
2674 select_row (clist, row, column, (GdkEvent *) event);
2676 clist->anchor = row;
2679 case GTK_SELECTION_BROWSE:
2680 select_row (clist, row, column, (GdkEvent *) event);
2683 case GTK_SELECTION_EXTENDED:
2684 if (event->type != GDK_BUTTON_PRESS)
2686 if (clist->anchor != -1)
2688 update_extended_selection (clist, clist->focus_row);
2689 GTK_CLIST_CLASS_FW (clist)->resync_selection
2690 (clist, (GdkEvent *) event);
2692 select_row (clist, row, column, (GdkEvent *) event);
2696 if (event->state & GDK_CONTROL_MASK)
2698 if (event->state & GDK_SHIFT_MASK)
2700 if (clist->anchor < 0)
2702 g_list_free (clist->undo_selection);
2703 g_list_free (clist->undo_unselection);
2704 clist->undo_selection = NULL;
2705 clist->undo_unselection = NULL;
2706 clist->anchor = old_row;
2707 clist->drag_pos = old_row;
2708 clist->undo_anchor = old_row;
2710 update_extended_selection (clist, clist->focus_row);
2714 if (clist->anchor == -1)
2715 set_anchor (clist, TRUE, row, old_row);
2717 update_extended_selection (clist, clist->focus_row);
2722 if (event->state & GDK_SHIFT_MASK)
2724 set_anchor (clist, FALSE, old_row, old_row);
2725 update_extended_selection (clist, clist->focus_row);
2729 if (clist->anchor == -1)
2730 set_anchor (clist, FALSE, row, old_row);
2732 update_extended_selection (clist, clist->focus_row);
2743 /* press on resize windows */
2744 for (i = 0; i < clist->columns; i++)
2745 if (clist->column[i].window && event->window == clist->column[i].window)
2747 GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
2748 gtk_widget_get_pointer (widget, &clist->x_drag, NULL);
2750 gdk_pointer_grab (clist->column[i].window, FALSE,
2751 GDK_POINTER_MOTION_HINT_MASK |
2752 GDK_BUTTON1_MOTION_MASK |
2753 GDK_BUTTON_RELEASE_MASK,
2754 NULL, NULL, event->time);
2755 gtk_grab_add (widget);
2757 if (GTK_CLIST_ADD_MODE (clist))
2758 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
2760 draw_xor_line (clist);
2768 gtk_clist_button_release (GtkWidget * widget,
2769 GdkEventButton * event)
2771 gint i, x, width, visible;
2774 g_return_val_if_fail (widget != NULL, FALSE);
2775 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2776 g_return_val_if_fail (event != NULL, FALSE);
2778 clist = GTK_CLIST (widget);
2780 /* we don't handle button 2 and 3 */
2781 if (event->button != 1)
2784 /* release on resize windows */
2785 if (GTK_CLIST_IN_DRAG (clist))
2786 for (i = 0; i < clist->columns; i++)
2787 if (clist->column[i].window && event->window == clist->column[i].window)
2789 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
2790 gtk_widget_get_pointer (widget, &x, NULL);
2791 width = new_column_width (clist, i, &x, &visible);
2793 gtk_grab_remove (widget);
2794 gdk_pointer_ungrab (event->time);
2797 draw_xor_line (clist);
2799 if (GTK_CLIST_ADD_MODE (clist))
2801 gdk_gc_set_line_attributes (clist->xor_gc, 1,
2802 GDK_LINE_ON_OFF_DASH, 0, 0);
2803 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
2806 resize_column (clist, i, width);
2810 if (GTK_CLIST_DRAG_SELECTION (clist))
2815 GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
2816 gtk_grab_remove (widget);
2817 gdk_pointer_ungrab (event->time);
2820 gtk_timeout_remove (clist->htimer);
2825 gtk_timeout_remove (clist->vtimer);
2828 switch (clist->selection_mode)
2830 case GTK_SELECTION_EXTENDED:
2831 if (!(event->state & GDK_SHIFT_MASK) ||
2832 event->x < 0 || event->x >= clist->clist_window_width ||
2833 event->y < 0 || event->y >= clist->clist_window_height)
2834 GTK_CLIST_CLASS_FW (clist)->resync_selection
2835 (clist, (GdkEvent *) event);
2838 case GTK_SELECTION_SINGLE:
2839 case GTK_SELECTION_MULTIPLE:
2840 if (get_selection_info (clist, event->x, event->y, &row, &column))
2842 if (clist->anchor == clist->focus_row)
2843 toggle_row (clist, row, column, (GdkEvent *) event);
2857 horizontal_timeout (GtkCList *clist)
2860 GdkEventMotion event;
2861 GdkModifierType mask;
2863 g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
2866 gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
2873 gtk_clist_motion (GTK_WIDGET (clist), &event);
2879 vertical_timeout (GtkCList *clist)
2882 GdkEventMotion event;
2883 GdkModifierType mask;
2885 g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
2888 gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
2895 gtk_clist_motion (GTK_WIDGET (clist), &event);
2901 move_vertical (GtkCList *clist,
2908 adj = GTK_RANGE (clist->vscrollbar)->adjustment;
2910 y = ROW_TOP_YPIXEL (clist, row) - clist->voffset;
2912 y = y - align * (clist->clist_window_height - clist->row_height)
2913 + (2 * align - 1) * CELL_SPACING;
2915 if (y + adj->page_size > adj->upper)
2916 adj->value = adj->upper - adj->page_size;
2920 gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
2924 move_horizontal (GtkCList *clist,
2930 adj = GTK_RANGE (clist->hscrollbar)->adjustment;
2934 upper = adj->upper - adj->page_size;
2935 adj->value = MIN (adj->value, upper);
2936 adj->value = MAX (adj->value, 0.0);
2938 gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
2942 gtk_clist_motion (GtkWidget * widget,
2943 GdkEventMotion * event)
2946 gint i, x, y, visible;
2949 g_return_val_if_fail (widget != NULL, FALSE);
2950 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2952 clist = GTK_CLIST (widget);
2954 if (!(gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)))
2957 if (GTK_CLIST_IN_DRAG (clist))
2958 for (i = 0; i < clist->columns; i++)
2959 if (clist->column[i].window && event->window == clist->column[i].window)
2961 if (event->is_hint || event->window != widget->window)
2962 gtk_widget_get_pointer (widget, &x, NULL);
2966 new_column_width (clist, i, &x, &visible);
2967 /* Welcome to my hack! I'm going to use a value of x_drag = -99999
2968 * to indicate that the xor line is already invisible */
2969 if (!visible && clist->x_drag != -99999)
2971 draw_xor_line (clist);
2972 clist->x_drag = -99999;
2975 if (x != clist->x_drag && visible)
2977 if (clist->x_drag != -99999)
2978 draw_xor_line (clist);
2981 draw_xor_line (clist);
2986 if (event->is_hint || event->window != clist->clist_window)
2987 gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
2989 /* horizontal autoscrolling */
2990 if (LIST_WIDTH (clist) > clist->clist_window_width &&
2991 (x < 0 || x >= clist->clist_window_width))
2996 clist->htimer = gtk_timeout_add
2997 (SCROLL_TIME, (GtkFunction) horizontal_timeout, clist);
2999 if (!((x < 0 && GTK_RANGE (clist->hscrollbar)->adjustment->value == 0) ||
3000 (x >= clist->clist_window_width &&
3001 GTK_RANGE (clist->hscrollbar)->adjustment->value ==
3002 LIST_WIDTH (clist) - clist->clist_window_width)))
3005 move_horizontal (clist, -1 + (x/2));
3007 move_horizontal (clist, 1 + (x - clist->clist_window_width) / 2);
3011 if (GTK_CLIST_IN_DRAG (clist))
3014 /* vertical autoscrolling */
3015 row = ROW_FROM_YPIXEL (clist, y);
3017 /* don't scroll on last pixel row if it's a cell spacing */
3018 if (y == clist->clist_window_height-1 &&
3019 y == ROW_TOP_YPIXEL (clist, row-1) + clist->row_height)
3022 if (LIST_HEIGHT (clist) > clist->clist_window_height &&
3023 (y < 0 || y >= clist->clist_window_height))
3028 clist->vtimer = gtk_timeout_add (SCROLL_TIME,
3029 (GtkFunction) vertical_timeout, clist);
3031 if (GTK_CLIST_DRAG_SELECTION (clist))
3033 if ((y < 0 && clist->focus_row == 0) ||
3034 (y >= clist->clist_window_height &&
3035 clist->focus_row == clist->rows-1))
3040 row = CLAMP (row, 0, clist->rows - 1);
3042 if (GTK_CLIST_DRAG_SELECTION (clist))
3044 if (row == clist->focus_row)
3047 gtk_clist_draw_focus (widget);
3048 clist->focus_row = row;
3049 gtk_clist_draw_focus (widget);
3051 switch (clist->selection_mode)
3053 case GTK_SELECTION_BROWSE:
3054 select_row (clist, clist->focus_row, - 1, (GdkEvent *) event);
3057 case GTK_SELECTION_EXTENDED:
3058 update_extended_selection (clist, clist->focus_row);
3066 if (ROW_TOP_YPIXEL(clist, row) < 0)
3067 move_vertical (clist, row, 0);
3068 else if (ROW_TOP_YPIXEL(clist, row) + clist->row_height >
3069 clist->clist_window_height)
3070 move_vertical (clist, row, 1);
3076 gtk_clist_size_request (GtkWidget * widget,
3077 GtkRequisition * requisition)
3082 g_return_if_fail (widget != NULL);
3083 g_return_if_fail (GTK_IS_CLIST (widget));
3084 g_return_if_fail (requisition != NULL);
3086 clist = GTK_CLIST (widget);
3088 add_style_data (clist);
3090 requisition->width = 0;
3091 requisition->height = 0;
3093 /* compute the size of the column title (title) area */
3094 clist->column_title_area.height = 0;
3095 if (GTK_CLIST_SHOW_TITLES (clist))
3096 for (i = 0; i < clist->columns; i++)
3097 if (clist->column[i].button)
3099 gtk_widget_size_request (clist->column[i].button, &clist->column[i].button->requisition);
3100 clist->column_title_area.height = MAX (clist->column_title_area.height,
3101 clist->column[i].button->requisition.height);
3103 requisition->height += clist->column_title_area.height;
3105 /* add the vscrollbar space */
3106 if ((clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
3107 GTK_WIDGET_VISIBLE (clist->vscrollbar))
3109 gtk_widget_size_request (clist->vscrollbar, &clist->vscrollbar->requisition);
3111 requisition->width += clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist);
3112 requisition->height = MAX (requisition->height,
3113 clist->vscrollbar->requisition.height);
3116 /* add the hscrollbar space */
3117 if ((clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
3118 GTK_WIDGET_VISIBLE (clist->hscrollbar))
3120 gtk_widget_size_request (clist->hscrollbar, &clist->hscrollbar->requisition);
3122 requisition->height += clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist);
3123 requisition->width = MAX (clist->hscrollbar->requisition.width,
3124 requisition->width -
3125 clist->vscrollbar->requisition.width);
3129 requisition->width += widget->style->klass->xthickness * 2 +
3130 GTK_CONTAINER (widget)->border_width * 2;
3131 requisition->height += widget->style->klass->ythickness * 2 +
3132 GTK_CONTAINER (widget)->border_width * 2;
3136 gtk_clist_size_allocate (GtkWidget * widget,
3137 GtkAllocation * allocation)
3140 GtkAllocation clist_allocation;
3141 GtkAllocation child_allocation;
3142 gint i, vscrollbar_vis, hscrollbar_vis;
3144 g_return_if_fail (widget != NULL);
3145 g_return_if_fail (GTK_IS_CLIST (widget));
3146 g_return_if_fail (allocation != NULL);
3148 clist = GTK_CLIST (widget);
3149 widget->allocation = *allocation;
3151 if (GTK_WIDGET_REALIZED (widget))
3153 gdk_window_move_resize (widget->window,
3154 allocation->x + GTK_CONTAINER (widget)->border_width,
3155 allocation->y + GTK_CONTAINER (widget)->border_width,
3156 allocation->width - GTK_CONTAINER (widget)->border_width * 2,
3157 allocation->height - GTK_CONTAINER (widget)->border_width * 2);
3160 /* use internal allocation structure for all the math
3161 * because it's easier than always subtracting the container
3163 clist->internal_allocation.x = 0;
3164 clist->internal_allocation.y = 0;
3165 clist->internal_allocation.width = MAX (1, allocation->width -
3166 GTK_CONTAINER (widget)->border_width * 2);
3167 clist->internal_allocation.height = MAX (1, allocation->height -
3168 GTK_CONTAINER (widget)->border_width * 2);
3170 /* allocate clist window assuming no scrollbars */
3171 clist_allocation.x = clist->internal_allocation.x + widget->style->klass->xthickness;
3172 clist_allocation.y = clist->internal_allocation.y + widget->style->klass->ythickness +
3173 clist->column_title_area.height;
3174 clist_allocation.width = MAX (1, clist->internal_allocation.width -
3175 (2 * widget->style->klass->xthickness));
3176 clist_allocation.height = MAX (1, clist->internal_allocation.height -
3177 (2 * widget->style->klass->ythickness) -
3178 clist->column_title_area.height);
3181 * here's where we decide to show/not show the scrollbars
3186 for (i = 0; i <= 1; i++)
3188 if (LIST_HEIGHT (clist) <= clist_allocation.height &&
3189 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
3195 if (!vscrollbar_vis)
3198 clist_allocation.width = MAX (1, clist_allocation.width -
3199 (clist->vscrollbar->requisition.width +
3200 SCROLLBAR_SPACING (clist)));
3204 if (LIST_WIDTH (clist) <= clist_allocation.width &&
3205 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
3211 if (!hscrollbar_vis)
3214 clist_allocation.height = MAX (1, clist_allocation.height -
3215 (clist->hscrollbar->requisition.height +
3216 SCROLLBAR_SPACING (clist)));
3221 clist->clist_window_width = clist_allocation.width;
3222 clist->clist_window_height = clist_allocation.height;
3224 if (GTK_WIDGET_REALIZED (widget))
3226 gdk_window_move_resize (clist->clist_window,
3229 clist_allocation.width,
3230 clist_allocation.height);
3233 /* position the window which holds the column title buttons */
3234 clist->column_title_area.x = widget->style->klass->xthickness;
3235 clist->column_title_area.y = widget->style->klass->ythickness;
3236 clist->column_title_area.width = clist_allocation.width;
3238 if (GTK_WIDGET_REALIZED (widget))
3240 gdk_window_move_resize (clist->title_window,
3241 clist->column_title_area.x,
3242 clist->column_title_area.y,
3243 clist->column_title_area.width,
3244 clist->column_title_area.height);
3247 /* column button allocation */
3248 size_allocate_columns (clist);
3250 if (GTK_WIDGET_REALIZED (widget))
3251 size_allocate_title_buttons (clist);
3253 adjust_scrollbars (clist);
3255 /* allocate the vscrollbar */
3258 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
3259 gtk_widget_show (clist->vscrollbar);
3261 child_allocation.x = clist->internal_allocation.x +
3262 clist->internal_allocation.width -
3263 clist->vscrollbar->requisition.width;
3264 child_allocation.y = clist->internal_allocation.y;
3265 child_allocation.width = clist->vscrollbar->requisition.width;
3266 child_allocation.height = MAX (1, clist->internal_allocation.height -
3267 (hscrollbar_vis ? (clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist)) : 0));
3269 gtk_widget_size_allocate (clist->vscrollbar, &child_allocation);
3273 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
3274 gtk_widget_hide (clist->vscrollbar);
3279 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
3280 gtk_widget_show (clist->hscrollbar);
3282 child_allocation.x = clist->internal_allocation.x;
3283 child_allocation.y = clist->internal_allocation.y +
3284 clist->internal_allocation.height -
3285 clist->hscrollbar->requisition.height;
3286 child_allocation.width = MAX (1, clist->internal_allocation.width -
3287 (vscrollbar_vis ? (clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist)) : 0));
3288 child_allocation.height = clist->hscrollbar->requisition.height;
3290 gtk_widget_size_allocate (clist->hscrollbar, &child_allocation);
3294 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
3295 gtk_widget_hide (clist->hscrollbar);
3298 /* set the vscrollbar adjustments */
3299 adjust_scrollbars (clist);
3307 gtk_clist_foreach (GtkContainer * container,
3308 GtkCallback callback,
3309 gpointer callback_data)
3314 g_return_if_fail (container != NULL);
3315 g_return_if_fail (GTK_IS_CLIST (container));
3316 g_return_if_fail (callback != NULL);
3318 clist = GTK_CLIST (container);
3320 /* callback for the column buttons */
3321 for (i = 0; i < clist->columns; i++)
3322 if (clist->column[i].button)
3323 (*callback) (clist->column[i].button, callback_data);
3325 /* callbacks for the scrollbars */
3326 if (clist->vscrollbar)
3327 (*callback) (clist->vscrollbar, callback_data);
3328 if (clist->hscrollbar)
3329 (*callback) (clist->hscrollbar, callback_data);
3338 draw_row (GtkCList * clist,
3339 GdkRectangle * area,
3341 GtkCListRow * clist_row)
3344 GdkGC *fg_gc, *bg_gc;
3345 GdkRectangle row_rectangle, cell_rectangle, clip_rectangle, intersect_rectangle,
3347 gint i, offset = 0, width, height, pixmap_width = 0;
3348 gint xsrc, ysrc, xdest, ydest;
3350 g_return_if_fail (clist != NULL);
3352 /* bail now if we arn't drawable yet */
3353 if (!GTK_WIDGET_DRAWABLE (clist))
3356 if (row < 0 || row >= clist->rows)
3359 widget = GTK_WIDGET (clist);
3361 /* if the function is passed the pointer to the row instead of null,
3362 * it avoids this expensive lookup */
3364 clist_row = (g_list_nth (clist->row_list, row))->data;
3366 /* rectangle of the entire row */
3367 row_rectangle.x = 0;
3368 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
3369 row_rectangle.width = clist->clist_window_width;
3370 row_rectangle.height = clist->row_height;
3372 /* rectangle of the cell spacing above the row */
3373 cell_rectangle.x = 0;
3374 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
3375 cell_rectangle.width = row_rectangle.width;
3376 cell_rectangle.height = CELL_SPACING;
3378 /* rectangle used to clip drawing operations, it's y and height
3379 * positions only need to be set once, so we set them once here.
3380 * the x and width are set withing the drawing loop below once per
3382 clip_rectangle.y = row_rectangle.y;
3383 clip_rectangle.height = row_rectangle.height;
3385 /* select GC for background rectangle */
3386 if (clist_row->state == GTK_STATE_SELECTED)
3388 fg_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
3389 bg_gc = widget->style->bg_gc[GTK_STATE_SELECTED];
3393 if (clist_row->fg_set)
3395 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
3396 fg_gc = clist->fg_gc;
3399 fg_gc = widget->style->fg_gc[GTK_STATE_NORMAL];
3401 if (clist_row->bg_set)
3403 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
3404 bg_gc = clist->bg_gc;
3407 bg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
3410 /* draw the cell borders and background */
3413 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
3414 gdk_draw_rectangle (clist->clist_window,
3415 widget->style->base_gc[GTK_STATE_NORMAL],
3417 intersect_rectangle.x,
3418 intersect_rectangle.y,
3419 intersect_rectangle.width,
3420 intersect_rectangle.height);
3422 /* the last row has to clear it's bottom cell spacing too */
3423 if (clist_row == clist->row_list_end->data)
3425 cell_rectangle.y += clist->row_height + CELL_SPACING;
3427 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
3428 gdk_draw_rectangle (clist->clist_window,
3429 widget->style->base_gc[GTK_STATE_NORMAL],
3431 intersect_rectangle.x,
3432 intersect_rectangle.y,
3433 intersect_rectangle.width,
3434 intersect_rectangle.height);
3437 if (!gdk_rectangle_intersect (area, &row_rectangle, &intersect_rectangle))
3440 if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
3441 gdk_draw_rectangle (clist->clist_window,
3444 intersect_rectangle.x,
3445 intersect_rectangle.y,
3446 intersect_rectangle.width,
3447 intersect_rectangle.height);
3449 gdk_window_clear_area (clist->clist_window,
3450 intersect_rectangle.x,
3451 intersect_rectangle.y,
3452 intersect_rectangle.width,
3453 intersect_rectangle.height);
3457 gdk_draw_rectangle (clist->clist_window,
3458 widget->style->base_gc[GTK_STATE_NORMAL],
3462 cell_rectangle.width,
3463 cell_rectangle.height);
3465 /* the last row has to clear it's bottom cell spacing too */
3466 if (clist_row == clist->row_list_end->data)
3468 cell_rectangle.y += clist->row_height + CELL_SPACING;
3470 gdk_draw_rectangle (clist->clist_window,
3471 widget->style->base_gc[GTK_STATE_NORMAL],
3475 cell_rectangle.width,
3476 cell_rectangle.height);
3479 if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
3480 gdk_draw_rectangle (clist->clist_window,
3485 row_rectangle.width,
3486 row_rectangle.height);
3488 gdk_window_clear_area (clist->clist_window,
3491 row_rectangle.width,
3492 row_rectangle.height);
3495 /* iterate and draw all the columns (row cells) and draw their contents */
3496 for (i = 0; i < clist->columns; i++)
3498 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
3499 clip_rectangle.width = clist->column[i].area.width;
3501 /* calculate clipping region clipping region */
3504 rect = &clip_rectangle;
3508 if (!gdk_rectangle_intersect (area, &clip_rectangle,
3509 &intersect_rectangle))
3511 rect = &intersect_rectangle;
3514 /* calculate real width for column justification */
3515 switch (clist_row->cell[i].type)
3517 case GTK_CELL_EMPTY:
3522 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
3523 GTK_CELL_TEXT (clist_row->cell[i])->text);
3526 case GTK_CELL_PIXMAP:
3527 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &width, &height);
3528 pixmap_width = width;
3531 case GTK_CELL_PIXTEXT:
3532 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap, &width, &height);
3533 pixmap_width = width;
3534 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
3535 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
3536 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
3539 case GTK_CELL_WIDGET:
3549 switch (clist->column[i].justification)
3551 case GTK_JUSTIFY_LEFT:
3552 offset = clip_rectangle.x;
3555 case GTK_JUSTIFY_RIGHT:
3556 offset = (clip_rectangle.x + clip_rectangle.width) - width;
3559 case GTK_JUSTIFY_CENTER:
3560 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
3563 case GTK_JUSTIFY_FILL:
3564 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
3572 /* Draw Text or Pixmap */
3573 switch (clist_row->cell[i].type)
3575 case GTK_CELL_EMPTY:
3580 gdk_gc_set_clip_rectangle (fg_gc, rect);
3582 gdk_draw_string (clist->clist_window,
3583 widget->style->font,
3585 offset + clist_row->cell[i].horizontal,
3586 row_rectangle.y + clist->row_center_offset +
3587 clist_row->cell[i].vertical,
3588 GTK_CELL_TEXT (clist_row->cell[i])->text);
3590 gdk_gc_set_clip_rectangle (fg_gc, NULL);
3593 case GTK_CELL_PIXMAP:
3596 xdest = offset + clist_row->cell[i].horizontal;
3597 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
3598 clist_row->cell[i].vertical;
3600 if (xdest < clip_rectangle.x)
3602 xsrc = clip_rectangle.x - xdest;
3603 pixmap_width -= xsrc;
3604 xdest = clip_rectangle.x;
3607 if (xdest + pixmap_width > clip_rectangle.x + clip_rectangle.width)
3608 pixmap_width = (clip_rectangle.x + clip_rectangle.width) - xdest;
3610 if (ydest < clip_rectangle.y)
3612 ysrc = clip_rectangle.y - ydest;
3614 ydest = clip_rectangle.y;
3617 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
3618 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
3620 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
3622 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXMAP (clist_row->cell[i])->mask);
3623 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
3625 gdk_draw_pixmap (clist->clist_window,
3627 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
3630 pixmap_width, height);
3632 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
3634 gdk_gc_set_clip_origin (fg_gc, 0, 0);
3635 gdk_gc_set_clip_mask (fg_gc, NULL);
3639 case GTK_CELL_PIXTEXT:
3640 /* draw the pixmap */
3643 xdest = offset + clist_row->cell[i].horizontal;
3644 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
3645 clist_row->cell[i].vertical;
3647 if (xdest < clip_rectangle.x)
3649 xsrc = clip_rectangle.x - xdest;
3650 pixmap_width -= xsrc;
3651 xdest = clip_rectangle.x;
3654 if (xdest + pixmap_width > clip_rectangle.x + clip_rectangle.width)
3655 pixmap_width = (clip_rectangle.x + clip_rectangle.width) - xdest;
3657 if (ydest < clip_rectangle.y)
3659 ysrc = clip_rectangle.y - ydest;
3661 ydest = clip_rectangle.y;
3664 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
3665 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
3667 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask)
3669 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
3670 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
3673 gdk_draw_pixmap (clist->clist_window,
3675 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
3679 pixmap_width, height);
3681 gdk_gc_set_clip_origin (fg_gc, 0, 0);
3683 offset += pixmap_width + GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
3685 /* draw the string */
3686 gdk_gc_set_clip_rectangle (fg_gc, rect);
3688 gdk_draw_string (clist->clist_window,
3689 widget->style->font,
3691 offset + clist_row->cell[i].horizontal,
3692 row_rectangle.y + clist->row_center_offset +
3693 clist_row->cell[i].vertical,
3694 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
3696 gdk_gc_set_clip_rectangle (fg_gc, NULL);
3699 case GTK_CELL_WIDGET:
3709 if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget))
3713 if (gdk_rectangle_intersect (area, &row_rectangle,
3714 &intersect_rectangle))
3716 gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
3717 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
3718 row_rectangle.x, row_rectangle.y,
3719 row_rectangle.width - 1,
3720 row_rectangle.height - 1);
3721 gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
3725 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
3726 row_rectangle.x, row_rectangle.y,
3727 row_rectangle.width - 1, row_rectangle.height - 1);
3732 draw_rows (GtkCList * clist,
3733 GdkRectangle * area)
3736 GtkCListRow *clist_row;
3737 int i, first_row, last_row;
3739 g_return_if_fail (clist != NULL);
3740 g_return_if_fail (GTK_IS_CLIST (clist));
3742 if (clist->row_height == 0 ||
3743 !GTK_WIDGET_DRAWABLE (clist))
3748 first_row = ROW_FROM_YPIXEL (clist, area->y);
3749 last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
3753 first_row = ROW_FROM_YPIXEL (clist, 0);
3754 last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
3757 /* this is a small special case which exposes the bottom cell line
3758 * on the last row -- it might go away if I change the wall the cell spacings
3760 if (clist->rows == first_row)
3763 list = g_list_nth (clist->row_list, first_row);
3767 clist_row = list->data;
3773 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, area, i, clist_row);
3778 gdk_window_clear_area (clist->clist_window, 0, ROW_TOP_YPIXEL (clist, i), -1, -1);
3783 * size_allocate_title_buttons
3784 * size_allocate_columns
3787 size_allocate_title_buttons (GtkCList * clist)
3789 gint i, last_button = 0;
3790 GtkAllocation button_allocation;
3792 if (!GTK_WIDGET_REALIZED (clist))
3795 button_allocation.x = clist->hoffset;
3796 button_allocation.y = 0;
3797 button_allocation.width = 0;
3798 button_allocation.height = clist->column_title_area.height;
3800 for (i = 0; i < clist->columns; i++)
3802 button_allocation.width += clist->column[i].area.width;
3804 if (i == clist->columns - 1)
3805 button_allocation.width += 2 * (CELL_SPACING + COLUMN_INSET);
3807 button_allocation.width += CELL_SPACING + (2 * COLUMN_INSET);
3809 if (i == (clist->columns - 1) || clist->column[i + 1].button)
3811 gtk_widget_size_allocate (clist->column[last_button].button, &button_allocation);
3812 button_allocation.x += button_allocation.width;
3813 button_allocation.width = 0;
3815 gdk_window_show (clist->column[last_button].window);
3816 gdk_window_move_resize (clist->column[last_button].window,
3817 button_allocation.x - (DRAG_WIDTH / 2),
3818 0, DRAG_WIDTH, clist->column_title_area.height);
3820 last_button = i + 1;
3824 gdk_window_hide (clist->column[i].window);
3830 size_allocate_columns (GtkCList * clist)
3832 gint i, xoffset = 0;
3834 for (i = 0; i < clist->columns; i++)
3836 clist->column[i].area.x = xoffset + CELL_SPACING + COLUMN_INSET;
3838 if (i == clist->columns - 1)
3842 if (clist->column[i].width_set)
3844 width = clist->column[i].width;
3848 if (clist->column[i].title)
3849 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
3850 clist->column[i].title);
3855 clist->column[i].area.width = MAX (width,
3856 clist->clist_window_width -
3857 xoffset - (2 * (CELL_SPACING + COLUMN_INSET)));
3862 clist->column[i].area.width = clist->column[i].width;
3865 xoffset += clist->column[i].area.width + CELL_SPACING + (2 * COLUMN_INSET);
3874 * get_selection_info
3877 toggle_row (GtkCList * clist,
3882 GtkCListRow *clist_row;
3884 switch (clist->selection_mode)
3886 case GTK_SELECTION_EXTENDED:
3887 case GTK_SELECTION_MULTIPLE:
3888 case GTK_SELECTION_SINGLE:
3890 clist_row = g_list_nth (clist->row_list, row)->data;
3891 if (clist_row->state == GTK_STATE_SELECTED)
3893 unselect_row (clist, row, column, event);
3897 case GTK_SELECTION_BROWSE:
3898 select_row (clist, row, column, event);
3904 select_row (GtkCList * clist,
3909 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3910 row, column, event);
3914 unselect_row (GtkCList * clist,
3919 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3920 row, column, event);
3924 real_select_row (GtkCList * clist,
3929 GtkCListRow *clist_row;
3932 gboolean row_selected;
3934 g_return_if_fail (clist != NULL);
3935 g_return_if_fail (GTK_IS_CLIST (clist));
3937 if (row < 0 || row > (clist->rows - 1))
3940 switch (clist->selection_mode)
3942 case GTK_SELECTION_SINGLE:
3943 case GTK_SELECTION_BROWSE:
3945 row_selected = FALSE;
3946 list = clist->selection;
3950 sel_row = GPOINTER_TO_INT (list->data);
3954 row_selected = TRUE;
3956 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3957 sel_row, column, event);
3967 clist_row = (g_list_nth (clist->row_list, row))->data;
3969 if (clist_row->state != GTK_STATE_NORMAL)
3972 clist_row->state = GTK_STATE_SELECTED;
3973 if (!clist->selection)
3975 clist->selection = g_list_append (clist->selection,
3976 GINT_TO_POINTER (row));
3977 clist->selection_end = clist->selection;
3980 clist->selection_end =
3981 g_list_append (clist->selection_end, GINT_TO_POINTER (row))->next;
3983 if (!GTK_CLIST_FROZEN (clist)
3984 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3985 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
3989 real_unselect_row (GtkCList * clist,
3994 GtkCListRow *clist_row;
3996 g_return_if_fail (clist != NULL);
3997 g_return_if_fail (GTK_IS_CLIST (clist));
3999 if (row < 0 || row > (clist->rows - 1))
4002 clist_row = (g_list_nth (clist->row_list, row))->data;
4004 if (clist_row->state == GTK_STATE_SELECTED)
4006 clist_row->state = GTK_STATE_NORMAL;
4008 if (clist->selection_end &&
4009 clist->selection_end->data == GINT_TO_POINTER (row))
4010 clist->selection_end = clist->selection_end->prev;
4012 clist->selection = g_list_remove (clist->selection,
4013 GINT_TO_POINTER (row));
4015 if (!GTK_CLIST_FROZEN (clist)
4016 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
4017 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
4022 get_selection_info (GtkCList * clist,
4030 g_return_val_if_fail (clist != NULL, 0);
4031 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
4033 /* bounds checking, return false if the user clicked
4034 * on a blank area */
4035 trow = ROW_FROM_YPIXEL (clist, y);
4036 if (trow >= clist->rows)
4042 tcol = COLUMN_FROM_XPIXEL (clist, x);
4043 if (tcol >= clist->columns)
4053 gtk_clist_get_selection_info (GtkCList *clist,
4059 g_return_val_if_fail (clist != NULL, 0);
4060 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
4061 return get_selection_info (clist, x, y, row, column);
4071 draw_xor_line (GtkCList * clist)
4075 g_return_if_fail (clist != NULL);
4077 widget = GTK_WIDGET (clist);
4079 gdk_draw_line (widget->window, clist->xor_gc,
4081 widget->style->klass->ythickness,
4083 clist->column_title_area.height + clist->clist_window_height + 1);
4086 /* this function returns the new width of the column being resized given
4087 * the column and x position of the cursor; the x cursor position is passed
4088 * in as a pointer and automagicly corrected if it's beyond min/max limits */
4090 new_column_width (GtkCList * clist,
4099 /* first translate the x position from widget->window
4100 * to clist->clist_window */
4101 cx -= GTK_WIDGET (clist)->style->klass->xthickness;
4103 /* rx is x from the list beginning */
4104 rx = cx - clist->hoffset;
4106 /* you can't shrink a column to less than its minimum width */
4107 if (cx < (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH))
4109 *x = cx = COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH +
4110 GTK_WIDGET (clist)->style->klass->xthickness;
4111 cx -= GTK_WIDGET (clist)->style->klass->xthickness;
4112 rx = cx - clist->hoffset;
4115 if (cx > clist->clist_window_width)
4120 /* calculate new column width making sure it doesn't end up
4121 * less than the minimum width */
4122 width = (rx - COLUMN_LEFT (clist, column)) - COLUMN_INSET -
4123 ((clist->columns == (column - 1)) ? CELL_SPACING : 0);
4124 if (width < COLUMN_MIN_WIDTH)
4125 width = COLUMN_MIN_WIDTH;
4130 /* this will do more later */
4132 resize_column (GtkCList * clist,
4136 gtk_clist_set_column_width (clist, column, width);
4141 column_button_create (GtkCList * clist,
4146 button = clist->column[column].button = gtk_button_new ();
4147 gtk_widget_set_parent (button, GTK_WIDGET (clist));
4148 if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
4149 gtk_widget_set_parent_window (clist->column[column].button, clist->title_window);
4151 gtk_signal_connect (GTK_OBJECT (button), "clicked",
4152 (GtkSignalFunc) column_button_clicked,
4155 gtk_widget_show (button);
4159 column_button_clicked (GtkWidget * widget,
4165 g_return_if_fail (widget != NULL);
4166 g_return_if_fail (GTK_IS_CLIST (data));
4168 clist = GTK_CLIST (data);
4170 /* find the column who's button was pressed */
4171 for (i = 0; i < clist->columns; i++)
4172 if (clist->column[i].button == widget)
4175 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
4184 * vadjustment_changed
4185 * hadjustment_changed
4186 * vadjustment_value_changed
4187 * hadjustment_value_changed
4190 create_scrollbars (GtkCList * clist)
4192 GtkAdjustment *adjustment;
4194 clist->vscrollbar = gtk_vscrollbar_new (NULL);
4196 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
4198 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
4199 (GtkSignalFunc) vadjustment_changed,
4202 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
4203 (GtkSignalFunc) vadjustment_value_changed,
4206 gtk_widget_set_parent (clist->vscrollbar, GTK_WIDGET (clist));
4207 gtk_widget_show (clist->vscrollbar);
4209 clist->hscrollbar = gtk_hscrollbar_new (NULL);
4211 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
4213 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
4214 (GtkSignalFunc) hadjustment_changed,
4217 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
4218 (GtkSignalFunc) hadjustment_value_changed,
4221 gtk_widget_set_parent (clist->hscrollbar, GTK_WIDGET (clist));
4222 gtk_widget_show (clist->hscrollbar);
4226 adjust_scrollbars (GtkCList * clist)
4228 GTK_RANGE (clist->vscrollbar)->adjustment->page_size = clist->clist_window_height;
4229 GTK_RANGE (clist->vscrollbar)->adjustment->page_increment = clist->clist_window_height / 2;
4230 GTK_RANGE (clist->vscrollbar)->adjustment->step_increment = 10;
4231 GTK_RANGE (clist->vscrollbar)->adjustment->lower = 0;
4232 GTK_RANGE (clist->vscrollbar)->adjustment->upper = LIST_HEIGHT (clist);
4234 if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
4236 GTK_RANGE (clist->vscrollbar)->adjustment->value = MAX (0, LIST_HEIGHT (clist) -
4237 clist->clist_window_height);
4238 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
4242 GTK_RANGE (clist->hscrollbar)->adjustment->page_size = clist->clist_window_width;
4243 GTK_RANGE (clist->hscrollbar)->adjustment->page_increment = clist->clist_window_width / 2;
4244 GTK_RANGE (clist->hscrollbar)->adjustment->step_increment = 10;
4245 GTK_RANGE (clist->hscrollbar)->adjustment->lower = 0;
4246 GTK_RANGE (clist->hscrollbar)->adjustment->upper = LIST_WIDTH (clist);
4248 if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
4250 GTK_RANGE (clist->hscrollbar)->adjustment->value = MAX (0, LIST_WIDTH (clist) -
4251 clist->clist_window_width);
4252 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
4256 if (LIST_HEIGHT (clist) <= clist->clist_window_height &&
4257 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
4259 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
4261 gtk_widget_hide (clist->vscrollbar);
4262 gtk_widget_queue_resize (GTK_WIDGET (clist));
4267 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
4269 gtk_widget_show (clist->vscrollbar);
4270 gtk_widget_queue_resize (GTK_WIDGET (clist));
4274 if (LIST_WIDTH (clist) <= clist->clist_window_width &&
4275 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
4277 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
4279 gtk_widget_hide (clist->hscrollbar);
4280 gtk_widget_queue_resize (GTK_WIDGET (clist));
4285 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
4287 gtk_widget_show (clist->hscrollbar);
4288 gtk_widget_queue_resize (GTK_WIDGET (clist));
4292 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
4293 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment), "changed");
4297 vadjustment_changed (GtkAdjustment * adjustment,
4302 g_return_if_fail (adjustment != NULL);
4303 g_return_if_fail (data != NULL);
4305 clist = GTK_CLIST (data);
4309 hadjustment_changed (GtkAdjustment * adjustment,
4314 g_return_if_fail (adjustment != NULL);
4315 g_return_if_fail (data != NULL);
4317 clist = GTK_CLIST (data);
4321 check_exposures (GtkCList *clist)
4325 if (!GTK_WIDGET_REALIZED (clist))
4328 /* Make sure graphics expose events are processed before scrolling
4330 while ((event = gdk_event_get_graphics_expose (clist->clist_window)) != NULL)
4332 gtk_widget_event (GTK_WIDGET (clist), event);
4333 if (event->expose.count == 0)
4335 gdk_event_free (event);
4338 gdk_event_free (event);
4343 vadjustment_value_changed (GtkAdjustment * adjustment,
4350 g_return_if_fail (adjustment != NULL);
4351 g_return_if_fail (data != NULL);
4352 g_return_if_fail (GTK_IS_CLIST (data));
4354 clist = GTK_CLIST (data);
4356 if (!GTK_WIDGET_DRAWABLE (clist))
4359 value = adjustment->value;
4361 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar)))
4363 if (value > -clist->voffset)
4366 diff = value + clist->voffset;
4368 /* we have to re-draw the whole screen here... */
4369 if (diff >= clist->clist_window_height)
4371 clist->voffset = -value;
4372 draw_rows (clist, NULL);
4376 if ((diff != 0) && (diff != clist->clist_window_height))
4377 gdk_window_copy_area (clist->clist_window,
4380 clist->clist_window,
4383 clist->clist_window_width,
4384 clist->clist_window_height - diff);
4387 area.y = clist->clist_window_height - diff;
4388 area.width = clist->clist_window_width;
4394 diff = -clist->voffset - value;
4396 /* we have to re-draw the whole screen here... */
4397 if (diff >= clist->clist_window_height)
4399 clist->voffset = -value;
4400 draw_rows (clist, NULL);
4404 if ((diff != 0) && (diff != clist->clist_window_height))
4405 gdk_window_copy_area (clist->clist_window,
4408 clist->clist_window,
4411 clist->clist_window_width,
4412 clist->clist_window_height - diff);
4416 area.width = clist->clist_window_width;
4421 clist->voffset = -value;
4422 if ((diff != 0) && (diff != clist->clist_window_height))
4423 check_exposures (clist);
4426 draw_rows (clist, &area);
4430 hadjustment_value_changed (GtkAdjustment * adjustment,
4440 g_return_if_fail (adjustment != NULL);
4441 g_return_if_fail (data != NULL);
4442 g_return_if_fail (GTK_IS_CLIST (data));
4444 clist = GTK_CLIST (data);
4446 if (!GTK_WIDGET_DRAWABLE (clist) ||
4447 adjustment != gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar)))
4450 value = adjustment->value;
4452 /* move the column buttons and resize windows */
4453 for (i = 0; i < clist->columns; i++)
4455 if (clist->column[i].button)
4457 clist->column[i].button->allocation.x -= value + clist->hoffset;
4459 if (clist->column[i].button->window)
4461 gdk_window_move (clist->column[i].button->window,
4462 clist->column[i].button->allocation.x,
4463 clist->column[i].button->allocation.y);
4465 if (clist->column[i].window)
4466 gdk_window_move (clist->column[i].window,
4467 clist->column[i].button->allocation.x +
4468 clist->column[i].button->allocation.width -
4469 (DRAG_WIDTH / 2), 0);
4474 if (value > -clist->hoffset)
4477 diff = value + clist->hoffset;
4479 clist->hoffset = -value;
4481 /* we have to re-draw the whole screen here... */
4482 if (diff >= clist->clist_window_width)
4484 draw_rows (clist, NULL);
4488 if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
4489 GTK_CLIST_ADD_MODE (clist))
4491 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
4493 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
4494 clist->clist_window_width - 1,
4495 clist->row_height - 1);
4497 gdk_window_copy_area (clist->clist_window,
4500 clist->clist_window,
4503 clist->clist_window_width - diff,
4504 clist->clist_window_height);
4506 area.x = clist->clist_window_width - diff;
4511 if (!(diff = -clist->hoffset - value))
4514 clist->hoffset = -value;
4516 /* we have to re-draw the whole screen here... */
4517 if (diff >= clist->clist_window_width)
4519 draw_rows (clist, NULL);
4523 if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
4524 GTK_CLIST_ADD_MODE (clist))
4526 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
4528 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
4529 clist->clist_window_width - 1,
4530 clist->row_height - 1);
4533 gdk_window_copy_area (clist->clist_window,
4536 clist->clist_window,
4539 clist->clist_window_width - diff,
4540 clist->clist_window_height);
4547 area.height = clist->clist_window_height;
4549 check_exposures (clist);
4551 if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist))
4553 if (GTK_CLIST_ADD_MODE (clist))
4557 focus_row = clist->focus_row;
4558 clist->focus_row = -1;
4559 draw_rows (clist, &area);
4560 clist->focus_row = focus_row;
4562 gdk_draw_rectangle (clist->clist_window, clist->xor_gc,
4563 FALSE, 0, y, clist->clist_window_width - 1,
4564 clist->row_height - 1);
4574 x0 = clist->clist_window_width - 1;
4583 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
4584 gdk_draw_line (clist->clist_window, clist->xor_gc,
4585 x0, y + 1, x0, y + clist->row_height - 2);
4586 gdk_draw_line (clist->clist_window, clist->xor_gc,
4587 x1, y + 1, x1, y + clist->row_height - 2);
4591 draw_rows (clist, &area);
4595 * Memory Allocation/Distruction Routines for GtkCList stuctures
4607 static GtkCListColumn *
4608 columns_new (GtkCList * clist)
4611 GtkCListColumn *column;
4613 column = g_new (GtkCListColumn, clist->columns);
4615 for (i = 0; i < clist->columns; i++)
4617 column[i].area.x = 0;
4618 column[i].area.y = 0;
4619 column[i].area.width = 0;
4620 column[i].area.height = 0;
4621 column[i].title = NULL;
4622 column[i].button = NULL;
4623 column[i].window = NULL;
4624 column[i].width = 0;
4625 column[i].width_set = FALSE;
4626 column[i].justification = GTK_JUSTIFY_LEFT;
4633 column_title_new (GtkCList * clist,
4637 if (clist->column[column].title)
4638 g_free (clist->column[column].title);
4640 clist->column[column].title = g_strdup (title);
4644 columns_delete (GtkCList * clist)
4648 for (i = 0; i < clist->columns; i++)
4649 if (clist->column[i].title)
4650 g_free (clist->column[i].title);
4652 g_free (clist->column);
4655 static GtkCListRow *
4656 row_new (GtkCList * clist)
4659 GtkCListRow *clist_row;
4661 clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
4662 clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
4664 for (i = 0; i < clist->columns; i++)
4666 clist_row->cell[i].type = GTK_CELL_EMPTY;
4667 clist_row->cell[i].vertical = 0;
4668 clist_row->cell[i].horizontal = 0;
4671 clist_row->fg_set = FALSE;
4672 clist_row->bg_set = FALSE;
4673 clist_row->state = GTK_STATE_NORMAL;
4674 clist_row->data = NULL;
4675 clist_row->destroy = NULL;
4681 row_delete (GtkCList * clist,
4682 GtkCListRow * clist_row)
4686 for (i = 0; i < clist->columns; i++)
4687 cell_empty (clist, clist_row, i);
4689 if (clist_row->destroy)
4690 clist_row->destroy (clist_row->data);
4692 g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
4693 g_mem_chunk_free (clist->row_mem_chunk, clist_row);
4697 cell_empty (GtkCList * clist,
4698 GtkCListRow * clist_row,
4701 switch (clist_row->cell[column].type)
4703 case GTK_CELL_EMPTY:
4707 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
4710 case GTK_CELL_PIXMAP:
4711 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
4712 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
4713 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
4716 case GTK_CELL_PIXTEXT:
4717 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
4718 gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
4719 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
4720 gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
4723 case GTK_CELL_WIDGET:
4731 clist_row->cell[column].type = GTK_CELL_EMPTY;
4735 cell_set_text (GtkCList * clist,
4736 GtkCListRow * clist_row,
4740 cell_empty (clist, clist_row, column);
4744 clist_row->cell[column].type = GTK_CELL_TEXT;
4745 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
4750 cell_set_pixmap (GtkCList * clist,
4751 GtkCListRow * clist_row,
4756 cell_empty (clist, clist_row, column);
4760 clist_row->cell[column].type = GTK_CELL_PIXMAP;
4761 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
4762 /* We set the mask even if it is NULL */
4763 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
4768 cell_set_pixtext (GtkCList * clist,
4769 GtkCListRow * clist_row,
4776 cell_empty (clist, clist_row, column);
4780 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
4781 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
4782 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
4783 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
4784 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
4788 /* Fill in data after widget has correct style */
4791 add_style_data (GtkCList * clist)
4795 widget = GTK_WIDGET(clist);
4797 /* text properties */
4798 if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
4800 clist->row_height = widget->style->font->ascent + widget->style->font->descent + 1;
4801 clist->row_center_offset = widget->style->font->ascent + 1.5;
4806 text_height = clist->row_height - (GTK_WIDGET (clist)->style->font->ascent +
4807 GTK_WIDGET (clist) ->style->font->descent + 1);
4808 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
4815 /* focus functions */
4818 gtk_clist_draw_focus (GtkWidget *widget)
4822 g_return_if_fail (widget != NULL);
4823 g_return_if_fail (GTK_IS_CLIST (widget));
4825 if (!GTK_WIDGET_DRAWABLE (widget))
4828 clist = GTK_CLIST (widget);
4829 if (clist->focus_row >= 0)
4830 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
4831 0, ROW_TOP_YPIXEL(clist, clist->focus_row),
4832 clist->clist_window_width - 1,
4833 clist->row_height - 1);
4837 gtk_clist_set_focus_child (GtkContainer *container,
4840 g_return_if_fail (container != NULL);
4841 g_return_if_fail (GTK_IS_CLIST (container));
4845 g_return_if_fail (GTK_IS_WIDGET (child));
4846 GTK_CLIST_SET_FLAG (GTK_CLIST (container), CLIST_CHILD_HAS_FOCUS);
4849 parent_class->set_focus_child (container, child);
4853 gtk_clist_focus_in (GtkWidget *widget,
4854 GdkEventFocus *event)
4858 g_return_val_if_fail (widget != NULL, FALSE);
4859 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
4860 g_return_val_if_fail (event != NULL, FALSE);
4862 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4863 GTK_CLIST_UNSET_FLAG (widget, CLIST_CHILD_HAS_FOCUS);
4865 clist = GTK_CLIST (widget);
4867 if (clist->selection_mode == GTK_SELECTION_BROWSE &&
4868 clist->selection == NULL && clist->focus_row > -1)
4869 select_row (clist, clist->focus_row, -1, (GdkEvent *) event);
4871 gtk_widget_draw_focus (widget);
4877 gtk_clist_focus_out (GtkWidget *widget,
4878 GdkEventFocus *event)
4882 g_return_val_if_fail (widget != NULL, FALSE);
4883 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
4884 g_return_val_if_fail (event != NULL, FALSE);
4886 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4887 gtk_widget_draw_focus (widget);
4889 clist = GTK_CLIST (widget);
4891 if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
4892 GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, (GdkEvent *) event);
4898 toggle_add_mode (GtkCList *clist)
4900 g_return_if_fail (clist != 0);
4901 g_return_if_fail (GTK_IS_CLIST (clist));
4903 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
4904 clist->selection_mode != GTK_SELECTION_EXTENDED)
4907 gtk_clist_draw_focus (GTK_WIDGET (clist));
4908 if (!GTK_CLIST_ADD_MODE (clist))
4910 GTK_CLIST_SET_FLAG (clist, CLIST_ADD_MODE);
4911 gdk_gc_set_line_attributes (clist->xor_gc, 1,
4912 GDK_LINE_ON_OFF_DASH, 0, 0);
4913 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
4917 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
4918 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
4919 clist->anchor_state = GTK_STATE_SELECTED;
4921 gtk_clist_draw_focus (GTK_WIDGET (clist));
4925 toggle_focus_row (GtkCList *clist)
4927 g_return_if_fail (clist != 0);
4928 g_return_if_fail (GTK_IS_CLIST (clist));
4930 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
4931 clist->focus_row < 0 || clist->focus_row >= clist->rows)
4934 switch (clist->selection_mode)
4936 case GTK_SELECTION_SINGLE:
4937 case GTK_SELECTION_MULTIPLE:
4939 toggle_row (clist, clist->focus_row, 0, NULL);
4942 case GTK_SELECTION_EXTENDED:
4943 g_list_free (clist->undo_selection);
4944 g_list_free (clist->undo_unselection);
4945 clist->undo_selection = NULL;
4946 clist->undo_unselection = NULL;
4948 clist->anchor = clist->focus_row;
4949 clist->drag_pos = clist->focus_row;
4950 clist->undo_anchor = clist->focus_row;
4952 if (GTK_CLIST_ADD_MODE (clist))
4953 fake_toggle_row (clist, clist->focus_row);
4955 GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist,clist->focus_row);
4957 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
4966 move_focus_row (GtkCList *clist,
4967 GtkScrollType scroll_type,
4972 g_return_if_fail (clist != 0);
4973 g_return_if_fail (GTK_IS_CLIST (clist));
4975 widget = GTK_WIDGET (clist);
4977 switch (scroll_type)
4979 case GTK_SCROLL_STEP_BACKWARD:
4980 if (clist->focus_row <= 0)
4982 gtk_clist_draw_focus (widget);
4984 gtk_clist_draw_focus (widget);
4986 case GTK_SCROLL_STEP_FORWARD:
4987 if (clist->focus_row >= clist->rows - 1)
4989 gtk_clist_draw_focus (widget);
4991 gtk_clist_draw_focus (widget);
4993 case GTK_SCROLL_PAGE_BACKWARD:
4994 if (clist->focus_row <= 0)
4996 gtk_clist_draw_focus (widget);
4997 clist->focus_row = MAX (0, clist->focus_row -
4998 (2 * clist->clist_window_height -
4999 clist->row_height - CELL_SPACING) /
5000 (2 * (clist->row_height + CELL_SPACING)));
5001 gtk_clist_draw_focus (widget);
5003 case GTK_SCROLL_PAGE_FORWARD:
5004 if (clist->focus_row >= clist->rows - 1)
5006 gtk_clist_draw_focus (widget);
5007 clist->focus_row = MIN (clist->rows - 1, clist->focus_row +
5008 (2 * clist->clist_window_height -
5009 clist->row_height - CELL_SPACING) /
5010 (2 * (clist->row_height + CELL_SPACING)));
5011 gtk_clist_draw_focus (widget);
5013 case GTK_SCROLL_JUMP:
5014 if (position >= 0 && position <= 1)
5016 gtk_clist_draw_focus (widget);
5017 clist->focus_row = position * (clist->rows - 1);
5018 gtk_clist_draw_focus (widget);
5027 scroll_horizontal (GtkCList *clist,
5028 GtkScrollType scroll_type,
5033 g_return_if_fail (clist != 0);
5034 g_return_if_fail (GTK_IS_CLIST (clist));
5036 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
5039 switch (scroll_type)
5041 case GTK_SCROLL_STEP_BACKWARD:
5042 column = COLUMN_FROM_XPIXEL (clist, 0);
5043 if (COLUMN_LEFT_XPIXEL (clist, column) - CELL_SPACING - COLUMN_INSET >= 0
5047 case GTK_SCROLL_STEP_FORWARD:
5048 column = COLUMN_FROM_XPIXEL (clist, clist->clist_window_width);
5051 if (COLUMN_LEFT_XPIXEL (clist, column) + clist->column[column].area.width
5052 + CELL_SPACING + COLUMN_INSET - 1 <= clist->clist_window_width &&
5053 column < clist->columns - 1)
5056 case GTK_SCROLL_PAGE_BACKWARD:
5057 case GTK_SCROLL_PAGE_FORWARD:
5059 case GTK_SCROLL_JUMP:
5060 if (position >= 0 && position <= 1)
5061 column = position * (clist->columns - 1);
5069 if (COLUMN_LEFT_XPIXEL (clist, column) < CELL_SPACING + COLUMN_INSET)
5070 gtk_clist_moveto (clist, -1, column, 0, 0);
5071 else if (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET - 1
5072 + clist->column[column].area.width > clist->clist_window_width)
5074 if (column == clist->columns - 1)
5075 gtk_clist_moveto (clist, -1, column, 0, 0);
5077 gtk_clist_moveto (clist, -1, column, 0, 1);
5082 scroll_vertical (GtkCList *clist,
5083 GtkScrollType scroll_type,
5088 g_return_if_fail (clist != NULL);
5089 g_return_if_fail (GTK_IS_CLIST (clist));
5091 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
5094 switch (clist->selection_mode)
5096 case GTK_SELECTION_EXTENDED:
5097 if (clist->anchor >= 0)
5100 case GTK_SELECTION_BROWSE:
5102 old_focus_row = clist->focus_row;
5103 move_focus_row (clist, scroll_type, position);
5105 if (old_focus_row != clist->focus_row)
5107 if (clist->selection_mode == GTK_SELECTION_BROWSE)
5108 unselect_row (clist,old_focus_row, -1, NULL);
5109 else if (!GTK_CLIST_ADD_MODE (clist))
5111 gtk_clist_unselect_all (clist);
5112 clist->undo_anchor = old_focus_row;
5116 switch (gtk_clist_row_is_visible (clist, clist->focus_row))
5118 case GTK_VISIBILITY_NONE:
5119 if (old_focus_row != clist->focus_row &&
5120 !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
5121 GTK_CLIST_ADD_MODE (clist)))
5122 select_row (clist, clist->focus_row, -1, NULL);
5123 switch (scroll_type)
5125 case GTK_SCROLL_STEP_BACKWARD:
5126 case GTK_SCROLL_PAGE_BACKWARD:
5127 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5129 case GTK_SCROLL_STEP_FORWARD:
5130 case GTK_SCROLL_PAGE_FORWARD:
5131 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5133 case GTK_SCROLL_JUMP:
5134 gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
5141 case GTK_VISIBILITY_PARTIAL:
5142 switch (scroll_type)
5144 case GTK_SCROLL_STEP_BACKWARD:
5145 case GTK_SCROLL_PAGE_BACKWARD:
5146 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5148 case GTK_SCROLL_STEP_FORWARD:
5149 case GTK_SCROLL_PAGE_FORWARD:
5150 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5152 case GTK_SCROLL_JUMP:
5153 gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
5160 if (old_focus_row != clist->focus_row &&
5161 !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
5162 GTK_CLIST_ADD_MODE (clist)))
5163 select_row (clist, clist->focus_row, -1, NULL);
5169 move_focus_row (clist, scroll_type, position);
5171 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
5172 clist->clist_window_height)
5173 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5174 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
5175 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5181 set_anchor (GtkCList *clist,
5186 g_return_if_fail (clist != NULL);
5187 g_return_if_fail (GTK_IS_CLIST (clist));
5189 if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor >= 0)
5192 g_list_free (clist->undo_selection);
5193 g_list_free (clist->undo_unselection);
5194 clist->undo_selection = NULL;
5195 clist->undo_unselection = NULL;
5198 fake_toggle_row (clist, anchor);
5201 GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist, anchor);
5202 clist->anchor_state = GTK_STATE_SELECTED;
5205 clist->anchor = anchor;
5206 clist->drag_pos = anchor;
5207 clist->undo_anchor = undo_anchor;
5211 resync_selection (GtkCList *clist,
5217 gboolean thaw = FALSE;
5219 GtkCListRow *clist_row;
5221 if (clist->anchor < 0)
5224 if (!GTK_CLIST_FROZEN (clist))
5226 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
5230 i = MIN (clist->anchor, clist->drag_pos);
5231 e = MAX (clist->anchor, clist->drag_pos);
5233 if (clist->undo_selection)
5236 list = clist->selection;
5237 clist->selection = clist->undo_selection;
5238 clist->selection_end = g_list_last (clist->selection);
5239 clist->undo_selection = list;
5240 list = clist->selection;
5243 row = GPOINTER_TO_INT (list->data);
5245 if (row < i || row > e)
5247 clist_row = g_list_nth (clist->row_list, row)->data;
5248 clist_row->state = GTK_STATE_SELECTED;
5249 unselect_row (clist, row, -1, event);
5250 clist->undo_selection = g_list_prepend
5251 (clist->undo_selection, GINT_TO_POINTER (row));
5256 for (list = g_list_nth (clist->row_list, i); i <= e; i++, list = list->next)
5257 if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
5259 if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
5261 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
5262 unselect_row (clist, i, -1, event);
5263 clist->undo_selection = g_list_prepend (clist->undo_selection,
5264 GINT_TO_POINTER (i));
5267 else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
5269 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
5270 clist->undo_unselection = g_list_prepend (clist->undo_unselection,
5271 GINT_TO_POINTER (i));
5274 for (list = clist->undo_unselection; list; list = list->next)
5275 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
5276 GPOINTER_TO_INT (list->data), -1, event);
5279 clist->drag_pos = -1;
5282 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
5286 update_extended_selection (GtkCList *clist,
5296 gint y1 = clist->clist_window_height;
5297 gint y2 = clist->clist_window_height;
5302 if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor == -1)
5307 if (row >= clist->rows)
5308 row = clist->rows - 1;
5310 /* extending downwards */
5311 if (row > clist->drag_pos && clist->anchor <= clist->drag_pos)
5313 s2 = clist->drag_pos + 1;
5316 /* extending upwards */
5317 else if (row < clist->drag_pos && clist->anchor >= clist->drag_pos)
5320 e2 = clist->drag_pos - 1;
5322 else if (row < clist->drag_pos && clist->anchor < clist->drag_pos)
5324 e1 = clist->drag_pos;
5325 /* row and drag_pos on different sides of anchor :
5326 take back the selection between anchor and drag_pos,
5327 select between anchor and row */
5328 if (row < clist->anchor)
5330 s1 = clist->anchor + 1;
5332 e2 = clist->anchor - 1;
5334 /* take back the selection between anchor and drag_pos */
5338 else if (row > clist->drag_pos && clist->anchor > clist->drag_pos)
5340 s1 = clist->drag_pos;
5341 /* row and drag_pos on different sides of anchor :
5342 take back the selection between anchor and drag_pos,
5343 select between anchor and row */
5344 if (row > clist->anchor)
5346 e1 = clist->anchor - 1;
5347 s2 = clist->anchor + 1;
5350 /* take back the selection between anchor and drag_pos */
5355 clist->drag_pos = row;
5358 area.width = clist->clist_window_width;
5360 /* restore the elements between s1 and e1 */
5363 for (i = s1, list = g_list_nth (clist->row_list, i); i <= e1;
5364 i++, list = list->next)
5366 if (GTK_CLIST_CLASS_FW (clist)->selection_find (clist, i, list))
5367 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
5369 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
5372 top = ROW_TOP_YPIXEL (clist, clist->focus_row);
5374 if (top + clist->row_height <= 0)
5377 area.height = ROW_TOP_YPIXEL (clist, e1) + clist->row_height;
5378 draw_rows (clist, &area);
5379 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5381 else if (top >= clist->clist_window_height)
5383 area.y = ROW_TOP_YPIXEL (clist, s1);
5384 area.height = clist->clist_window_height - area.y;
5385 draw_rows (clist, &area);
5386 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5389 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5390 else if (top + clist->row_height > clist->clist_window_height)
5391 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5393 y1 = ROW_TOP_YPIXEL (clist, s1);
5394 h1 = (e1 - s1 + 1) * (clist->row_height + CELL_SPACING);
5397 /* extend the selection between s2 and e2 */
5400 for (i = s2, list = g_list_nth (clist->row_list, i); i <= e2;
5401 i++, list = list->next)
5402 if (GTK_CLIST_ROW (list)->state != clist->anchor_state)
5403 GTK_CLIST_ROW (list)->state = clist->anchor_state;
5405 top = ROW_TOP_YPIXEL (clist, clist->focus_row);
5407 if (top + clist->row_height <= 0)
5410 area.height = ROW_TOP_YPIXEL (clist, e2) + clist->row_height;
5411 draw_rows (clist, &area);
5412 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5414 else if (top >= clist->clist_window_height)
5416 area.y = ROW_TOP_YPIXEL (clist, s2);
5417 area.height = clist->clist_window_height - area.y;
5418 draw_rows (clist, &area);
5419 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5422 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5423 else if (top + clist->row_height > clist->clist_window_height)
5424 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5426 y2 = ROW_TOP_YPIXEL (clist, s2);
5427 h2 = (e2-s2+1) * (clist->row_height + CELL_SPACING);
5430 area.y = MAX (0, MIN (y1, y2));
5431 if (area.y > clist->clist_window_height)
5433 area.height = MIN (clist->clist_window_height, h1 + h2);
5434 if (s1 >= 0 && s2 >= 0)
5435 area.height += (clist->row_height + CELL_SPACING);
5436 draw_rows (clist, &area);
5440 start_selection (GtkCList *clist)
5442 g_return_if_fail (clist != NULL);
5443 g_return_if_fail (GTK_IS_CLIST (clist));
5445 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
5448 set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
5453 end_selection (GtkCList *clist)
5455 g_return_if_fail (clist != NULL);
5456 g_return_if_fail (GTK_IS_CLIST (clist));
5458 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)) ||
5459 clist->anchor == -1)
5462 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5466 extend_selection (GtkCList *clist,
5467 GtkScrollType scroll_type,
5469 gboolean auto_start_selection)
5471 g_return_if_fail (clist != NULL);
5472 g_return_if_fail (GTK_IS_CLIST (clist));
5474 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
5475 clist->selection_mode != GTK_SELECTION_EXTENDED)
5478 if (auto_start_selection)
5479 set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
5481 else if (clist->anchor == -1)
5484 move_focus_row (clist, scroll_type, position);
5486 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
5487 clist->clist_window_height)
5488 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5489 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
5490 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5492 update_extended_selection (clist, clist->focus_row);
5496 abort_column_resize (GtkCList *clist)
5498 g_return_if_fail (clist != NULL);
5499 g_return_if_fail (GTK_IS_CLIST (clist));
5501 if (!GTK_CLIST_IN_DRAG (clist))
5504 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
5505 gtk_grab_remove (GTK_WIDGET (clist));
5506 gdk_pointer_ungrab (gdk_time_get());
5508 if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
5509 draw_xor_line (clist);
5511 if (GTK_CLIST_ADD_MODE (clist))
5513 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0);
5514 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
5519 gtk_clist_key_press (GtkWidget * widget,
5520 GdkEventKey * event)
5523 gboolean handled = FALSE;
5525 g_return_val_if_fail (widget != NULL, FALSE);
5526 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
5527 g_return_val_if_fail (event != NULL, FALSE);
5529 clist = GTK_CLIST (widget);
5532 if (event->keyval == GDK_Escape && GTK_CLIST_IN_DRAG (clist))
5534 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
5535 gtk_grab_remove (widget);
5536 gdk_pointer_ungrab (event->time);
5538 if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
5539 draw_xor_line (clist);
5541 if (GTK_CLIST_ADD_MODE (clist))
5543 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH,
5545 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
5550 if (GTK_WIDGET_CLASS (parent_class)->key_press_event)
5551 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
5556 switch (event->keyval)
5559 case GDK_ISO_Left_Tab:
5560 if (event->state & GDK_SHIFT_MASK)
5561 return gtk_container_focus (GTK_CONTAINER (widget),
5562 GTK_DIR_TAB_BACKWARD);
5564 return gtk_container_focus (GTK_CONTAINER (widget),
5565 GTK_DIR_TAB_FORWARD);
5575 title_focus (GtkCList * clist,
5578 GtkWidget *focus_child;
5579 gboolean return_val = FALSE;
5584 if (!GTK_CLIST_SHOW_TITLES (clist))
5587 focus_child = GTK_CONTAINER (clist)->focus_child;
5591 case GTK_DIR_TAB_BACKWARD:
5593 if (!focus_child || focus_child == clist->hscrollbar ||
5594 focus_child == clist->hscrollbar ||
5595 !GTK_CLIST_CHILD_HAS_FOCUS (clist))
5597 if (dir == GTK_DIR_UP)
5598 i = COLUMN_FROM_XPIXEL (clist, 0);
5600 i = clist->columns - 1;
5601 focus_child = clist->column[i].button;
5602 dir = GTK_DIR_TAB_FORWARD;
5609 if (!focus_child || focus_child == clist->hscrollbar ||
5610 focus_child == clist->hscrollbar)
5612 i = clist->columns - 1;
5613 focus_child = clist->column[i].button;
5617 if (!focus_child || focus_child == clist->hscrollbar ||
5618 focus_child == clist->hscrollbar)
5621 focus_child = clist->column[i].button;
5627 while (i < clist->columns)
5629 if (clist->column[i].button == focus_child)
5631 if (clist->column[i].button &&
5632 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
5633 GTK_IS_CONTAINER (clist->column[i].button) &&
5634 !GTK_WIDGET_HAS_FOCUS (clist->column[i].button))
5635 if (gtk_container_focus
5636 (GTK_CONTAINER (clist->column[i].button), dir))
5641 if (!return_val && dir == GTK_DIR_UP)
5652 while (j >= 0 && j < clist->columns)
5654 if (clist->column[j].button &&
5655 GTK_WIDGET_VISIBLE (clist->column[j].button))
5657 if (GTK_IS_CONTAINER (clist->column[j].button) &&
5659 (GTK_CONTAINER (clist->column[j].button), dir))
5664 else if (GTK_WIDGET_CAN_FOCUS (clist->column[j].button))
5666 gtk_widget_grab_focus (clist->column[j].button);
5676 if (COLUMN_LEFT_XPIXEL (clist, j) < CELL_SPACING + COLUMN_INSET)
5677 gtk_clist_moveto (clist, -1, j, 0, 0);
5678 else if (COLUMN_LEFT_XPIXEL(clist, j) + clist->column[j].area.width >
5679 clist->clist_window_width)
5681 if (j == clist->columns-1)
5682 gtk_clist_moveto (clist, -1, j, 0, 0);
5684 gtk_clist_moveto (clist, -1, j, 0, 1);
5691 gtk_clist_focus (GtkContainer * container,
5692 GtkDirectionType direction)
5695 GtkWidget *focus_child;
5698 g_return_val_if_fail (container != NULL, FALSE);
5699 g_return_val_if_fail (GTK_IS_CLIST (container), FALSE);
5701 if (!GTK_WIDGET_SENSITIVE (container))
5704 clist = GTK_CLIST (container);
5705 focus_child = container->focus_child;
5706 old_row = clist->focus_row;
5712 if (GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
5713 (!focus_child || (focus_child && focus_child != clist->vscrollbar &&
5714 focus_child != clist->hscrollbar)))
5716 if (title_focus (clist, direction))
5718 gtk_container_set_focus_child (container, NULL);
5721 gtk_widget_grab_focus (GTK_WIDGET (container));
5724 case GTK_DIR_TAB_FORWARD:
5725 if (GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
5726 (!focus_child || (focus_child != clist->vscrollbar &&
5727 focus_child != clist->hscrollbar)))
5729 gboolean tf = FALSE;
5731 if (((focus_child && direction == GTK_DIR_DOWN) ||
5732 !(tf = title_focus (clist, GTK_DIR_TAB_FORWARD)))
5735 if (clist->focus_row < 0)
5737 clist->focus_row = 0;
5739 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
5740 clist->selection_mode == GTK_SELECTION_EXTENDED) &&
5742 select_row (clist, clist->focus_row, -1, NULL);
5744 gtk_widget_grab_focus (GTK_WIDGET (container));
5752 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
5754 if ((!GTK_CLIST_CHILD_HAS_FOCUS (clist) || !focus_child ||
5755 (focus_child != clist->vscrollbar &&
5756 focus_child != clist->hscrollbar)) &&
5757 GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
5758 GTK_WIDGET_CAN_FOCUS (clist->vscrollbar))
5760 gtk_widget_grab_focus (clist->vscrollbar);
5764 if ((!GTK_CLIST_CHILD_HAS_FOCUS (clist) || !focus_child ||
5765 focus_child != clist->hscrollbar) &&
5766 GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
5767 GTK_WIDGET_CAN_FOCUS (clist->hscrollbar))
5769 gtk_widget_grab_focus (clist->hscrollbar);
5774 case GTK_DIR_TAB_BACKWARD:
5775 if (!focus_child && GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
5776 GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
5777 GTK_WIDGET_CAN_FOCUS (clist->hscrollbar))
5779 gtk_widget_grab_focus (clist->hscrollbar);
5783 if ((!focus_child || focus_child == clist->hscrollbar) &&
5784 GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
5785 GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
5786 GTK_WIDGET_CAN_FOCUS (clist->vscrollbar))
5788 gtk_widget_grab_focus (clist->vscrollbar);
5792 if ((!focus_child || focus_child == clist->hscrollbar ||
5793 focus_child == clist->vscrollbar) &&
5794 GTK_CLIST_CHILD_HAS_FOCUS (clist) && clist->rows)
5796 if (clist->focus_row < 0)
5798 clist->focus_row = 0;
5799 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
5800 clist->selection_mode == GTK_SELECTION_EXTENDED) &&
5802 select_row (clist, clist->focus_row, -1, NULL);
5804 gtk_widget_grab_focus (GTK_WIDGET (container));
5808 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
5810 if (title_focus (clist, direction))
5819 gtk_container_set_focus_child (container, NULL);
5824 gtk_clist_unselect_all (GtkCList * clist)
5826 GTK_CLIST_CLASS_FW (clist)->unselect_all (clist);
5830 real_unselect_all (GtkCList * clist)
5835 g_return_if_fail (clist != NULL);
5836 g_return_if_fail (GTK_IS_CLIST (clist));
5838 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
5841 switch (clist->selection_mode)
5843 case GTK_SELECTION_BROWSE:
5844 if (clist->focus_row >= 0)
5846 select_row (clist, clist->focus_row, -1, NULL);
5851 case GTK_SELECTION_EXTENDED:
5852 g_list_free (clist->undo_selection);
5853 g_list_free (clist->undo_unselection);
5854 clist->undo_selection = NULL;
5855 clist->undo_unselection = NULL;
5858 clist->drag_pos = -1;
5859 clist->undo_anchor = clist->focus_row;
5866 list = clist->selection;
5870 i = GPOINTER_TO_INT (list->data);
5872 unselect_row (clist, i, -1, NULL);
5877 gtk_clist_select_all (GtkCList * clist)
5879 GTK_CLIST_CLASS_FW (clist)->select_all (clist);
5883 real_select_all (GtkCList * clist)
5888 g_return_if_fail (clist != NULL);
5889 g_return_if_fail (GTK_IS_CLIST (clist));
5891 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
5894 switch (clist->selection_mode)
5896 case GTK_SELECTION_SINGLE:
5897 case GTK_SELECTION_BROWSE:
5900 case GTK_SELECTION_EXTENDED:
5901 g_list_free (clist->undo_selection);
5902 g_list_free (clist->undo_unselection);
5903 clist->undo_selection = NULL;
5904 clist->undo_unselection = NULL;
5907 ((GtkCListRow *) (clist->row_list->data))->state !=
5909 fake_toggle_row (clist, 0);
5911 clist->anchor_state = GTK_STATE_SELECTED;
5913 clist->drag_pos = 0;
5914 clist->undo_anchor = clist->focus_row;
5915 update_extended_selection (clist, clist->rows);
5916 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5919 case GTK_SELECTION_MULTIPLE:
5920 for (i = 0, list = clist->row_list; list; i++, list = list->next)
5922 if (((GtkCListRow *)(list->data))->state == GTK_STATE_NORMAL)
5923 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
5931 fake_unselect_all (GtkCList * clist,
5938 if (row >= 0 && (work = g_list_nth (clist->row_list, row)))
5940 if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
5942 GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
5944 if (!GTK_CLIST_FROZEN (clist) &&
5945 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
5946 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
5947 GTK_CLIST_ROW (work));
5951 clist->undo_selection = clist->selection;
5952 clist->selection = NULL;
5953 clist->selection_end = NULL;
5955 for (list = clist->undo_selection; list; list = list->next)
5957 if ((i = GPOINTER_TO_INT (list->data)) == row ||
5958 !(work = g_list_nth (clist->row_list, i)))
5961 GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
5962 if (!GTK_CLIST_FROZEN (clist) &&
5963 gtk_clist_row_is_visible (clist, i) != GTK_VISIBILITY_NONE)
5964 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, i,
5965 GTK_CLIST_ROW (work));
5970 fake_toggle_row (GtkCList *clist,
5975 if (!(work = g_list_nth (clist->row_list, row)))
5978 if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
5979 clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
5981 clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
5983 if (!GTK_CLIST_FROZEN (clist) &&
5984 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
5985 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
5986 GTK_CLIST_ROW (work));
5990 selection_find (GtkCList *clist,
5992 GList *row_list_element)
5994 return g_list_find (clist->selection, GINT_TO_POINTER (row_number));