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);
355 static void gtk_clist_marshal_signal_1 (GtkObject * object,
359 static void gtk_clist_marshal_signal_2 (GtkObject * object,
363 static void gtk_clist_marshal_signal_3 (GtkObject * object,
367 static void gtk_clist_marshal_signal_4 (GtkObject * object,
371 static void gtk_clist_marshal_signal_5 (GtkObject * object,
378 /* Fill in data after widget is realized and has style */
380 static void add_style_data (GtkCList * clist);
382 static GtkContainerClass *parent_class = NULL;
383 static guint clist_signals[LAST_SIGNAL] = {0};
387 gtk_clist_get_type (void)
389 static GtkType clist_type = 0;
393 GtkTypeInfo clist_info =
397 sizeof (GtkCListClass),
398 (GtkClassInitFunc) gtk_clist_class_init,
399 (GtkObjectInitFunc) gtk_clist_init,
400 /* reserved_1 */ NULL,
401 /* reserved_2 */ NULL,
402 (GtkClassInitFunc) NULL,
405 clist_type = gtk_type_unique (gtk_container_get_type (), &clist_info);
412 gtk_clist_class_init (GtkCListClass * klass)
414 GtkObjectClass *object_class;
415 GtkWidgetClass *widget_class;
416 GtkContainerClass *container_class;
418 object_class = (GtkObjectClass *) klass;
419 widget_class = (GtkWidgetClass *) klass;
420 container_class = (GtkContainerClass *) klass;
422 parent_class = gtk_type_class (gtk_container_get_type ());
424 clist_signals[SELECT_ROW] =
425 gtk_signal_new ("select_row",
428 GTK_SIGNAL_OFFSET (GtkCListClass, select_row),
429 gtk_clist_marshal_signal_1,
430 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_GDK_EVENT);
431 clist_signals[UNSELECT_ROW] =
432 gtk_signal_new ("unselect_row",
435 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_row),
436 gtk_clist_marshal_signal_1,
437 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_GDK_EVENT);
438 clist_signals[CLICK_COLUMN] =
439 gtk_signal_new ("click_column",
442 GTK_SIGNAL_OFFSET (GtkCListClass, click_column),
443 gtk_clist_marshal_signal_3,
444 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
446 clist_signals[TOGGLE_FOCUS_ROW] =
447 gtk_signal_new ("toggle_focus_row",
448 GTK_RUN_LAST | GTK_RUN_ACTION,
450 GTK_SIGNAL_OFFSET (GtkCListClass, toggle_focus_row),
451 gtk_clist_marshal_signal_2,
453 clist_signals[SELECT_ALL] =
454 gtk_signal_new ("select_all",
455 GTK_RUN_LAST | GTK_RUN_ACTION,
457 GTK_SIGNAL_OFFSET (GtkCListClass, select_all),
458 gtk_clist_marshal_signal_2,
460 clist_signals[UNSELECT_ALL] =
461 gtk_signal_new ("unselect_all",
462 GTK_RUN_LAST | GTK_RUN_ACTION,
464 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_all),
465 gtk_clist_marshal_signal_2,
467 clist_signals[UNDO_SELECTION] =
468 gtk_signal_new ("undo_selection",
469 GTK_RUN_LAST | GTK_RUN_ACTION,
471 GTK_SIGNAL_OFFSET (GtkCListClass, undo_selection),
472 gtk_clist_marshal_signal_2,
474 clist_signals[START_SELECTION] =
475 gtk_signal_new ("start_selection",
476 GTK_RUN_LAST | GTK_RUN_ACTION,
478 GTK_SIGNAL_OFFSET (GtkCListClass, start_selection),
479 gtk_clist_marshal_signal_2,
481 clist_signals[END_SELECTION] =
482 gtk_signal_new ("end_selection",
483 GTK_RUN_LAST | GTK_RUN_ACTION,
485 GTK_SIGNAL_OFFSET (GtkCListClass, end_selection),
486 gtk_clist_marshal_signal_2,
488 clist_signals[TOGGLE_ADD_MODE] =
489 gtk_signal_new ("toggle_add_mode",
490 GTK_RUN_LAST | GTK_RUN_ACTION,
492 GTK_SIGNAL_OFFSET (GtkCListClass, toggle_add_mode),
493 gtk_clist_marshal_signal_2,
495 clist_signals[EXTEND_SELECTION] =
496 gtk_signal_new ("extend_selection",
497 GTK_RUN_LAST | GTK_RUN_ACTION,
499 GTK_SIGNAL_OFFSET (GtkCListClass, extend_selection),
500 gtk_clist_marshal_signal_5,
502 GTK_TYPE_ENUM, GTK_TYPE_FLOAT, GTK_TYPE_BOOL);
503 clist_signals[SCROLL_VERTICAL] =
504 gtk_signal_new ("scroll_vertical",
505 GTK_RUN_LAST | GTK_RUN_ACTION,
507 GTK_SIGNAL_OFFSET (GtkCListClass, scroll_vertical),
508 gtk_clist_marshal_signal_4,
509 GTK_TYPE_NONE, 2, GTK_TYPE_ENUM, GTK_TYPE_FLOAT);
510 clist_signals[SCROLL_HORIZONTAL] =
511 gtk_signal_new ("scroll_horizontal",
512 GTK_RUN_LAST | GTK_RUN_ACTION,
514 GTK_SIGNAL_OFFSET (GtkCListClass, scroll_horizontal),
515 gtk_clist_marshal_signal_4,
516 GTK_TYPE_NONE, 2, GTK_TYPE_ENUM, GTK_TYPE_FLOAT);
517 clist_signals[ABORT_COLUMN_RESIZE] =
518 gtk_signal_new ("abort_column_resize",
519 GTK_RUN_LAST | GTK_RUN_ACTION,
521 GTK_SIGNAL_OFFSET (GtkCListClass, abort_column_resize),
522 gtk_clist_marshal_signal_2,
526 gtk_object_class_add_signals (object_class, clist_signals, LAST_SIGNAL);
528 object_class->destroy = gtk_clist_destroy;
529 object_class->finalize = gtk_clist_finalize;
531 widget_class->realize = gtk_clist_realize;
532 widget_class->unrealize = gtk_clist_unrealize;
533 widget_class->map = gtk_clist_map;
534 widget_class->unmap = gtk_clist_unmap;
535 widget_class->draw = gtk_clist_draw;
536 widget_class->button_press_event = gtk_clist_button_press;
537 widget_class->button_release_event = gtk_clist_button_release;
538 widget_class->motion_notify_event = gtk_clist_motion;
539 widget_class->expose_event = gtk_clist_expose;
540 widget_class->size_request = gtk_clist_size_request;
541 widget_class->size_allocate = gtk_clist_size_allocate;
542 widget_class->key_press_event = gtk_clist_key_press;
543 widget_class->focus_in_event = gtk_clist_focus_in;
544 widget_class->focus_out_event = gtk_clist_focus_out;
545 widget_class->draw_focus = gtk_clist_draw_focus;
547 /* container_class->add = NULL; use the default GtkContainerClass warning */
548 /* container_class->remove = NULL; use the default GtkContainerClass warning */
549 container_class->foreach = gtk_clist_foreach;
550 container_class->focus = gtk_clist_focus;
551 container_class->set_focus_child = gtk_clist_set_focus_child;
553 klass->select_row = real_select_row;
554 klass->unselect_row = real_unselect_row;
555 klass->undo_selection = real_undo_selection;
556 klass->resync_selection = resync_selection;
557 klass->selection_find = selection_find;
558 klass->click_column = NULL;
559 klass->draw_row = draw_row;
560 klass->clear = real_clear;
561 klass->select_all = real_select_all;
562 klass->unselect_all = real_unselect_all;
563 klass->fake_unselect_all = fake_unselect_all;
564 klass->scroll_horizontal = scroll_horizontal;
565 klass->scroll_vertical = scroll_vertical;
566 klass->extend_selection = extend_selection;
567 klass->toggle_focus_row = toggle_focus_row;
568 klass->toggle_add_mode = toggle_add_mode;
569 klass->start_selection = start_selection;
570 klass->end_selection = end_selection;
571 klass->abort_column_resize = abort_column_resize;
573 klass->scrollbar_spacing = 5;
576 GtkBindingSet *binding_set;
578 binding_set = gtk_binding_set_by_class (klass);
579 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
580 "scroll_vertical", 2,
581 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
582 GTK_TYPE_FLOAT, 0.0);
583 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
584 "scroll_vertical", 2,
585 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
586 GTK_TYPE_FLOAT, 0.0);
587 gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
588 "scroll_vertical", 2,
589 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
590 GTK_TYPE_FLOAT, 0.0);
591 gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
592 "scroll_vertical", 2,
593 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
594 GTK_TYPE_FLOAT, 0.0);
595 gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
596 "scroll_vertical", 2,
597 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
598 GTK_TYPE_FLOAT, 0.0);
599 gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
600 "scroll_vertical", 2,
601 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
602 GTK_TYPE_FLOAT, 1.0);
604 gtk_binding_entry_add_signal (binding_set, GDK_Up, GDK_SHIFT_MASK,
605 "extend_selection", 3,
606 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
607 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
608 gtk_binding_entry_add_signal (binding_set, GDK_Down, GDK_SHIFT_MASK,
609 "extend_selection", 3,
610 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
611 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
612 gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_SHIFT_MASK,
613 "extend_selection", 3,
614 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
615 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
616 gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_SHIFT_MASK,
617 "extend_selection", 3,
618 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
619 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
620 gtk_binding_entry_add_signal (binding_set, GDK_Home,
621 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
622 "extend_selection", 3,
623 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
624 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
625 gtk_binding_entry_add_signal (binding_set, GDK_End,
626 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
627 "extend_selection", 3,
628 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
629 GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
632 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
633 "scroll_horizontal", 2,
634 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
635 GTK_TYPE_FLOAT, 0.0);
636 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
637 "scroll_horizontal", 2,
638 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
639 GTK_TYPE_FLOAT, 0.0);
640 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
641 "scroll_horizontal", 2,
642 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
643 GTK_TYPE_FLOAT, 0.0);
644 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
645 "scroll_horizontal", 2,
646 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
647 GTK_TYPE_FLOAT, 1.0);
650 gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
651 "undo_selection", 0);
652 gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
653 "abort_column_resize", 0);
654 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
655 "toggle_focus_row", 0);
656 gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
657 "toggle_add_mode", 0);
658 gtk_binding_entry_add_signal (binding_set, '/', GDK_CONTROL_MASK,
660 gtk_binding_entry_add_signal (binding_set, '\\', GDK_CONTROL_MASK,
662 gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
663 GDK_RELEASE_MASK | GDK_SHIFT_MASK,
665 gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
666 GDK_RELEASE_MASK | GDK_SHIFT_MASK,
672 GtkBindingSet *binding_set;
674 binding_set = gtk_binding_set_by_class (klass);
675 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
676 "scroll_vertical", 2,
677 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
678 GTK_TYPE_FLOAT, 0.0);
679 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
680 "scroll_vertical", 2,
681 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
682 GTK_TYPE_FLOAT, 0.0);
683 gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
684 "scroll_vertical", 2,
685 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
686 GTK_TYPE_FLOAT, 0.0);
687 gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
688 "scroll_vertical", 2,
689 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
690 GTK_TYPE_FLOAT, 0.0);
691 gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
692 "scroll_vertical", 2,
693 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
694 GTK_TYPE_FLOAT, 0.0);
695 gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
696 "scroll_vertical", 2,
697 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
700 gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
701 "extend_selection", 3,
702 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
703 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
704 gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
705 "extend_selection", 3,
706 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
707 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
708 gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, 0,
709 "extend_selection", 3,
710 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
711 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
712 gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, 0,
713 "extend_selection", 3,
714 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
715 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
716 gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
717 "extend_selection", 3,
718 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
719 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
720 gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
721 "extend_selection", 3,
722 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
723 GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
725 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
726 "scroll_horizontal", 2,
727 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
728 GTK_TYPE_FLOAT, 0.0);
729 gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
730 "scroll_horizontal", 2,
731 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
732 GTK_TYPE_FLOAT, 0.0);
733 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
734 "scroll_horizontal", 2,
735 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
736 GTK_TYPE_FLOAT, 0.0);
737 gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
738 "scroll_horizontal", 2,
739 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
740 GTK_TYPE_FLOAT, 0.0);
741 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
742 "scroll_horizontal", 2,
743 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
744 GTK_TYPE_FLOAT, 0.0);
745 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
746 "sroll_horizontal", 2,
747 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
748 GTK_TYPE_FLOAT, 1.0);
750 gtk_binding_entry_add_signal (binding_set, GDK_KP_Divide, 0,
751 "undo_selection", 0);
752 gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
753 "abort_column_resize", 0);
754 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
755 "toggle_focus_row", 0);
756 gtk_binding_entry_add_signal (binding_set, GDK_KP_Multiply, 0,
757 "toggle_add_mode", 0);
758 gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, 0,
760 gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, 0,
762 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
769 gtk_clist_marshal_signal_1 (GtkObject * object,
774 GtkCListSignal1 rfunc;
776 rfunc = (GtkCListSignal1) func;
778 (*rfunc) (object, GTK_VALUE_INT (args[0]),
779 GTK_VALUE_INT (args[1]),
780 GTK_VALUE_POINTER (args[2]),
785 gtk_clist_marshal_signal_2 (GtkObject * object,
790 GtkCListSignal2 rfunc;
792 rfunc = (GtkCListSignal2) func;
794 (*rfunc) (object, func_data);
798 gtk_clist_marshal_signal_3 (GtkObject * object,
803 GtkCListSignal3 rfunc;
805 rfunc = (GtkCListSignal3) func;
807 (*rfunc) (object, GTK_VALUE_INT (args[0]), func_data);
811 gtk_clist_marshal_signal_4 (GtkObject * object,
816 GtkCListSignal4 rfunc;
818 rfunc = (GtkCListSignal4) func;
820 (*rfunc) (object, GTK_VALUE_INT (args[0]),
821 GTK_VALUE_FLOAT (args[1]), func_data);
825 gtk_clist_marshal_signal_5 (GtkObject * object,
830 GtkCListSignal5 rfunc;
832 rfunc = (GtkCListSignal5) func;
834 (*rfunc) (object, GTK_VALUE_INT (args[0]), GTK_VALUE_FLOAT (args[1]),
835 GTK_VALUE_BOOL (args[2]), func_data);
839 gtk_clist_init (GtkCList * clist)
843 GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
844 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
846 clist->row_mem_chunk = NULL;
847 clist->cell_mem_chunk = NULL;
850 clist->row_center_offset = 0;
851 clist->row_height = 0;
852 clist->row_list = NULL;
853 clist->row_list_end = NULL;
857 clist->title_window = NULL;
858 clist->column_title_area.x = 0;
859 clist->column_title_area.y = 0;
860 clist->column_title_area.width = 1;
861 clist->column_title_area.height = 1;
863 clist->clist_window = NULL;
864 clist->clist_window_width = 1;
865 clist->clist_window_height = 1;
870 clist->shadow_type = GTK_SHADOW_IN;
871 clist->hscrollbar_policy = GTK_POLICY_ALWAYS;
872 clist->vscrollbar_policy = GTK_POLICY_ALWAYS;
874 clist->cursor_drag = NULL;
875 clist->xor_gc = NULL;
880 clist->selection_mode = GTK_SELECTION_SINGLE;
881 clist->selection = NULL;
882 clist->selection_end = NULL;
883 clist->undo_selection = NULL;
884 clist->undo_unselection = NULL;
886 GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
887 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
888 clist->focus_row = -1;
889 clist->undo_anchor = -1;
892 clist->anchor_state = GTK_STATE_SELECTED;
893 clist->drag_pos = -1;
900 gtk_clist_construct (GtkCList * clist,
906 g_return_if_fail (clist != NULL);
907 g_return_if_fail (GTK_IS_CLIST (clist));
908 g_return_if_fail (GTK_CLIST_CONSTRUCTED (clist) == FALSE);
910 GTK_CLIST_SET_FLAG (clist, CLIST_CONSTRUCTED);
912 /* initalize memory chunks, if this has not been done by any
913 * possibly derived widget
915 if (!clist->row_mem_chunk)
916 clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
917 sizeof (GtkCListRow),
918 sizeof (GtkCListRow) * CLIST_OPTIMUM_SIZE,
921 if (!clist->cell_mem_chunk)
922 clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
923 sizeof (GtkCell) * columns,
924 sizeof (GtkCell) * columns * CLIST_OPTIMUM_SIZE,
927 /* set number of columns, allocate memory */
928 clist->columns = columns;
929 clist->column = columns_new (clist);
931 /* there needs to be at least one column button
932 * because there is alot of code that will break if it
934 column_button_create (clist, 0);
936 /* create scrollbars */
937 create_scrollbars (clist);
941 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
942 for (i = 0; i < columns; i++)
943 gtk_clist_set_column_title (clist, i, titles[i]);
947 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
952 * GTKCLIST PUBLIC INTERFACE
953 * gtk_clist_new_with_titles
957 gtk_clist_new_with_titles (gint columns,
962 g_return_val_if_fail (titles != NULL, NULL);
964 widget = gtk_type_new (gtk_clist_get_type ());
966 gtk_clist_construct (GTK_CLIST (widget), columns, titles);
972 gtk_clist_new (gint columns)
979 clist = gtk_type_new (gtk_clist_get_type ());
980 gtk_clist_construct (clist, columns, NULL);
981 return GTK_WIDGET (clist);
985 gtk_clist_set_border (GtkCList * clist,
986 GtkShadowType border)
988 g_return_if_fail (clist != NULL);
989 g_return_if_fail (GTK_IS_CLIST (clist));
991 clist->shadow_type = border;
993 if (GTK_WIDGET_VISIBLE (clist))
994 gtk_widget_queue_resize (GTK_WIDGET (clist));
998 gtk_clist_set_selection_mode (GtkCList * clist,
999 GtkSelectionMode mode)
1001 g_return_if_fail (clist != NULL);
1002 g_return_if_fail (GTK_IS_CLIST (clist));
1004 if (mode == clist->selection_mode)
1007 clist->selection_mode = mode;
1009 clist->anchor_state = GTK_STATE_SELECTED;
1010 clist->drag_pos = -1;
1011 clist->undo_anchor = clist->focus_row;
1013 g_list_free (clist->undo_selection);
1014 g_list_free (clist->undo_unselection);
1015 clist->undo_selection = NULL;
1016 clist->undo_unselection = NULL;
1020 case GTK_SELECTION_MULTIPLE:
1021 case GTK_SELECTION_EXTENDED:
1023 case GTK_SELECTION_BROWSE:
1024 case GTK_SELECTION_SINGLE:
1025 gtk_clist_unselect_all (clist);
1031 gtk_clist_freeze (GtkCList * clist)
1033 g_return_if_fail (clist != NULL);
1034 g_return_if_fail (GTK_IS_CLIST (clist));
1036 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
1040 gtk_clist_thaw (GtkCList * clist)
1042 g_return_if_fail (clist != NULL);
1043 g_return_if_fail (GTK_IS_CLIST (clist));
1045 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
1047 adjust_scrollbars (clist);
1048 draw_rows (clist, NULL);
1052 gtk_clist_column_titles_show (GtkCList * clist)
1054 g_return_if_fail (clist != NULL);
1055 g_return_if_fail (GTK_IS_CLIST (clist));
1057 if (!GTK_CLIST_SHOW_TITLES (clist))
1059 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
1060 if (clist->title_window)
1061 gdk_window_show (clist->title_window);
1062 gtk_widget_queue_resize (GTK_WIDGET (clist));
1067 gtk_clist_column_titles_hide (GtkCList * clist)
1069 g_return_if_fail (clist != NULL);
1070 g_return_if_fail (GTK_IS_CLIST (clist));
1072 if (GTK_CLIST_SHOW_TITLES (clist))
1074 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
1075 if (clist->title_window)
1076 gdk_window_hide (clist->title_window);
1077 gtk_widget_queue_resize (GTK_WIDGET (clist));
1082 gtk_clist_column_title_active (GtkCList * clist,
1085 g_return_if_fail (clist != NULL);
1086 g_return_if_fail (GTK_IS_CLIST (clist));
1088 if (column < 0 || column >= clist->columns)
1091 if (!GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
1092 !GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
1094 GTK_WIDGET_SET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
1095 if (GTK_WIDGET_VISIBLE (clist))
1096 gtk_widget_queue_draw (clist->column[column].button);
1101 gtk_clist_column_title_passive (GtkCList * clist,
1104 g_return_if_fail (clist != NULL);
1105 g_return_if_fail (GTK_IS_CLIST (clist));
1107 if (column < 0 || column >= clist->columns)
1110 if (GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
1111 GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
1113 GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
1114 if (GTK_WIDGET_VISIBLE (clist))
1115 gtk_widget_queue_draw (clist->column[column].button);
1120 gtk_clist_column_titles_active (GtkCList * clist)
1124 g_return_if_fail (clist != NULL);
1125 g_return_if_fail (GTK_IS_CLIST (clist));
1127 for (i = 0; i < clist->columns; i++)
1128 if (clist->column[i].button)
1129 gtk_clist_column_title_active (clist, i);
1133 gtk_clist_column_titles_passive (GtkCList * clist)
1137 g_return_if_fail (clist != NULL);
1138 g_return_if_fail (GTK_IS_CLIST (clist));
1140 for (i = 0; i < clist->columns; i++)
1141 if (clist->column[i].button)
1142 gtk_clist_column_title_passive (clist, i);
1146 gtk_clist_set_column_title (GtkCList * clist,
1150 gint new_button = 0;
1151 GtkWidget *old_widget;
1152 GtkWidget *alignment = NULL;
1155 g_return_if_fail (clist != NULL);
1156 g_return_if_fail (GTK_IS_CLIST (clist));
1158 if (column < 0 || column >= clist->columns)
1161 /* if the column button doesn't currently exist,
1162 * it has to be created first */
1163 if (!clist->column[column].button)
1165 column_button_create (clist, column);
1169 column_title_new (clist, column, title);
1171 /* remove and destroy the old widget */
1172 old_widget = GTK_BIN (clist->column[column].button)->child;
1174 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
1176 /* create new alignment based no column justification */
1177 switch (clist->column[column].justification)
1179 case GTK_JUSTIFY_LEFT:
1180 alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
1183 case GTK_JUSTIFY_RIGHT:
1184 alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
1187 case GTK_JUSTIFY_CENTER:
1188 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1191 case GTK_JUSTIFY_FILL:
1192 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1196 label = gtk_label_new (clist->column[column].title);
1197 gtk_container_add (GTK_CONTAINER (alignment), label);
1198 gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
1199 gtk_widget_show (label);
1200 gtk_widget_show (alignment);
1202 /* if this button didn't previously exist, then the
1203 * column button positions have to be re-computed */
1204 if (GTK_WIDGET_VISIBLE (clist) && new_button)
1205 size_allocate_title_buttons (clist);
1209 gtk_clist_set_column_widget (GtkCList * clist,
1213 gint new_button = 0;
1214 GtkWidget *old_widget;
1216 g_return_if_fail (clist != NULL);
1217 g_return_if_fail (GTK_IS_CLIST (clist));
1219 if (column < 0 || column >= clist->columns)
1222 /* if the column button doesn't currently exist,
1223 * it has to be created first */
1224 if (!clist->column[column].button)
1226 column_button_create (clist, column);
1230 column_title_new (clist, column, NULL);
1232 /* remove and destroy the old widget */
1233 old_widget = GTK_BIN (clist->column[column].button)->child;
1235 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
1237 /* add and show the widget */
1240 gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
1241 gtk_widget_show (widget);
1244 /* if this button didn't previously exist, then the
1245 * column button positions have to be re-computed */
1246 if (GTK_WIDGET_VISIBLE (clist) && new_button)
1247 size_allocate_title_buttons (clist);
1251 gtk_clist_set_column_justification (GtkCList * clist,
1253 GtkJustification justification)
1255 GtkWidget *alignment;
1257 g_return_if_fail (clist != NULL);
1258 g_return_if_fail (GTK_IS_CLIST (clist));
1260 if (column < 0 || column >= clist->columns)
1263 clist->column[column].justification = justification;
1265 /* change the alinment of the button title if it's not a
1267 if (clist->column[column].title)
1269 alignment = GTK_BIN (clist->column[column].button)->child;
1271 switch (clist->column[column].justification)
1273 case GTK_JUSTIFY_LEFT:
1274 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
1277 case GTK_JUSTIFY_RIGHT:
1278 gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
1281 case GTK_JUSTIFY_CENTER:
1282 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1285 case GTK_JUSTIFY_FILL:
1286 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1294 if (!GTK_CLIST_FROZEN (clist))
1295 draw_rows (clist, NULL);
1299 gtk_clist_set_column_width (GtkCList * clist,
1303 g_return_if_fail (clist != NULL);
1304 g_return_if_fail (GTK_IS_CLIST (clist));
1306 if (column < 0 || column >= clist->columns)
1309 clist->column[column].width = width;
1310 clist->column[column].width_set = TRUE;
1312 /* FIXME: this is quite expensive to do if the widget hasn't
1313 * been size_allocated yet, and pointless. Should
1316 size_allocate_columns (clist);
1317 size_allocate_title_buttons (clist);
1319 if (!GTK_CLIST_FROZEN (clist))
1321 adjust_scrollbars (clist);
1322 draw_rows (clist, NULL);
1327 gtk_clist_set_row_height (GtkCList * clist,
1332 g_return_if_fail (clist != NULL);
1333 g_return_if_fail (GTK_IS_CLIST (clist));
1336 clist->row_height = height;
1340 GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
1342 if (GTK_WIDGET_REALIZED (clist))
1344 text_height = height - (GTK_WIDGET (clist)->style->font->ascent +
1345 GTK_WIDGET (clist) ->style->font->descent + 1);
1346 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
1349 if (!GTK_CLIST_FROZEN (clist))
1351 adjust_scrollbars (clist);
1352 draw_rows (clist, NULL);
1357 gtk_clist_moveto (GtkCList * clist,
1363 g_return_if_fail (clist != NULL);
1364 g_return_if_fail (GTK_IS_CLIST (clist));
1366 if (row < -1 || row >= clist->rows)
1368 if (column < -1 || column >= clist->columns)
1371 row_align = CLAMP (row_align, 0, 1);
1372 col_align = CLAMP (col_align, 0, 1);
1374 /* adjust horizontal scrollbar */
1380 adj = GTK_RANGE (clist->hscrollbar)->adjustment;
1382 x = COLUMN_LEFT (clist, column) - CELL_SPACING - COLUMN_INSET -
1383 (col_align * (clist->clist_window_width - 2 * COLUMN_INSET -
1384 CELL_SPACING - clist->column[column].area.width));
1386 gtk_adjustment_set_value (adj, 0.0);
1387 else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
1388 gtk_adjustment_set_value
1389 (adj, LIST_WIDTH (clist) - clist->clist_window_width);
1391 gtk_adjustment_set_value (adj, x);
1394 /* adjust vertical scrollbar */
1396 move_vertical (clist, row, row_align);
1400 gtk_clist_get_cell_type (GtkCList * clist,
1404 GtkCListRow *clist_row;
1406 g_return_val_if_fail (clist != NULL, -1);
1407 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
1409 if (row < 0 || row >= clist->rows)
1411 if (column < 0 || column >= clist->columns)
1414 clist_row = (g_list_nth (clist->row_list, row))->data;
1416 return clist_row->cell[column].type;
1420 gtk_clist_set_text (GtkCList * clist,
1425 GtkCListRow *clist_row;
1427 g_return_if_fail (clist != NULL);
1428 g_return_if_fail (GTK_IS_CLIST (clist));
1430 if (row < 0 || row >= clist->rows)
1432 if (column < 0 || column >= clist->columns)
1435 clist_row = (g_list_nth (clist->row_list, row))->data;
1437 /* if text is null, then the cell is empty */
1439 cell_set_text (clist, clist_row, column, text);
1441 cell_empty (clist, clist_row, column);
1443 /* redraw the list if it's not frozen */
1444 if (!GTK_CLIST_FROZEN (clist))
1446 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1447 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1452 gtk_clist_get_text (GtkCList * clist,
1457 GtkCListRow *clist_row;
1459 g_return_val_if_fail (clist != NULL, 0);
1460 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
1462 if (row < 0 || row >= clist->rows)
1464 if (column < 0 || column >= clist->columns)
1467 clist_row = (g_list_nth (clist->row_list, row))->data;
1469 if (clist_row->cell[column].type != GTK_CELL_TEXT)
1473 *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
1479 gtk_clist_set_pixmap (GtkCList * clist,
1485 GtkCListRow *clist_row;
1487 g_return_if_fail (clist != NULL);
1488 g_return_if_fail (GTK_IS_CLIST (clist));
1490 if (row < 0 || row >= clist->rows)
1492 if (column < 0 || column >= clist->columns)
1495 clist_row = (g_list_nth (clist->row_list, row))->data;
1497 gdk_pixmap_ref (pixmap);
1499 if (mask) gdk_pixmap_ref (mask);
1501 cell_set_pixmap (clist, clist_row, column, pixmap, mask);
1503 /* redraw the list if it's not frozen */
1504 if (!GTK_CLIST_FROZEN (clist))
1506 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1507 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1512 gtk_clist_get_pixmap (GtkCList * clist,
1515 GdkPixmap ** pixmap,
1518 GtkCListRow *clist_row;
1520 g_return_val_if_fail (clist != NULL, 0);
1521 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
1523 if (row < 0 || row >= clist->rows)
1525 if (column < 0 || column >= clist->columns)
1528 clist_row = (g_list_nth (clist->row_list, row))->data;
1530 if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
1535 *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
1536 /* mask can be NULL */
1537 *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
1544 gtk_clist_set_pixtext (GtkCList * clist,
1552 GtkCListRow *clist_row;
1554 g_return_if_fail (clist != NULL);
1555 g_return_if_fail (GTK_IS_CLIST (clist));
1557 if (row < 0 || row >= clist->rows)
1559 if (column < 0 || column >= clist->columns)
1562 clist_row = (g_list_nth (clist->row_list, row))->data;
1564 gdk_pixmap_ref (pixmap);
1565 if (mask) gdk_pixmap_ref (mask);
1566 cell_set_pixtext (clist, clist_row, column, text, spacing, pixmap, mask);
1568 /* redraw the list if it's not frozen */
1569 if (!GTK_CLIST_FROZEN (clist))
1571 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1572 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1577 gtk_clist_get_pixtext (GtkCList * clist,
1582 GdkPixmap ** pixmap,
1585 GtkCListRow *clist_row;
1587 g_return_val_if_fail (clist != NULL, 0);
1588 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
1590 if (row < 0 || row >= clist->rows)
1592 if (column < 0 || column >= clist->columns)
1595 clist_row = (g_list_nth (clist->row_list, row))->data;
1597 if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
1601 *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
1603 *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
1605 *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
1607 /* mask can be NULL */
1608 *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
1614 gtk_clist_set_foreground (GtkCList * clist,
1618 GtkCListRow *clist_row;
1620 g_return_if_fail (clist != NULL);
1621 g_return_if_fail (GTK_IS_CLIST (clist));
1623 if (row < 0 || row >= clist->rows)
1626 clist_row = (g_list_nth (clist->row_list, row))->data;
1630 clist_row->foreground = *color;
1631 clist_row->fg_set = TRUE;
1634 clist_row->fg_set = FALSE;
1636 if (!GTK_CLIST_FROZEN (clist)
1637 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1638 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1642 gtk_clist_set_background (GtkCList * clist,
1646 GtkCListRow *clist_row;
1648 g_return_if_fail (clist != NULL);
1649 g_return_if_fail (GTK_IS_CLIST (clist));
1651 if (row < 0 || row >= clist->rows)
1654 clist_row = (g_list_nth (clist->row_list, row))->data;
1658 clist_row->background = *color;
1659 clist_row->bg_set = TRUE;
1662 clist_row->bg_set = FALSE;
1664 if (!GTK_CLIST_FROZEN (clist)
1665 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1666 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1670 gtk_clist_set_shift (GtkCList * clist,
1676 GtkCListRow *clist_row;
1678 g_return_if_fail (clist != NULL);
1679 g_return_if_fail (GTK_IS_CLIST (clist));
1681 if (row < 0 || row >= clist->rows)
1683 if (column < 0 || column >= clist->columns)
1686 clist_row = (g_list_nth (clist->row_list, row))->data;
1688 clist_row->cell[column].vertical = vertical;
1689 clist_row->cell[column].horizontal = horizontal;
1691 if (!GTK_CLIST_FROZEN (clist)
1692 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1693 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
1697 gtk_clist_append (GtkCList * clist,
1701 GtkCListRow *clist_row;
1703 g_return_val_if_fail (clist != NULL, -1);
1704 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
1706 clist_row = row_new (clist);
1709 /* set the text in the row's columns */
1711 for (i = 0; i < clist->columns; i++)
1713 cell_set_text (clist, clist_row, i, text[i]);
1715 /* keeps track of the end of the list so the list
1716 * doesn't have to be traversed every time a item is added */
1717 if (!clist->row_list)
1719 clist->row_list = g_list_append (clist->row_list, clist_row);
1720 clist->row_list_end = clist->row_list;
1722 /* check the selection mode to see if we should select
1723 * the first row automaticly */
1724 switch (clist->selection_mode)
1726 case GTK_SELECTION_BROWSE:
1727 select_row (clist, 0, -1, NULL);
1735 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
1737 /* redraw the list if it's not frozen */
1738 if (!GTK_CLIST_FROZEN (clist))
1740 adjust_scrollbars (clist);
1742 if (gtk_clist_row_is_visible (clist, clist->rows - 1) != GTK_VISIBILITY_NONE)
1743 draw_rows (clist, NULL);
1746 /* return index of the row */
1747 return clist->rows - 1;
1751 gtk_clist_insert (GtkCList * clist,
1756 GtkCListRow *clist_row;
1758 g_return_if_fail (clist != NULL);
1759 g_return_if_fail (GTK_IS_CLIST (clist));
1760 g_return_if_fail (text != NULL);
1762 /* return if out of bounds */
1763 if (row < 0 || row > clist->rows)
1766 if (clist->rows == 0)
1767 gtk_clist_append (clist, text);
1770 /* create the row */
1771 clist_row = row_new (clist);
1773 /* set the text in the row's columns */
1775 for (i = 0; i < clist->columns; i++)
1777 cell_set_text (clist, clist_row, i, text[i]);
1779 /* reset the row end pointer if we're inserting at the
1780 * end of the list */
1781 if (row == clist->rows)
1782 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
1784 clist->row_list = g_list_insert (clist->row_list, clist_row, row);
1788 if (row < ROW_FROM_YPIXEL (clist, 0))
1789 clist->voffset -= (clist->row_height + CELL_SPACING);
1791 /* syncronize the selection list */
1792 sync_selection (clist, row, SYNC_INSERT);
1795 /* redraw the list if it isn't frozen */
1796 if (!GTK_CLIST_FROZEN (clist))
1798 adjust_scrollbars (clist);
1800 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1801 draw_rows (clist, NULL);
1806 gtk_clist_remove (GtkCList * clist,
1809 gint was_visible, was_selected;
1811 GtkCListRow *clist_row;
1813 g_return_if_fail (clist != NULL);
1814 g_return_if_fail (GTK_IS_CLIST (clist));
1816 /* return if out of bounds */
1817 if (row < 0 || row > (clist->rows - 1))
1820 was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
1823 /* get the row we're going to delete */
1824 list = g_list_nth (clist->row_list, row);
1825 clist_row = list->data;
1827 /* if we're removing a selected row, we have to make sure
1828 * it's properly unselected, and then sync up the clist->selected
1829 * list to reflect the deincrimented indexies of rows after the
1831 if (clist_row->state == GTK_STATE_SELECTED)
1833 switch (clist->selection_mode)
1835 case GTK_SELECTION_SINGLE:
1836 case GTK_SELECTION_MULTIPLE:
1837 case GTK_SELECTION_EXTENDED:
1838 unselect_row (clist, row, -1, NULL);
1841 case GTK_SELECTION_BROWSE:
1842 select_row (clist, row - 1, -1, NULL);
1850 /* reset the row end pointer if we're removing at the
1851 * end of the list */
1852 if (row == clist->rows - 1)
1853 clist->row_list_end = list->prev;
1854 if (row >= clist->focus_row && clist->focus_row >=0)
1857 clist->row_list = g_list_remove (clist->row_list, clist_row);
1860 if (row < ROW_FROM_YPIXEL (clist, 0))
1861 clist->voffset += clist->row_height + CELL_SPACING;
1863 sync_selection (clist, row, SYNC_REMOVE);
1866 row_delete (clist, clist_row);
1868 /* redraw the row if it isn't frozen */
1869 if (!GTK_CLIST_FROZEN (clist))
1871 adjust_scrollbars (clist);
1874 draw_rows (clist, NULL);
1879 sync_selection (GtkCList * clist,
1886 if (mode == SYNC_INSERT)
1891 if (clist->focus_row >= row)
1893 clist->focus_row += d;
1894 if (clist->focus_row == -1 && clist->rows >= 1)
1895 clist->focus_row = 0;
1898 if (clist->selection_mode == GTK_SELECTION_BROWSE && clist->anchor != -1)
1899 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
1901 g_list_free (clist->undo_selection);
1902 g_list_free (clist->undo_unselection);
1903 clist->undo_selection = NULL;
1904 clist->undo_unselection = NULL;
1907 clist->drag_pos = -1;
1908 clist->undo_anchor = clist->focus_row;
1910 list = clist->selection;
1913 if (GPOINTER_TO_INT (list->data) >= row)
1914 list->data = ((gchar*) list->data) + d;
1920 gtk_clist_clear (GtkCList * clist)
1922 GTK_CLIST_CLASS_FW (clist)->clear (clist);
1926 real_clear (GtkCList * clist)
1930 g_return_if_fail (clist != NULL);
1931 g_return_if_fail (GTK_IS_CLIST (clist));
1933 /* remove all the rows */
1934 for (list = clist->row_list; list; list = list->next)
1935 row_delete (clist, GTK_CLIST_ROW (list));
1937 g_list_free (clist->row_list);
1939 /* free up the selection list */
1940 g_list_free (clist->selection);
1941 g_list_free (clist->undo_selection);
1942 g_list_free (clist->undo_unselection);
1944 clist->row_list = NULL;
1945 clist->row_list_end = NULL;
1946 clist->selection = NULL;
1947 clist->selection_end = NULL;
1948 clist->undo_selection = NULL;
1949 clist->undo_unselection = NULL;
1952 clist->focus_row = -1;
1954 clist->undo_anchor = -1;
1955 clist->anchor_state = GTK_STATE_SELECTED;
1956 clist->drag_pos = -1;
1958 /* zero-out the scrollbars */
1959 if (clist->vscrollbar)
1961 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
1962 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
1964 if (!GTK_CLIST_FROZEN (clist))
1965 gtk_clist_thaw (clist);
1970 gtk_clist_swap_rows (GtkCList * clist,
1975 GList *list, *link1, *link2;
1978 g_return_if_fail (clist != NULL);
1979 g_return_if_fail (GTK_IS_CLIST (clist));
1981 if (row1 < 0 || row1 > (clist->rows - 1))
1984 if (row2 < 0 || row2 > (clist->rows - 1))
1987 first = MIN (row1, row2);
1988 last = MAX (row1, row2);
1990 link1 = g_list_nth (clist->row_list, first);
1991 link2 = g_list_nth (link1, row2 - row1);
1994 link1->data = link2->data;
1997 list = clist->selection;
2000 if (GPOINTER_TO_INT (list->data) == row1)
2001 GPOINTER_TO_INT (list->data) = row2;
2003 if (GPOINTER_TO_INT (list->data) == row2)
2004 GPOINTER_TO_INT (list->data) = row1;
2009 if (!GTK_CLIST_FROZEN (clist))
2011 if (gtk_clist_row_is_visible (clist, row1) != GTK_VISIBILITY_NONE)
2012 GTK_CLIST_CLASS_FW (clist)->draw_row
2013 (clist, NULL, row1, GTK_CLIST_ROW (link2));
2015 if (gtk_clist_row_is_visible (clist, row2) != GTK_VISIBILITY_NONE)
2016 GTK_CLIST_CLASS_FW (clist)->draw_row
2017 (clist, NULL, row2, GTK_CLIST_ROW (link1));
2022 gtk_clist_set_row_data (GtkCList * clist,
2026 gtk_clist_set_row_data_full (clist, row, data, NULL);
2030 gtk_clist_set_row_data_full (GtkCList * clist,
2033 GtkDestroyNotify destroy)
2035 GtkCListRow *clist_row;
2037 g_return_if_fail (clist != NULL);
2038 g_return_if_fail (GTK_IS_CLIST (clist));
2040 if (row < 0 || row > (clist->rows - 1))
2043 clist_row = (g_list_nth (clist->row_list, row))->data;
2044 clist_row->data = data;
2045 clist_row->destroy = destroy;
2047 /* re-send the selected signal if data is changed/added
2048 * so the application can respond to the new data --
2049 * this could be questionable behavior */
2050 if (clist_row->state == GTK_STATE_SELECTED)
2051 select_row (clist, row, -1, NULL);
2055 gtk_clist_get_row_data (GtkCList * clist,
2058 GtkCListRow *clist_row;
2060 g_return_val_if_fail (clist != NULL, NULL);
2061 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
2063 if (row < 0 || row > (clist->rows - 1))
2066 clist_row = (g_list_nth (clist->row_list, row))->data;
2067 return clist_row->data;
2071 gtk_clist_find_row_from_data (GtkCList * clist,
2077 g_return_val_if_fail (clist != NULL, -1);
2078 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2080 if (clist->rows < 1)
2081 return -1; /* is this an optimization or just worthless? */
2083 for (n = 0, list = clist->row_list; list; n++, list = list->next)
2084 if (GTK_CLIST_ROW (list)->data == data)
2091 gtk_clist_select_row (GtkCList * clist,
2095 g_return_if_fail (clist != NULL);
2096 g_return_if_fail (GTK_IS_CLIST (clist));
2098 if (row < 0 || row >= clist->rows)
2101 if (column < -1 || column >= clist->columns)
2104 select_row (clist, row, column, NULL);
2108 gtk_clist_unselect_row (GtkCList * clist,
2112 g_return_if_fail (clist != NULL);
2113 g_return_if_fail (GTK_IS_CLIST (clist));
2115 if (row < 0 || row >= clist->rows)
2118 if (column < -1 || column >= clist->columns)
2121 unselect_row (clist, row, column, NULL);
2125 gtk_clist_row_is_visible (GtkCList * clist,
2130 g_return_val_if_fail (clist != NULL, 0);
2131 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
2133 if (row < 0 || row >= clist->rows)
2134 return GTK_VISIBILITY_NONE;
2136 if (clist->row_height == 0)
2137 return GTK_VISIBILITY_NONE;
2139 if (row < ROW_FROM_YPIXEL (clist, 0))
2140 return GTK_VISIBILITY_NONE;
2142 if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
2143 return GTK_VISIBILITY_NONE;
2145 top = ROW_TOP_YPIXEL (clist, row);
2148 || ((top + clist->row_height) >= clist->clist_window_height))
2149 return GTK_VISIBILITY_PARTIAL;
2151 return GTK_VISIBILITY_FULL;
2155 gtk_clist_get_vadjustment (GtkCList * clist)
2157 g_return_val_if_fail (clist != NULL, NULL);
2158 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
2160 return gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
2164 gtk_clist_get_hadjustment (GtkCList * clist)
2166 g_return_val_if_fail (clist != NULL, NULL);
2167 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
2169 return gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
2173 gtk_clist_set_policy (GtkCList * clist,
2174 GtkPolicyType vscrollbar_policy,
2175 GtkPolicyType hscrollbar_policy)
2177 g_return_if_fail (clist != NULL);
2178 g_return_if_fail (GTK_IS_CLIST (clist));
2180 if (clist->vscrollbar_policy != vscrollbar_policy)
2182 clist->vscrollbar_policy = vscrollbar_policy;
2184 if (GTK_WIDGET (clist)->parent)
2185 gtk_widget_queue_resize (GTK_WIDGET (clist));
2188 if (clist->hscrollbar_policy != hscrollbar_policy)
2190 clist->hscrollbar_policy = hscrollbar_policy;
2192 if (GTK_WIDGET (clist)->parent)
2193 gtk_widget_queue_resize (GTK_WIDGET (clist));
2198 gtk_clist_undo_selection (GtkCList *clist)
2200 g_return_if_fail (clist != NULL);
2201 g_return_if_fail (GTK_IS_CLIST (clist));
2203 if (clist->selection_mode == GTK_SELECTION_EXTENDED &&
2204 (clist->undo_selection || clist->undo_unselection))
2205 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNDO_SELECTION]);
2209 real_undo_selection (GtkCList *clist)
2213 g_return_if_fail (clist != NULL);
2214 g_return_if_fail (GTK_IS_CLIST (clist));
2216 if (gdk_pointer_is_grabbed () ||
2217 clist->selection_mode != GTK_SELECTION_EXTENDED)
2220 if (clist->anchor >= 0)
2221 resync_selection (clist, NULL);
2223 if (!(clist->undo_selection || clist->undo_unselection))
2225 gtk_clist_unselect_all (clist);
2229 for (work = clist->undo_selection; work; work = work->next)
2230 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2231 GPOINTER_TO_INT (work->data), -1, NULL);
2233 for (work = clist->undo_unselection; work; work = work->next)
2234 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2235 GPOINTER_TO_INT (work->data), -1, NULL);
2237 if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
2239 gtk_clist_draw_focus (GTK_WIDGET (clist));
2240 clist->focus_row = clist->undo_anchor;
2241 gtk_clist_draw_focus (GTK_WIDGET (clist));
2244 clist->focus_row = clist->undo_anchor;
2246 clist->undo_anchor = -1;
2248 g_list_free (clist->undo_selection);
2249 g_list_free (clist->undo_unselection);
2250 clist->undo_selection = NULL;
2251 clist->undo_unselection = NULL;
2253 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
2254 clist->clist_window_height)
2255 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
2256 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
2257 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
2263 * gtk_clist_finalize
2266 gtk_clist_destroy (GtkObject * object)
2271 g_return_if_fail (object != NULL);
2272 g_return_if_fail (GTK_IS_CLIST (object));
2274 clist = GTK_CLIST (object);
2276 /* freeze the list */
2277 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
2279 /* get rid of all the rows */
2280 gtk_clist_clear (clist);
2282 /* Since we don't have a _remove method, unparent the children
2283 * instead of destroying them so the focus will be unset properly.
2284 * (For other containers, the _remove method takes care of the
2285 * unparent) The destroy will happen when the refcount drops
2289 /* destroy the scrollbars */
2290 if (clist->vscrollbar)
2292 gtk_widget_unparent (clist->vscrollbar);
2293 clist->vscrollbar = NULL;
2295 if (clist->hscrollbar)
2297 gtk_widget_unparent (clist->hscrollbar);
2298 clist->hscrollbar = NULL;
2303 gtk_timeout_remove (clist->htimer);
2308 gtk_timeout_remove (clist->vtimer);
2312 /* destroy the column buttons */
2313 for (i = 0; i < clist->columns; i++)
2314 if (clist->column[i].button)
2316 gtk_widget_unparent (clist->column[i].button);
2317 clist->column[i].button = NULL;
2320 if (GTK_OBJECT_CLASS (parent_class)->destroy)
2321 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
2325 gtk_clist_finalize (GtkObject * object)
2329 g_return_if_fail (object != NULL);
2330 g_return_if_fail (GTK_IS_CLIST (object));
2332 clist = GTK_CLIST (object);
2334 columns_delete (clist);
2336 g_mem_chunk_destroy (clist->cell_mem_chunk);
2337 g_mem_chunk_destroy (clist->row_mem_chunk);
2339 if (GTK_OBJECT_CLASS (parent_class)->finalize)
2340 (*GTK_OBJECT_CLASS (parent_class)->finalize) (object);
2346 * gtk_clist_unrealize
2351 * gtk_clist_button_press
2352 * gtk_clist_button_release
2353 * gtk_clist_button_motion
2354 * gtk_clist_size_request
2355 * gtk_clist_size_allocate
2358 gtk_clist_realize (GtkWidget * widget)
2362 GdkWindowAttr attributes;
2363 gint attributes_mask;
2367 g_return_if_fail (widget != NULL);
2368 g_return_if_fail (GTK_IS_CLIST (widget));
2370 clist = GTK_CLIST (widget);
2372 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
2374 add_style_data (clist);
2376 border_width = GTK_CONTAINER (widget)->border_width;
2378 attributes.window_type = GDK_WINDOW_CHILD;
2379 attributes.x = widget->allocation.x + border_width;
2380 attributes.y = widget->allocation.y + border_width;
2381 attributes.width = widget->allocation.width - border_width * 2;
2382 attributes.height = widget->allocation.height - border_width * 2;
2383 attributes.wclass = GDK_INPUT_OUTPUT;
2384 attributes.visual = gtk_widget_get_visual (widget);
2385 attributes.colormap = gtk_widget_get_colormap (widget);
2386 attributes.event_mask = gtk_widget_get_events (widget);
2387 attributes.event_mask |= (GDK_EXPOSURE_MASK |
2388 GDK_BUTTON_PRESS_MASK |
2389 GDK_BUTTON_RELEASE_MASK |
2390 GDK_KEY_PRESS_MASK |
2391 GDK_KEY_RELEASE_MASK);
2392 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
2395 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
2396 gdk_window_set_user_data (widget->window, clist);
2398 widget->style = gtk_style_attach (widget->style, widget->window);
2400 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
2402 /* column-title window */
2404 attributes.x = clist->column_title_area.x;
2405 attributes.y = clist->column_title_area.y;
2406 attributes.width = clist->column_title_area.width;
2407 attributes.height = clist->column_title_area.height;
2409 clist->title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2410 gdk_window_set_user_data (clist->title_window, clist);
2412 gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_SELECTED);
2413 gdk_window_show (clist->title_window);
2415 /* set things up so column buttons are drawn in title window */
2416 for (i = 0; i < clist->columns; i++)
2417 if (clist->column[i].button)
2418 gtk_widget_set_parent_window (clist->column[i].button, clist->title_window);
2421 attributes.x = clist->internal_allocation.x + widget->style->klass->xthickness;
2422 attributes.y = clist->internal_allocation.y + widget->style->klass->ythickness +
2423 clist->column_title_area.height;
2424 attributes.width = clist->clist_window_width;
2425 attributes.height = clist->clist_window_height;
2427 clist->clist_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2428 gdk_window_set_user_data (clist->clist_window, clist);
2430 gdk_window_set_background (clist->clist_window, &widget->style->bg[GTK_STATE_PRELIGHT]);
2431 gdk_window_show (clist->clist_window);
2432 gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
2433 &clist->clist_window_height);
2435 /* create resize windows */
2436 attributes.wclass = GDK_INPUT_ONLY;
2437 attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
2438 GDK_BUTTON_RELEASE_MASK |
2439 GDK_POINTER_MOTION_MASK |
2440 GDK_POINTER_MOTION_HINT_MASK |
2441 GDK_KEY_PRESS_MASK);
2442 attributes.cursor = clist->cursor_drag = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
2443 attributes_mask = GDK_WA_CURSOR;
2445 for (i = 0; i < clist->columns; i++)
2447 clist->column[i].window = gdk_window_new (clist->title_window, &attributes, attributes_mask);
2448 gdk_window_set_user_data (clist->column[i].window, clist);
2451 /* This is slightly less efficient than creating them with the
2452 * right size to begin with, but easier
2454 size_allocate_title_buttons (clist);
2457 clist->fg_gc = gdk_gc_new (widget->window);
2458 clist->bg_gc = gdk_gc_new (widget->window);
2460 /* We'll use this gc to do scrolling as well */
2461 gdk_gc_set_exposures (clist->fg_gc, TRUE);
2463 values.foreground = widget->style->white;
2464 values.function = GDK_XOR;
2465 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
2466 clist->xor_gc = gdk_gc_new_with_values (widget->window,
2474 gtk_clist_unrealize (GtkWidget * widget)
2479 g_return_if_fail (widget != NULL);
2480 g_return_if_fail (GTK_IS_CLIST (widget));
2482 clist = GTK_CLIST (widget);
2484 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
2486 gdk_cursor_destroy (clist->cursor_drag);
2487 gdk_gc_destroy (clist->xor_gc);
2488 gdk_gc_destroy (clist->fg_gc);
2489 gdk_gc_destroy (clist->bg_gc);
2491 for (i = 0; i < clist->columns; i++)
2492 if (clist->column[i].window)
2494 gdk_window_set_user_data (clist->column[i].window, NULL);
2495 gdk_window_destroy (clist->column[i].window);
2496 clist->column[i].window = NULL;
2499 gdk_window_set_user_data (clist->clist_window, NULL);
2500 gdk_window_destroy (clist->clist_window);
2501 clist->clist_window = NULL;
2503 gdk_window_set_user_data (clist->title_window, NULL);
2504 gdk_window_destroy (clist->title_window);
2505 clist->title_window = NULL;
2507 clist->cursor_drag = NULL;
2508 clist->xor_gc = NULL;
2509 clist->fg_gc = NULL;
2510 clist->bg_gc = NULL;
2512 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
2513 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
2517 gtk_clist_map (GtkWidget * widget)
2522 g_return_if_fail (widget != NULL);
2523 g_return_if_fail (GTK_IS_CLIST (widget));
2525 clist = GTK_CLIST (widget);
2527 if (!GTK_WIDGET_MAPPED (widget))
2529 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2531 gdk_window_show (widget->window);
2532 gdk_window_show (clist->title_window);
2533 gdk_window_show (clist->clist_window);
2535 /* map column buttons */
2536 for (i = 0; i < clist->columns; i++)
2537 if (clist->column[i].button &&
2538 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
2539 !GTK_WIDGET_MAPPED (clist->column[i].button))
2540 gtk_widget_map (clist->column[i].button);
2542 /* map resize windows AFTER column buttons (above) */
2543 for (i = 0; i < clist->columns; i++)
2544 if (clist->column[i].window && clist->column[i].button)
2545 gdk_window_show (clist->column[i].window);
2547 /* map vscrollbars */
2548 if (GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
2549 !GTK_WIDGET_MAPPED (clist->vscrollbar))
2550 gtk_widget_map (clist->vscrollbar);
2552 if (GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
2553 !GTK_WIDGET_MAPPED (clist->hscrollbar))
2554 gtk_widget_map (clist->hscrollbar);
2556 /* unfreeze the list */
2557 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
2562 gtk_clist_unmap (GtkWidget * widget)
2567 g_return_if_fail (widget != NULL);
2568 g_return_if_fail (GTK_IS_CLIST (widget));
2570 clist = GTK_CLIST (widget);
2572 if (GTK_WIDGET_MAPPED (widget))
2574 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
2576 for (i = 0; i < clist->columns; i++)
2577 if (clist->column[i].window)
2578 gdk_window_hide (clist->column[i].window);
2580 gdk_window_hide (clist->clist_window);
2581 gdk_window_hide (clist->title_window);
2582 gdk_window_hide (widget->window);
2584 /* unmap scrollbars */
2585 if (GTK_WIDGET_MAPPED (clist->vscrollbar))
2586 gtk_widget_unmap (clist->vscrollbar);
2588 if (GTK_WIDGET_MAPPED (clist->hscrollbar))
2589 gtk_widget_unmap (clist->hscrollbar);
2591 /* unmap column buttons */
2592 for (i = 0; i < clist->columns; i++)
2593 if (clist->column[i].button &&
2594 GTK_WIDGET_MAPPED (clist->column[i].button))
2595 gtk_widget_unmap (clist->column[i].button);
2597 /* freeze the list */
2598 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
2603 gtk_clist_draw (GtkWidget * widget,
2604 GdkRectangle * area)
2609 g_return_if_fail (widget != NULL);
2610 g_return_if_fail (GTK_IS_CLIST (widget));
2611 g_return_if_fail (area != NULL);
2613 if (GTK_WIDGET_DRAWABLE (widget))
2615 clist = GTK_CLIST (widget);
2616 border_width = GTK_CONTAINER (widget)->border_width;
2618 gdk_window_clear_area (widget->window,
2619 area->x - border_width,
2620 area->y - border_width,
2621 area->width, area->height);
2623 /* draw list shadow/border */
2624 gtk_draw_shadow (widget->style, widget->window,
2625 GTK_STATE_NORMAL, clist->shadow_type,
2627 clist->clist_window_width + (2 * widget->style->klass->xthickness),
2628 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
2629 clist->column_title_area.height);
2631 gdk_window_clear_area (clist->clist_window,
2634 draw_rows (clist, NULL);
2639 gtk_clist_expose (GtkWidget * widget,
2640 GdkEventExpose * event)
2644 g_return_val_if_fail (widget != NULL, FALSE);
2645 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2646 g_return_val_if_fail (event != NULL, FALSE);
2648 if (GTK_WIDGET_DRAWABLE (widget))
2650 clist = GTK_CLIST (widget);
2653 if (event->window == widget->window)
2654 gtk_draw_shadow (widget->style, widget->window,
2655 GTK_STATE_NORMAL, clist->shadow_type,
2657 clist->clist_window_width + (2 * widget->style->klass->xthickness),
2658 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
2659 clist->column_title_area.height);
2661 /* exposure events on the list */
2662 if (event->window == clist->clist_window)
2663 draw_rows (clist, &event->area);
2670 gtk_clist_button_press (GtkWidget * widget,
2671 GdkEventButton * event)
2680 g_return_val_if_fail (widget != NULL, FALSE);
2681 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2682 g_return_val_if_fail (event != NULL, FALSE);
2684 clist = GTK_CLIST (widget);
2686 /* we don't handle button 2 and 3 */
2687 if (event->button != 1)
2690 /* selections on the list */
2691 if (event->window == clist->clist_window)
2696 if (get_selection_info (clist, x, y, &row, &column))
2698 gint old_row = clist->focus_row;
2699 gboolean no_focus_row = FALSE;
2701 if (clist->focus_row == -1)
2704 no_focus_row = TRUE;
2707 GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION);
2708 gdk_pointer_grab (clist->clist_window, FALSE,
2709 GDK_POINTER_MOTION_HINT_MASK |
2710 GDK_BUTTON1_MOTION_MASK |
2711 GDK_BUTTON_RELEASE_MASK,
2712 NULL, NULL, event->time);
2715 if (GTK_CLIST_ADD_MODE (clist))
2717 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
2718 if (GTK_WIDGET_HAS_FOCUS (widget))
2720 gtk_clist_draw_focus (widget);
2721 gdk_gc_set_line_attributes (clist->xor_gc, 1,
2722 GDK_LINE_SOLID, 0, 0);
2723 clist->focus_row = row;
2724 gtk_clist_draw_focus (widget);
2728 gdk_gc_set_line_attributes (clist->xor_gc, 1,
2729 GDK_LINE_SOLID, 0, 0);
2730 clist->focus_row = row;
2733 else if (row != clist->focus_row)
2735 if (GTK_WIDGET_HAS_FOCUS (widget))
2737 gtk_clist_draw_focus (widget);
2738 clist->focus_row = row;
2739 gtk_clist_draw_focus (widget);
2742 clist->focus_row = row;
2745 if (!GTK_WIDGET_HAS_FOCUS (widget))
2746 gtk_widget_grab_focus (widget);
2748 switch (clist->selection_mode)
2750 case GTK_SELECTION_SINGLE:
2751 case GTK_SELECTION_MULTIPLE:
2752 clist->anchor = row;
2755 case GTK_SELECTION_BROWSE:
2756 if (row != old_row || no_focus_row)
2757 select_row (clist, row, column, (GdkEvent *) event);
2760 case GTK_SELECTION_EXTENDED:
2761 if (event->state & GDK_CONTROL_MASK)
2763 if (event->state & GDK_SHIFT_MASK)
2765 set_anchor (clist, TRUE, old_row, old_row);
2766 update_extended_selection (clist, clist->focus_row);
2770 if (clist->anchor == -1)
2771 set_anchor (clist, TRUE, row, old_row);
2773 update_extended_selection (clist, clist->focus_row);
2777 if (event->state & GDK_SHIFT_MASK)
2779 set_anchor (clist, FALSE, old_row, old_row);
2780 update_extended_selection (clist, clist->focus_row);
2783 if (clist->anchor == -1)
2784 set_anchor (clist, FALSE, row, old_row);
2786 update_extended_selection (clist, clist->focus_row);
2796 /* press on resize windows */
2797 for (i = 0; i < clist->columns; i++)
2798 if (clist->column[i].window && event->window == clist->column[i].window)
2800 GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
2801 gtk_widget_get_pointer (widget, &clist->x_drag, NULL);
2803 gdk_pointer_grab (clist->column[i].window, FALSE,
2804 GDK_POINTER_MOTION_HINT_MASK |
2805 GDK_BUTTON1_MOTION_MASK |
2806 GDK_BUTTON_RELEASE_MASK,
2807 NULL, NULL, event->time);
2809 if (GTK_CLIST_ADD_MODE (clist))
2810 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
2812 draw_xor_line (clist);
2820 gtk_clist_button_release (GtkWidget * widget,
2821 GdkEventButton * event)
2823 gint i, x, width, visible;
2826 g_return_val_if_fail (widget != NULL, FALSE);
2827 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2828 g_return_val_if_fail (event != NULL, FALSE);
2830 clist = GTK_CLIST (widget);
2832 /* we don't handle button 2 and 3 */
2833 if (event->button != 1)
2836 /* release on resize windows */
2837 if (GTK_CLIST_IN_DRAG (clist))
2838 for (i = 0; i < clist->columns; i++)
2839 if (clist->column[i].window && event->window == clist->column[i].window)
2841 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
2842 gtk_widget_get_pointer (widget, &x, NULL);
2843 width = new_column_width (clist, i, &x, &visible);
2844 gdk_pointer_ungrab (event->time);
2847 draw_xor_line (clist);
2849 if (GTK_CLIST_ADD_MODE (clist))
2851 gdk_gc_set_line_attributes (clist->xor_gc, 1,
2852 GDK_LINE_ON_OFF_DASH, 0, 0);
2853 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
2856 resize_column (clist, i, width);
2860 if (GTK_CLIST_DRAG_SELECTION (clist))
2865 GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
2866 gdk_pointer_ungrab (event->time);
2869 gtk_timeout_remove (clist->htimer);
2874 gtk_timeout_remove (clist->vtimer);
2877 switch (clist->selection_mode)
2879 case GTK_SELECTION_EXTENDED:
2880 if (!(event->state & GDK_SHIFT_MASK) ||
2881 event->x < 0 || event->x >= clist->clist_window_width ||
2882 event->y < 0 || event->y >= clist->clist_window_height)
2883 GTK_CLIST_CLASS_FW (clist)->resync_selection
2884 (clist, (GdkEvent *) event);
2887 case GTK_SELECTION_SINGLE:
2888 case GTK_SELECTION_MULTIPLE:
2889 if (get_selection_info (clist, event->x, event->y, &row, &column))
2891 if (clist->anchor == clist->focus_row)
2892 toggle_row (clist, row, column, (GdkEvent *) event);
2906 horizontal_timeout (GtkCList *clist)
2909 GdkEventMotion event;
2910 GdkModifierType mask;
2912 g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
2915 gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
2922 gtk_clist_motion (GTK_WIDGET (clist), &event);
2928 vertical_timeout (GtkCList *clist)
2931 GdkEventMotion event;
2932 GdkModifierType mask;
2934 g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
2937 gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
2944 gtk_clist_motion (GTK_WIDGET (clist), &event);
2950 move_vertical (GtkCList *clist,
2957 adj = GTK_RANGE (clist->vscrollbar)->adjustment;
2959 y = ROW_TOP_YPIXEL (clist, row) - clist->voffset;
2961 y = y - align * (clist->clist_window_height - clist->row_height)
2962 + (2 * align - 1) * CELL_SPACING;
2964 if (y + adj->page_size > adj->upper)
2965 adj->value = adj->upper - adj->page_size;
2969 gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
2973 move_horizontal (GtkCList *clist,
2979 adj = GTK_RANGE (clist->hscrollbar)->adjustment;
2983 upper = adj->upper - adj->page_size;
2984 adj->value = MIN (adj->value, upper);
2985 adj->value = MAX (adj->value, 0.0);
2987 gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
2991 gtk_clist_motion (GtkWidget * widget,
2992 GdkEventMotion * event)
2994 gint i, x, y, visible;
2997 g_return_val_if_fail (widget != NULL, FALSE);
2998 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
3000 clist = GTK_CLIST (widget);
3002 if (GTK_CLIST_IN_DRAG (clist))
3003 for (i = 0; i < clist->columns; i++)
3004 if (clist->column[i].window && event->window == clist->column[i].window)
3006 if (event->is_hint || event->window != widget->window)
3007 gtk_widget_get_pointer (widget, &x, NULL);
3011 new_column_width (clist, i, &x, &visible);
3012 /* Welcome to my hack! I'm going to use a value of x_drage = -99999 to
3013 * indicate the the xor line is already no visible */
3014 if (!visible && clist->x_drag != -99999)
3016 draw_xor_line (clist);
3017 clist->x_drag = -99999;
3020 if (x != clist->x_drag && visible)
3022 if (clist->x_drag != -99999)
3023 draw_xor_line (clist);
3026 draw_xor_line (clist);
3030 if (GTK_CLIST_DRAG_SELECTION (clist))
3034 if (event->is_hint || event->window != clist->clist_window)
3035 gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
3037 /* horizontal autoscrolling */
3038 if (LIST_WIDTH (clist) > clist->clist_window_width &&
3039 (x < 0 || x >= clist->clist_window_width))
3041 if (clist->htimer == 0)
3043 clist->htimer = gtk_timeout_add
3044 (SCROLL_TIME, (GtkFunction) horizontal_timeout, clist);
3046 if (!((x < 0 && GTK_RANGE (clist->hscrollbar)->adjustment->value
3047 == 0) || (x >= clist->clist_window_width &&
3048 GTK_RANGE (clist->hscrollbar)->adjustment->value ==
3049 LIST_WIDTH (clist) - clist->clist_window_width)))
3052 move_horizontal (clist, -1 + (x/2));
3054 move_horizontal (clist,
3055 1 + (x - clist->clist_window_width) / 2);
3062 row = ROW_FROM_YPIXEL (clist, y);
3064 /* don't scroll on last pixel row if it's a cell spacing */
3065 if (y == clist->clist_window_height-1 &&
3066 y == ROW_TOP_YPIXEL (clist, row-1) + clist->row_height)
3069 /* vertical autoscrolling */
3070 if (LIST_HEIGHT (clist) > clist->clist_window_height &&
3071 (y < 0 || y >= clist->clist_window_height))
3073 if (clist->vtimer == 0)
3075 clist->vtimer = gtk_timeout_add (SCROLL_TIME,
3076 (GtkFunction) vertical_timeout,
3079 if ((y < 0 && clist->focus_row == 0) ||
3080 (y >= clist->clist_window_height &&
3081 clist->focus_row == clist->rows-1))
3084 if (row < 0 && clist->focus_row > 0)
3086 gtk_clist_draw_focus (widget);
3087 clist->focus_row = 0;
3088 gtk_clist_draw_focus (widget);
3090 else if (row > clist->rows - 1 && clist->focus_row
3093 gtk_clist_draw_focus (widget);
3094 clist->focus_row = clist->rows - 1;
3095 gtk_clist_draw_focus (widget);
3097 else if (row >= 0 && row <= clist->rows - 1)
3099 gtk_clist_draw_focus (widget);
3100 clist->focus_row = row;
3101 gtk_clist_draw_focus (widget);
3106 switch (clist->selection_mode)
3108 case GTK_SELECTION_BROWSE:
3109 select_row (clist, clist->focus_row, -1, (GdkEvent *) event);
3112 case GTK_SELECTION_EXTENDED:
3113 update_extended_selection (clist, clist->focus_row);
3121 move_vertical (clist, row, 0);
3123 move_vertical (clist, row, 1);
3129 if (row == clist->focus_row)
3132 /* dragging inside clist_window */
3133 if (row < 0 && clist->focus_row > 0)
3135 gtk_clist_draw_focus (widget);
3136 clist->focus_row = 0;
3137 gtk_clist_draw_focus (widget);
3139 else if (row > clist->rows-1 && clist->focus_row < clist->rows-1)
3141 gtk_clist_draw_focus (widget);
3142 clist->focus_row = clist->rows-1;
3143 gtk_clist_draw_focus (widget);
3145 else if (row >= 0 && row <= clist->rows-1)
3147 gtk_clist_draw_focus (widget);
3148 clist->focus_row = row;
3149 gtk_clist_draw_focus (widget);
3154 switch (clist->selection_mode)
3156 case GTK_SELECTION_EXTENDED:
3157 update_extended_selection (clist, clist->focus_row);
3160 case GTK_SELECTION_BROWSE:
3161 select_row (clist, clist->focus_row, -1, (GdkEvent *) event);
3168 if (ROW_TOP_YPIXEL(clist, clist->focus_row) + clist->row_height <= 0)
3169 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
3170 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
3171 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
3172 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) >=
3173 clist->clist_window_height)
3174 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
3175 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
3176 clist->clist_window_height)
3177 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
3183 gtk_clist_size_request (GtkWidget * widget,
3184 GtkRequisition * requisition)
3189 g_return_if_fail (widget != NULL);
3190 g_return_if_fail (GTK_IS_CLIST (widget));
3191 g_return_if_fail (requisition != NULL);
3193 clist = GTK_CLIST (widget);
3195 add_style_data (clist);
3197 requisition->width = 0;
3198 requisition->height = 0;
3200 /* compute the size of the column title (title) area */
3201 clist->column_title_area.height = 0;
3202 if (GTK_CLIST_SHOW_TITLES (clist))
3203 for (i = 0; i < clist->columns; i++)
3204 if (clist->column[i].button)
3206 gtk_widget_size_request (clist->column[i].button, &clist->column[i].button->requisition);
3207 clist->column_title_area.height = MAX (clist->column_title_area.height,
3208 clist->column[i].button->requisition.height);
3210 requisition->height += clist->column_title_area.height;
3212 /* add the vscrollbar space */
3213 if ((clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
3214 GTK_WIDGET_VISIBLE (clist->vscrollbar))
3216 gtk_widget_size_request (clist->vscrollbar, &clist->vscrollbar->requisition);
3218 requisition->width += clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist);
3219 requisition->height = MAX (requisition->height,
3220 clist->vscrollbar->requisition.height);
3223 /* add the hscrollbar space */
3224 if ((clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
3225 GTK_WIDGET_VISIBLE (clist->hscrollbar))
3227 gtk_widget_size_request (clist->hscrollbar, &clist->hscrollbar->requisition);
3229 requisition->height += clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist);
3230 requisition->width = MAX (clist->hscrollbar->requisition.width,
3231 requisition->width -
3232 clist->vscrollbar->requisition.width);
3236 requisition->width += widget->style->klass->xthickness * 2 +
3237 GTK_CONTAINER (widget)->border_width * 2;
3238 requisition->height += widget->style->klass->ythickness * 2 +
3239 GTK_CONTAINER (widget)->border_width * 2;
3243 gtk_clist_size_allocate (GtkWidget * widget,
3244 GtkAllocation * allocation)
3247 GtkAllocation clist_allocation;
3248 GtkAllocation child_allocation;
3249 gint i, vscrollbar_vis, hscrollbar_vis;
3251 g_return_if_fail (widget != NULL);
3252 g_return_if_fail (GTK_IS_CLIST (widget));
3253 g_return_if_fail (allocation != NULL);
3255 clist = GTK_CLIST (widget);
3256 widget->allocation = *allocation;
3258 if (GTK_WIDGET_REALIZED (widget))
3260 gdk_window_move_resize (widget->window,
3261 allocation->x + GTK_CONTAINER (widget)->border_width,
3262 allocation->y + GTK_CONTAINER (widget)->border_width,
3263 allocation->width - GTK_CONTAINER (widget)->border_width * 2,
3264 allocation->height - GTK_CONTAINER (widget)->border_width * 2);
3267 /* use internal allocation structure for all the math
3268 * because it's easier than always subtracting the container
3270 clist->internal_allocation.x = 0;
3271 clist->internal_allocation.y = 0;
3272 clist->internal_allocation.width = MAX (1, allocation->width -
3273 GTK_CONTAINER (widget)->border_width * 2);
3274 clist->internal_allocation.height = MAX (1, allocation->height -
3275 GTK_CONTAINER (widget)->border_width * 2);
3277 /* allocate clist window assuming no scrollbars */
3278 clist_allocation.x = clist->internal_allocation.x + widget->style->klass->xthickness;
3279 clist_allocation.y = clist->internal_allocation.y + widget->style->klass->ythickness +
3280 clist->column_title_area.height;
3281 clist_allocation.width = MAX (1, clist->internal_allocation.width -
3282 (2 * widget->style->klass->xthickness));
3283 clist_allocation.height = MAX (1, clist->internal_allocation.height -
3284 (2 * widget->style->klass->ythickness) -
3285 clist->column_title_area.height);
3288 * here's where we decide to show/not show the scrollbars
3293 for (i = 0; i <= 1; i++)
3295 if (LIST_HEIGHT (clist) <= clist_allocation.height &&
3296 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
3302 if (!vscrollbar_vis)
3305 clist_allocation.width = MAX (1, clist_allocation.width -
3306 (clist->vscrollbar->requisition.width +
3307 SCROLLBAR_SPACING (clist)));
3311 if (LIST_WIDTH (clist) <= clist_allocation.width &&
3312 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
3318 if (!hscrollbar_vis)
3321 clist_allocation.height = MAX (1, clist_allocation.height -
3322 (clist->hscrollbar->requisition.height +
3323 SCROLLBAR_SPACING (clist)));
3328 clist->clist_window_width = clist_allocation.width;
3329 clist->clist_window_height = clist_allocation.height;
3331 if (GTK_WIDGET_REALIZED (widget))
3333 gdk_window_move_resize (clist->clist_window,
3336 clist_allocation.width,
3337 clist_allocation.height);
3340 /* position the window which holds the column title buttons */
3341 clist->column_title_area.x = widget->style->klass->xthickness;
3342 clist->column_title_area.y = widget->style->klass->ythickness;
3343 clist->column_title_area.width = clist_allocation.width;
3345 if (GTK_WIDGET_REALIZED (widget))
3347 gdk_window_move_resize (clist->title_window,
3348 clist->column_title_area.x,
3349 clist->column_title_area.y,
3350 clist->column_title_area.width,
3351 clist->column_title_area.height);
3354 /* column button allocation */
3355 size_allocate_columns (clist);
3357 if (GTK_WIDGET_REALIZED (widget))
3358 size_allocate_title_buttons (clist);
3360 adjust_scrollbars (clist);
3362 /* allocate the vscrollbar */
3365 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
3366 gtk_widget_show (clist->vscrollbar);
3368 child_allocation.x = clist->internal_allocation.x +
3369 clist->internal_allocation.width -
3370 clist->vscrollbar->requisition.width;
3371 child_allocation.y = clist->internal_allocation.y;
3372 child_allocation.width = clist->vscrollbar->requisition.width;
3373 child_allocation.height = MAX (1, clist->internal_allocation.height -
3374 (hscrollbar_vis ? (clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist)) : 0));
3376 gtk_widget_size_allocate (clist->vscrollbar, &child_allocation);
3380 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
3381 gtk_widget_hide (clist->vscrollbar);
3386 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
3387 gtk_widget_show (clist->hscrollbar);
3389 child_allocation.x = clist->internal_allocation.x;
3390 child_allocation.y = clist->internal_allocation.y +
3391 clist->internal_allocation.height -
3392 clist->hscrollbar->requisition.height;
3393 child_allocation.width = MAX (1, clist->internal_allocation.width -
3394 (vscrollbar_vis ? (clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist)) : 0));
3395 child_allocation.height = clist->hscrollbar->requisition.height;
3397 gtk_widget_size_allocate (clist->hscrollbar, &child_allocation);
3401 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
3402 gtk_widget_hide (clist->hscrollbar);
3405 /* set the vscrollbar adjustments */
3406 adjust_scrollbars (clist);
3414 gtk_clist_foreach (GtkContainer * container,
3415 GtkCallback callback,
3416 gpointer callback_data)
3421 g_return_if_fail (container != NULL);
3422 g_return_if_fail (GTK_IS_CLIST (container));
3423 g_return_if_fail (callback != NULL);
3425 clist = GTK_CLIST (container);
3427 /* callback for the column buttons */
3428 for (i = 0; i < clist->columns; i++)
3429 if (clist->column[i].button)
3430 (*callback) (clist->column[i].button, callback_data);
3432 /* callbacks for the scrollbars */
3433 if (clist->vscrollbar)
3434 (*callback) (clist->vscrollbar, callback_data);
3435 if (clist->hscrollbar)
3436 (*callback) (clist->hscrollbar, callback_data);
3445 draw_row (GtkCList * clist,
3446 GdkRectangle * area,
3448 GtkCListRow * clist_row)
3451 GdkGC *fg_gc, *bg_gc;
3452 GdkRectangle row_rectangle, cell_rectangle, clip_rectangle, intersect_rectangle,
3454 gint i, offset = 0, width, height, pixmap_width = 0;
3455 gint xsrc, ysrc, xdest, ydest;
3457 g_return_if_fail (clist != NULL);
3459 /* bail now if we arn't drawable yet */
3460 if (!GTK_WIDGET_DRAWABLE (clist))
3463 if (row < 0 || row >= clist->rows)
3466 widget = GTK_WIDGET (clist);
3468 /* if the function is passed the pointer to the row instead of null,
3469 * it avoids this expensive lookup */
3471 clist_row = (g_list_nth (clist->row_list, row))->data;
3473 /* rectangle of the entire row */
3474 row_rectangle.x = 0;
3475 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
3476 row_rectangle.width = clist->clist_window_width;
3477 row_rectangle.height = clist->row_height;
3479 /* rectangle of the cell spacing above the row */
3480 cell_rectangle.x = 0;
3481 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
3482 cell_rectangle.width = row_rectangle.width;
3483 cell_rectangle.height = CELL_SPACING;
3485 /* rectangle used to clip drawing operations, it's y and height
3486 * positions only need to be set once, so we set them once here.
3487 * the x and width are set withing the drawing loop below once per
3489 clip_rectangle.y = row_rectangle.y;
3490 clip_rectangle.height = row_rectangle.height;
3492 /* select GC for background rectangle */
3493 if (clist_row->state == GTK_STATE_SELECTED)
3495 fg_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
3496 bg_gc = widget->style->bg_gc[GTK_STATE_SELECTED];
3500 if (clist_row->fg_set)
3502 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
3503 fg_gc = clist->fg_gc;
3506 fg_gc = widget->style->fg_gc[GTK_STATE_NORMAL];
3508 if (clist_row->bg_set)
3510 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
3511 bg_gc = clist->bg_gc;
3514 bg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
3517 /* draw the cell borders and background */
3520 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
3521 gdk_draw_rectangle (clist->clist_window,
3522 widget->style->base_gc[GTK_STATE_NORMAL],
3524 intersect_rectangle.x,
3525 intersect_rectangle.y,
3526 intersect_rectangle.width,
3527 intersect_rectangle.height);
3529 /* the last row has to clear it's bottom cell spacing too */
3530 if (clist_row == clist->row_list_end->data)
3532 cell_rectangle.y += clist->row_height + CELL_SPACING;
3534 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
3535 gdk_draw_rectangle (clist->clist_window,
3536 widget->style->base_gc[GTK_STATE_NORMAL],
3538 intersect_rectangle.x,
3539 intersect_rectangle.y,
3540 intersect_rectangle.width,
3541 intersect_rectangle.height);
3544 if (!gdk_rectangle_intersect (area, &row_rectangle, &intersect_rectangle))
3547 if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
3548 gdk_draw_rectangle (clist->clist_window,
3551 intersect_rectangle.x,
3552 intersect_rectangle.y,
3553 intersect_rectangle.width,
3554 intersect_rectangle.height);
3556 gdk_window_clear_area (clist->clist_window,
3557 intersect_rectangle.x,
3558 intersect_rectangle.y,
3559 intersect_rectangle.width,
3560 intersect_rectangle.height);
3564 gdk_draw_rectangle (clist->clist_window,
3565 widget->style->base_gc[GTK_STATE_NORMAL],
3569 cell_rectangle.width,
3570 cell_rectangle.height);
3572 /* the last row has to clear it's bottom cell spacing too */
3573 if (clist_row == clist->row_list_end->data)
3575 cell_rectangle.y += clist->row_height + CELL_SPACING;
3577 gdk_draw_rectangle (clist->clist_window,
3578 widget->style->base_gc[GTK_STATE_NORMAL],
3582 cell_rectangle.width,
3583 cell_rectangle.height);
3586 if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
3587 gdk_draw_rectangle (clist->clist_window,
3592 row_rectangle.width,
3593 row_rectangle.height);
3595 gdk_window_clear_area (clist->clist_window,
3598 row_rectangle.width,
3599 row_rectangle.height);
3602 /* iterate and draw all the columns (row cells) and draw their contents */
3603 for (i = 0; i < clist->columns; i++)
3605 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
3606 clip_rectangle.width = clist->column[i].area.width;
3608 /* calculate clipping region clipping region */
3611 rect = &clip_rectangle;
3615 if (!gdk_rectangle_intersect (area, &clip_rectangle,
3616 &intersect_rectangle))
3618 rect = &intersect_rectangle;
3621 /* calculate real width for column justification */
3622 switch (clist_row->cell[i].type)
3624 case GTK_CELL_EMPTY:
3629 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
3630 GTK_CELL_TEXT (clist_row->cell[i])->text);
3633 case GTK_CELL_PIXMAP:
3634 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &width, &height);
3635 pixmap_width = width;
3638 case GTK_CELL_PIXTEXT:
3639 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap, &width, &height);
3640 pixmap_width = width;
3641 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
3642 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
3643 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
3646 case GTK_CELL_WIDGET:
3656 switch (clist->column[i].justification)
3658 case GTK_JUSTIFY_LEFT:
3659 offset = clip_rectangle.x;
3662 case GTK_JUSTIFY_RIGHT:
3663 offset = (clip_rectangle.x + clip_rectangle.width) - width;
3666 case GTK_JUSTIFY_CENTER:
3667 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
3670 case GTK_JUSTIFY_FILL:
3671 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
3679 /* Draw Text or Pixmap */
3680 switch (clist_row->cell[i].type)
3682 case GTK_CELL_EMPTY:
3687 gdk_gc_set_clip_rectangle (fg_gc, rect);
3689 gdk_draw_string (clist->clist_window,
3690 widget->style->font,
3692 offset + clist_row->cell[i].horizontal,
3693 row_rectangle.y + clist->row_center_offset +
3694 clist_row->cell[i].vertical,
3695 GTK_CELL_TEXT (clist_row->cell[i])->text);
3697 gdk_gc_set_clip_rectangle (fg_gc, NULL);
3700 case GTK_CELL_PIXMAP:
3703 xdest = offset + clist_row->cell[i].horizontal;
3704 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
3705 clist_row->cell[i].vertical;
3707 if (xdest < clip_rectangle.x)
3709 xsrc = clip_rectangle.x - xdest;
3710 pixmap_width -= xsrc;
3711 xdest = clip_rectangle.x;
3714 if (xdest + pixmap_width > clip_rectangle.x + clip_rectangle.width)
3715 pixmap_width = (clip_rectangle.x + clip_rectangle.width) - xdest;
3717 if (ydest < clip_rectangle.y)
3719 ysrc = clip_rectangle.y - ydest;
3721 ydest = clip_rectangle.y;
3724 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
3725 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
3727 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
3729 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXMAP (clist_row->cell[i])->mask);
3730 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
3732 gdk_draw_pixmap (clist->clist_window,
3734 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
3737 pixmap_width, height);
3739 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
3741 gdk_gc_set_clip_origin (fg_gc, 0, 0);
3742 gdk_gc_set_clip_mask (fg_gc, NULL);
3746 case GTK_CELL_PIXTEXT:
3747 /* draw the pixmap */
3750 xdest = offset + clist_row->cell[i].horizontal;
3751 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
3752 clist_row->cell[i].vertical;
3754 if (xdest < clip_rectangle.x)
3756 xsrc = clip_rectangle.x - xdest;
3757 pixmap_width -= xsrc;
3758 xdest = clip_rectangle.x;
3761 if (xdest + pixmap_width > clip_rectangle.x + clip_rectangle.width)
3762 pixmap_width = (clip_rectangle.x + clip_rectangle.width) - xdest;
3764 if (ydest < clip_rectangle.y)
3766 ysrc = clip_rectangle.y - ydest;
3768 ydest = clip_rectangle.y;
3771 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
3772 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
3774 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask)
3776 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
3777 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
3780 gdk_draw_pixmap (clist->clist_window,
3782 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
3786 pixmap_width, height);
3788 gdk_gc_set_clip_origin (fg_gc, 0, 0);
3790 offset += pixmap_width + GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
3792 /* draw the string */
3793 gdk_gc_set_clip_rectangle (fg_gc, rect);
3795 gdk_draw_string (clist->clist_window,
3796 widget->style->font,
3798 offset + clist_row->cell[i].horizontal,
3799 row_rectangle.y + clist->row_center_offset +
3800 clist_row->cell[i].vertical,
3801 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
3803 gdk_gc_set_clip_rectangle (fg_gc, NULL);
3806 case GTK_CELL_WIDGET:
3816 if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget))
3820 if (gdk_rectangle_intersect (area, &row_rectangle,
3821 &intersect_rectangle))
3823 gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
3824 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
3825 row_rectangle.x, row_rectangle.y,
3826 row_rectangle.width - 1,
3827 row_rectangle.height - 1);
3828 gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
3832 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
3833 row_rectangle.x, row_rectangle.y,
3834 row_rectangle.width - 1, row_rectangle.height - 1);
3839 draw_rows (GtkCList * clist,
3840 GdkRectangle * area)
3843 GtkCListRow *clist_row;
3844 int i, first_row, last_row;
3846 g_return_if_fail (clist != NULL);
3847 g_return_if_fail (GTK_IS_CLIST (clist));
3849 if (clist->row_height == 0 ||
3850 !GTK_WIDGET_DRAWABLE (clist))
3855 first_row = ROW_FROM_YPIXEL (clist, area->y);
3856 last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
3860 first_row = ROW_FROM_YPIXEL (clist, 0);
3861 last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
3864 /* this is a small special case which exposes the bottom cell line
3865 * on the last row -- it might go away if I change the wall the cell spacings
3867 if (clist->rows == first_row)
3870 list = g_list_nth (clist->row_list, first_row);
3874 clist_row = list->data;
3880 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, area, i, clist_row);
3885 gdk_window_clear_area (clist->clist_window, 0, ROW_TOP_YPIXEL (clist, i), -1, -1);
3890 * size_allocate_title_buttons
3891 * size_allocate_columns
3894 size_allocate_title_buttons (GtkCList * clist)
3896 gint i, last_button = 0;
3897 GtkAllocation button_allocation;
3899 if (!GTK_WIDGET_REALIZED (clist))
3902 button_allocation.x = clist->hoffset;
3903 button_allocation.y = 0;
3904 button_allocation.width = 0;
3905 button_allocation.height = clist->column_title_area.height;
3907 for (i = 0; i < clist->columns; i++)
3909 button_allocation.width += clist->column[i].area.width;
3911 if (i == clist->columns - 1)
3912 button_allocation.width += 2 * (CELL_SPACING + COLUMN_INSET);
3914 button_allocation.width += CELL_SPACING + (2 * COLUMN_INSET);
3916 if (i == (clist->columns - 1) || clist->column[i + 1].button)
3918 gtk_widget_size_allocate (clist->column[last_button].button, &button_allocation);
3919 button_allocation.x += button_allocation.width;
3920 button_allocation.width = 0;
3922 gdk_window_show (clist->column[last_button].window);
3923 gdk_window_move_resize (clist->column[last_button].window,
3924 button_allocation.x - (DRAG_WIDTH / 2),
3925 0, DRAG_WIDTH, clist->column_title_area.height);
3927 last_button = i + 1;
3931 gdk_window_hide (clist->column[i].window);
3937 size_allocate_columns (GtkCList * clist)
3939 gint i, xoffset = 0;
3941 for (i = 0; i < clist->columns; i++)
3943 clist->column[i].area.x = xoffset + CELL_SPACING + COLUMN_INSET;
3945 if (i == clist->columns - 1)
3949 if (clist->column[i].width_set)
3951 width = clist->column[i].width;
3955 if (clist->column[i].title)
3956 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
3957 clist->column[i].title);
3962 clist->column[i].area.width = MAX (width,
3963 clist->clist_window_width -
3964 xoffset - (2 * (CELL_SPACING + COLUMN_INSET)));
3969 clist->column[i].area.width = clist->column[i].width;
3972 xoffset += clist->column[i].area.width + CELL_SPACING + (2 * COLUMN_INSET);
3981 * get_selection_info
3984 toggle_row (GtkCList * clist,
3989 GtkCListRow *clist_row;
3991 switch (clist->selection_mode)
3993 case GTK_SELECTION_EXTENDED:
3994 case GTK_SELECTION_MULTIPLE:
3995 case GTK_SELECTION_SINGLE:
3997 clist_row = g_list_nth (clist->row_list, row)->data;
3998 if (clist_row->state == GTK_STATE_SELECTED)
4000 unselect_row (clist, row, column, event);
4004 case GTK_SELECTION_BROWSE:
4005 select_row (clist, row, column, event);
4011 select_row (GtkCList * clist,
4016 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
4017 row, column, event);
4021 unselect_row (GtkCList * clist,
4026 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
4027 row, column, event);
4031 real_select_row (GtkCList * clist,
4036 GtkCListRow *clist_row;
4039 gboolean row_selected;
4041 g_return_if_fail (clist != NULL);
4042 g_return_if_fail (GTK_IS_CLIST (clist));
4044 if (row < 0 || row > (clist->rows - 1))
4047 switch (clist->selection_mode)
4049 case GTK_SELECTION_SINGLE:
4050 case GTK_SELECTION_BROWSE:
4052 row_selected = FALSE;
4053 list = clist->selection;
4057 sel_row = GPOINTER_TO_INT (list->data);
4061 row_selected = TRUE;
4063 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
4064 sel_row, column, event);
4074 clist_row = (g_list_nth (clist->row_list, row))->data;
4076 if (clist_row->state != GTK_STATE_NORMAL)
4079 clist_row->state = GTK_STATE_SELECTED;
4080 if (!clist->selection)
4082 clist->selection = g_list_append (clist->selection,
4083 GINT_TO_POINTER (row));
4084 clist->selection_end = clist->selection;
4087 clist->selection_end =
4088 g_list_append (clist->selection_end, GINT_TO_POINTER (row))->next;
4090 if (!GTK_CLIST_FROZEN (clist)
4091 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
4092 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
4096 real_unselect_row (GtkCList * clist,
4101 GtkCListRow *clist_row;
4103 g_return_if_fail (clist != NULL);
4104 g_return_if_fail (GTK_IS_CLIST (clist));
4106 if (row < 0 || row > (clist->rows - 1))
4109 clist_row = (g_list_nth (clist->row_list, row))->data;
4111 if (clist_row->state == GTK_STATE_SELECTED)
4113 clist_row->state = GTK_STATE_NORMAL;
4115 if (clist->selection_end &&
4116 clist->selection_end->data == GINT_TO_POINTER (row))
4117 clist->selection_end = clist->selection_end->prev;
4119 clist->selection = g_list_remove (clist->selection,
4120 GINT_TO_POINTER (row));
4122 if (!GTK_CLIST_FROZEN (clist)
4123 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
4124 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
4129 get_selection_info (GtkCList * clist,
4137 g_return_val_if_fail (clist != NULL, 0);
4138 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
4140 /* bounds checking, return false if the user clicked
4141 * on a blank area */
4142 trow = ROW_FROM_YPIXEL (clist, y);
4143 if (trow >= clist->rows)
4149 tcol = COLUMN_FROM_XPIXEL (clist, x);
4150 if (tcol >= clist->columns)
4160 gtk_clist_get_selection_info (GtkCList *clist,
4166 g_return_val_if_fail (clist != NULL, 0);
4167 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
4168 return get_selection_info (clist, x, y, row, column);
4178 draw_xor_line (GtkCList * clist)
4182 g_return_if_fail (clist != NULL);
4184 widget = GTK_WIDGET (clist);
4186 gdk_draw_line (widget->window, clist->xor_gc,
4188 widget->style->klass->ythickness,
4190 clist->column_title_area.height + clist->clist_window_height + 1);
4193 /* this function returns the new width of the column being resized given
4194 * the column and x position of the cursor; the x cursor position is passed
4195 * in as a pointer and automagicly corrected if it's beyond min/max limits */
4197 new_column_width (GtkCList * clist,
4206 /* first translate the x position from widget->window
4207 * to clist->clist_window */
4208 cx -= GTK_WIDGET (clist)->style->klass->xthickness;
4210 /* rx is x from the list beginning */
4211 rx = cx - clist->hoffset;
4213 /* you can't shrink a column to less than its minimum width */
4214 if (cx < (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH))
4216 *x = cx = COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH +
4217 GTK_WIDGET (clist)->style->klass->xthickness;
4218 cx -= GTK_WIDGET (clist)->style->klass->xthickness;
4219 rx = cx - clist->hoffset;
4222 if (cx > clist->clist_window_width)
4227 /* calculate new column width making sure it doesn't end up
4228 * less than the minimum width */
4229 width = (rx - COLUMN_LEFT (clist, column)) - COLUMN_INSET -
4230 ((clist->columns == (column - 1)) ? CELL_SPACING : 0);
4231 if (width < COLUMN_MIN_WIDTH)
4232 width = COLUMN_MIN_WIDTH;
4237 /* this will do more later */
4239 resize_column (GtkCList * clist,
4243 gtk_clist_set_column_width (clist, column, width);
4248 column_button_create (GtkCList * clist,
4253 button = clist->column[column].button = gtk_button_new ();
4254 gtk_widget_set_parent (button, GTK_WIDGET (clist));
4255 if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
4256 gtk_widget_set_parent_window (clist->column[column].button, clist->title_window);
4258 gtk_signal_connect (GTK_OBJECT (button), "clicked",
4259 (GtkSignalFunc) column_button_clicked,
4262 gtk_widget_show (button);
4266 column_button_clicked (GtkWidget * widget,
4272 g_return_if_fail (widget != NULL);
4273 g_return_if_fail (GTK_IS_CLIST (data));
4275 clist = GTK_CLIST (data);
4277 /* find the column who's button was pressed */
4278 for (i = 0; i < clist->columns; i++)
4279 if (clist->column[i].button == widget)
4282 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
4291 * vadjustment_changed
4292 * hadjustment_changed
4293 * vadjustment_value_changed
4294 * hadjustment_value_changed
4297 create_scrollbars (GtkCList * clist)
4299 GtkAdjustment *adjustment;
4301 clist->vscrollbar = gtk_vscrollbar_new (NULL);
4303 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
4305 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
4306 (GtkSignalFunc) vadjustment_changed,
4309 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
4310 (GtkSignalFunc) vadjustment_value_changed,
4313 gtk_widget_set_parent (clist->vscrollbar, GTK_WIDGET (clist));
4314 gtk_widget_show (clist->vscrollbar);
4316 clist->hscrollbar = gtk_hscrollbar_new (NULL);
4318 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
4320 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
4321 (GtkSignalFunc) hadjustment_changed,
4324 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
4325 (GtkSignalFunc) hadjustment_value_changed,
4328 gtk_widget_set_parent (clist->hscrollbar, GTK_WIDGET (clist));
4329 gtk_widget_show (clist->hscrollbar);
4333 adjust_scrollbars (GtkCList * clist)
4335 GTK_RANGE (clist->vscrollbar)->adjustment->page_size = clist->clist_window_height;
4336 GTK_RANGE (clist->vscrollbar)->adjustment->page_increment = clist->clist_window_height / 2;
4337 GTK_RANGE (clist->vscrollbar)->adjustment->step_increment = 10;
4338 GTK_RANGE (clist->vscrollbar)->adjustment->lower = 0;
4339 GTK_RANGE (clist->vscrollbar)->adjustment->upper = LIST_HEIGHT (clist);
4341 if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
4343 GTK_RANGE (clist->vscrollbar)->adjustment->value = MAX (0, LIST_HEIGHT (clist) -
4344 clist->clist_window_height);
4345 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
4349 GTK_RANGE (clist->hscrollbar)->adjustment->page_size = clist->clist_window_width;
4350 GTK_RANGE (clist->hscrollbar)->adjustment->page_increment = clist->clist_window_width / 2;
4351 GTK_RANGE (clist->hscrollbar)->adjustment->step_increment = 10;
4352 GTK_RANGE (clist->hscrollbar)->adjustment->lower = 0;
4353 GTK_RANGE (clist->hscrollbar)->adjustment->upper = LIST_WIDTH (clist);
4355 if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
4357 GTK_RANGE (clist->hscrollbar)->adjustment->value = MAX (0, LIST_WIDTH (clist) -
4358 clist->clist_window_width);
4359 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
4363 if (LIST_HEIGHT (clist) <= clist->clist_window_height &&
4364 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
4366 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
4368 gtk_widget_hide (clist->vscrollbar);
4369 gtk_widget_queue_resize (GTK_WIDGET (clist));
4374 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
4376 gtk_widget_show (clist->vscrollbar);
4377 gtk_widget_queue_resize (GTK_WIDGET (clist));
4381 if (LIST_WIDTH (clist) <= clist->clist_window_width &&
4382 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
4384 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
4386 gtk_widget_hide (clist->hscrollbar);
4387 gtk_widget_queue_resize (GTK_WIDGET (clist));
4392 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
4394 gtk_widget_show (clist->hscrollbar);
4395 gtk_widget_queue_resize (GTK_WIDGET (clist));
4399 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
4400 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment), "changed");
4404 vadjustment_changed (GtkAdjustment * adjustment,
4409 g_return_if_fail (adjustment != NULL);
4410 g_return_if_fail (data != NULL);
4412 clist = GTK_CLIST (data);
4416 hadjustment_changed (GtkAdjustment * adjustment,
4421 g_return_if_fail (adjustment != NULL);
4422 g_return_if_fail (data != NULL);
4424 clist = GTK_CLIST (data);
4428 check_exposures (GtkCList *clist)
4432 if (!GTK_WIDGET_REALIZED (clist))
4435 /* Make sure graphics expose events are processed before scrolling
4437 while ((event = gdk_event_get_graphics_expose (clist->clist_window)) != NULL)
4439 gtk_widget_event (GTK_WIDGET (clist), event);
4440 if (event->expose.count == 0)
4442 gdk_event_free (event);
4445 gdk_event_free (event);
4450 vadjustment_value_changed (GtkAdjustment * adjustment,
4457 g_return_if_fail (adjustment != NULL);
4458 g_return_if_fail (data != NULL);
4459 g_return_if_fail (GTK_IS_CLIST (data));
4461 clist = GTK_CLIST (data);
4463 if (!GTK_WIDGET_DRAWABLE (clist))
4466 value = adjustment->value;
4468 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar)))
4470 if (value > -clist->voffset)
4473 diff = value + clist->voffset;
4475 /* we have to re-draw the whole screen here... */
4476 if (diff >= clist->clist_window_height)
4478 clist->voffset = -value;
4479 draw_rows (clist, NULL);
4483 if ((diff != 0) && (diff != clist->clist_window_height))
4484 gdk_window_copy_area (clist->clist_window,
4487 clist->clist_window,
4490 clist->clist_window_width,
4491 clist->clist_window_height - diff);
4494 area.y = clist->clist_window_height - diff;
4495 area.width = clist->clist_window_width;
4501 diff = -clist->voffset - value;
4503 /* we have to re-draw the whole screen here... */
4504 if (diff >= clist->clist_window_height)
4506 clist->voffset = -value;
4507 draw_rows (clist, NULL);
4511 if ((diff != 0) && (diff != clist->clist_window_height))
4512 gdk_window_copy_area (clist->clist_window,
4515 clist->clist_window,
4518 clist->clist_window_width,
4519 clist->clist_window_height - diff);
4523 area.width = clist->clist_window_width;
4528 clist->voffset = -value;
4529 if ((diff != 0) && (diff != clist->clist_window_height))
4530 check_exposures (clist);
4533 draw_rows (clist, &area);
4537 hadjustment_value_changed (GtkAdjustment * adjustment,
4547 g_return_if_fail (adjustment != NULL);
4548 g_return_if_fail (data != NULL);
4549 g_return_if_fail (GTK_IS_CLIST (data));
4551 clist = GTK_CLIST (data);
4553 if (!GTK_WIDGET_DRAWABLE (clist) ||
4554 adjustment != gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar)))
4557 value = adjustment->value;
4559 /* move the column buttons and resize windows */
4560 for (i = 0; i < clist->columns; i++)
4562 if (clist->column[i].button)
4564 clist->column[i].button->allocation.x -= value + clist->hoffset;
4566 if (clist->column[i].button->window)
4568 gdk_window_move (clist->column[i].button->window,
4569 clist->column[i].button->allocation.x,
4570 clist->column[i].button->allocation.y);
4572 if (clist->column[i].window)
4573 gdk_window_move (clist->column[i].window,
4574 clist->column[i].button->allocation.x +
4575 clist->column[i].button->allocation.width -
4576 (DRAG_WIDTH / 2), 0);
4581 if (value > -clist->hoffset)
4584 diff = value + clist->hoffset;
4586 clist->hoffset = -value;
4588 /* we have to re-draw the whole screen here... */
4589 if (diff >= clist->clist_window_width)
4591 draw_rows (clist, NULL);
4595 if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
4596 GTK_CLIST_ADD_MODE (clist))
4598 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
4600 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
4601 clist->clist_window_width - 1,
4602 clist->row_height - 1);
4604 gdk_window_copy_area (clist->clist_window,
4607 clist->clist_window,
4610 clist->clist_window_width - diff,
4611 clist->clist_window_height);
4613 area.x = clist->clist_window_width - diff;
4618 if (!(diff = -clist->hoffset - value))
4621 clist->hoffset = -value;
4623 /* we have to re-draw the whole screen here... */
4624 if (diff >= clist->clist_window_width)
4626 draw_rows (clist, NULL);
4630 if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
4631 GTK_CLIST_ADD_MODE (clist))
4633 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
4635 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
4636 clist->clist_window_width - 1,
4637 clist->row_height - 1);
4640 gdk_window_copy_area (clist->clist_window,
4643 clist->clist_window,
4646 clist->clist_window_width - diff,
4647 clist->clist_window_height);
4654 area.height = clist->clist_window_height;
4656 check_exposures (clist);
4658 if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist))
4660 if (GTK_CLIST_ADD_MODE (clist))
4664 focus_row = clist->focus_row;
4665 clist->focus_row = -1;
4666 draw_rows (clist, &area);
4667 clist->focus_row = focus_row;
4669 gdk_draw_rectangle (clist->clist_window, clist->xor_gc,
4670 FALSE, 0, y, clist->clist_window_width - 1,
4671 clist->row_height - 1);
4681 x0 = clist->clist_window_width - 1;
4690 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
4691 gdk_draw_line (clist->clist_window, clist->xor_gc,
4692 x0, y + 1, x0, y + clist->row_height - 2);
4693 gdk_draw_line (clist->clist_window, clist->xor_gc,
4694 x1, y + 1, x1, y + clist->row_height - 2);
4698 draw_rows (clist, &area);
4702 * Memory Allocation/Distruction Routines for GtkCList stuctures
4714 static GtkCListColumn *
4715 columns_new (GtkCList * clist)
4718 GtkCListColumn *column;
4720 column = g_new (GtkCListColumn, clist->columns);
4722 for (i = 0; i < clist->columns; i++)
4724 column[i].area.x = 0;
4725 column[i].area.y = 0;
4726 column[i].area.width = 0;
4727 column[i].area.height = 0;
4728 column[i].title = NULL;
4729 column[i].button = NULL;
4730 column[i].window = NULL;
4731 column[i].width = 0;
4732 column[i].width_set = FALSE;
4733 column[i].justification = GTK_JUSTIFY_LEFT;
4740 column_title_new (GtkCList * clist,
4744 if (clist->column[column].title)
4745 g_free (clist->column[column].title);
4747 clist->column[column].title = g_strdup (title);
4751 columns_delete (GtkCList * clist)
4755 for (i = 0; i < clist->columns; i++)
4756 if (clist->column[i].title)
4757 g_free (clist->column[i].title);
4759 g_free (clist->column);
4762 static GtkCListRow *
4763 row_new (GtkCList * clist)
4766 GtkCListRow *clist_row;
4768 clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
4769 clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
4771 for (i = 0; i < clist->columns; i++)
4773 clist_row->cell[i].type = GTK_CELL_EMPTY;
4774 clist_row->cell[i].vertical = 0;
4775 clist_row->cell[i].horizontal = 0;
4778 clist_row->fg_set = FALSE;
4779 clist_row->bg_set = FALSE;
4780 clist_row->state = GTK_STATE_NORMAL;
4781 clist_row->data = NULL;
4782 clist_row->destroy = NULL;
4788 row_delete (GtkCList * clist,
4789 GtkCListRow * clist_row)
4793 for (i = 0; i < clist->columns; i++)
4794 cell_empty (clist, clist_row, i);
4796 if (clist_row->destroy)
4797 clist_row->destroy (clist_row->data);
4799 g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
4800 g_mem_chunk_free (clist->row_mem_chunk, clist_row);
4804 cell_empty (GtkCList * clist,
4805 GtkCListRow * clist_row,
4808 switch (clist_row->cell[column].type)
4810 case GTK_CELL_EMPTY:
4814 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
4817 case GTK_CELL_PIXMAP:
4818 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
4819 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
4820 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
4823 case GTK_CELL_PIXTEXT:
4824 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
4825 gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
4826 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
4827 gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
4830 case GTK_CELL_WIDGET:
4838 clist_row->cell[column].type = GTK_CELL_EMPTY;
4842 cell_set_text (GtkCList * clist,
4843 GtkCListRow * clist_row,
4847 cell_empty (clist, clist_row, column);
4851 clist_row->cell[column].type = GTK_CELL_TEXT;
4852 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
4857 cell_set_pixmap (GtkCList * clist,
4858 GtkCListRow * clist_row,
4863 cell_empty (clist, clist_row, column);
4867 clist_row->cell[column].type = GTK_CELL_PIXMAP;
4868 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
4869 /* We set the mask even if it is NULL */
4870 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
4875 cell_set_pixtext (GtkCList * clist,
4876 GtkCListRow * clist_row,
4883 cell_empty (clist, clist_row, column);
4887 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
4888 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
4889 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
4890 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
4891 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
4895 /* Fill in data after widget has correct style */
4898 add_style_data (GtkCList * clist)
4902 widget = GTK_WIDGET(clist);
4904 /* text properties */
4905 if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
4907 clist->row_height = widget->style->font->ascent + widget->style->font->descent + 1;
4908 clist->row_center_offset = widget->style->font->ascent + 1.5;
4913 text_height = clist->row_height - (GTK_WIDGET (clist)->style->font->ascent +
4914 GTK_WIDGET (clist) ->style->font->descent + 1);
4915 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
4922 /* focus functions */
4925 gtk_clist_draw_focus (GtkWidget *widget)
4929 g_return_if_fail (widget != NULL);
4930 g_return_if_fail (GTK_IS_CLIST (widget));
4932 if (!GTK_WIDGET_DRAWABLE (widget))
4935 clist = GTK_CLIST (widget);
4936 if (clist->focus_row >= 0)
4937 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
4938 0, ROW_TOP_YPIXEL(clist, clist->focus_row),
4939 clist->clist_window_width - 1,
4940 clist->row_height - 1);
4944 gtk_clist_set_focus_child (GtkContainer *container,
4947 g_return_if_fail (container != NULL);
4948 g_return_if_fail (GTK_IS_CLIST (container));
4952 g_return_if_fail (GTK_IS_WIDGET (child));
4953 GTK_CLIST_SET_FLAG (GTK_CLIST (container), CLIST_CHILD_HAS_FOCUS);
4956 parent_class->set_focus_child (container, child);
4960 gtk_clist_focus_in (GtkWidget *widget,
4961 GdkEventFocus *event)
4965 g_return_val_if_fail (widget != NULL, FALSE);
4966 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
4967 g_return_val_if_fail (event != NULL, FALSE);
4969 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4970 GTK_CLIST_UNSET_FLAG (widget, CLIST_CHILD_HAS_FOCUS);
4972 clist = GTK_CLIST (widget);
4974 if (clist->selection_mode == GTK_SELECTION_BROWSE &&
4975 clist->selection == NULL && clist->focus_row > -1)
4976 select_row (clist, clist->focus_row, -1, (GdkEvent *) event);
4978 gtk_widget_draw_focus (widget);
4984 gtk_clist_focus_out (GtkWidget *widget,
4985 GdkEventFocus *event)
4987 g_return_val_if_fail (widget != NULL, FALSE);
4988 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
4989 g_return_val_if_fail (event != NULL, FALSE);
4991 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4992 gtk_widget_draw_focus (widget);
4994 if (GTK_CLIST (widget)->anchor != -1)
4995 GTK_CLIST_CLASS_FW (widget)->resync_selection
4996 (GTK_CLIST (widget), (GdkEvent *) event);
5002 toggle_add_mode (GtkCList *clist)
5004 g_return_if_fail (clist != 0);
5005 g_return_if_fail (GTK_IS_CLIST (clist));
5007 if (gdk_pointer_is_grabbed () ||
5008 clist->selection_mode != GTK_SELECTION_EXTENDED)
5011 gtk_clist_draw_focus (GTK_WIDGET (clist));
5012 if (!GTK_CLIST_ADD_MODE (clist))
5014 GTK_CLIST_SET_FLAG (clist, CLIST_ADD_MODE);
5015 gdk_gc_set_line_attributes (clist->xor_gc, 1,
5016 GDK_LINE_ON_OFF_DASH, 0, 0);
5017 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
5021 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
5022 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
5023 clist->anchor_state = GTK_STATE_SELECTED;
5025 gtk_clist_draw_focus (GTK_WIDGET (clist));
5029 toggle_focus_row (GtkCList *clist)
5031 g_return_if_fail (clist != 0);
5032 g_return_if_fail (GTK_IS_CLIST (clist));
5034 if (gdk_pointer_is_grabbed ())
5037 switch (clist->selection_mode)
5039 case GTK_SELECTION_SINGLE:
5040 case GTK_SELECTION_MULTIPLE:
5042 toggle_row (clist, clist->focus_row, 0, NULL);
5045 case GTK_SELECTION_EXTENDED:
5046 g_list_free (clist->undo_selection);
5047 g_list_free (clist->undo_unselection);
5048 clist->undo_selection = NULL;
5049 clist->undo_unselection = NULL;
5051 if (GTK_CLIST_ADD_MODE (clist))
5053 clist->anchor = clist->focus_row;
5054 clist->drag_pos = clist->focus_row;
5055 clist->undo_anchor = clist->focus_row;
5056 fake_toggle_row (clist, clist->focus_row);
5057 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5061 clist->anchor = clist->focus_row;
5062 clist->drag_pos = clist->focus_row;
5063 clist->undo_anchor = clist->focus_row;
5064 GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist,
5066 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5076 move_focus_row (GtkCList *clist,
5077 GtkScrollType scroll_type,
5082 g_return_if_fail (clist != 0);
5083 g_return_if_fail (GTK_IS_CLIST (clist));
5085 widget = GTK_WIDGET (clist);
5087 switch (scroll_type)
5089 case GTK_SCROLL_STEP_BACKWARD:
5090 if (clist->focus_row <= 0)
5092 gtk_clist_draw_focus (widget);
5094 gtk_clist_draw_focus (widget);
5096 case GTK_SCROLL_STEP_FORWARD:
5097 if (clist->focus_row >= clist->rows - 1)
5099 gtk_clist_draw_focus (widget);
5101 gtk_clist_draw_focus (widget);
5103 case GTK_SCROLL_PAGE_BACKWARD:
5104 if (clist->focus_row <= 0)
5106 gtk_clist_draw_focus (widget);
5107 clist->focus_row = MAX (0, clist->focus_row -
5108 (2 * clist->clist_window_height -
5109 clist->row_height - CELL_SPACING) /
5110 (2 * (clist->row_height + CELL_SPACING)));
5111 gtk_clist_draw_focus (widget);
5113 case GTK_SCROLL_PAGE_FORWARD:
5114 if (clist->focus_row >= clist->rows - 1)
5116 gtk_clist_draw_focus (widget);
5117 clist->focus_row = MIN (clist->rows - 1, clist->focus_row +
5118 (2 * clist->clist_window_height -
5119 clist->row_height - CELL_SPACING) /
5120 (2 * (clist->row_height + CELL_SPACING)));
5121 gtk_clist_draw_focus (widget);
5123 case GTK_SCROLL_JUMP:
5124 if (position >= 0 && position <= 1)
5126 gtk_clist_draw_focus (widget);
5127 clist->focus_row = position * (clist->rows - 1);
5128 gtk_clist_draw_focus (widget);
5137 scroll_horizontal (GtkCList *clist,
5138 GtkScrollType scroll_type,
5143 g_return_if_fail (clist != 0);
5144 g_return_if_fail (GTK_IS_CLIST (clist));
5146 if (gdk_pointer_is_grabbed ())
5149 switch (scroll_type)
5151 case GTK_SCROLL_STEP_BACKWARD:
5152 column = COLUMN_FROM_XPIXEL (clist, 0);
5153 if (COLUMN_LEFT_XPIXEL (clist, column) - CELL_SPACING - COLUMN_INSET >= 0
5157 case GTK_SCROLL_STEP_FORWARD:
5158 column = COLUMN_FROM_XPIXEL (clist, clist->clist_window_width);
5161 if (COLUMN_LEFT_XPIXEL (clist, column) + clist->column[column].area.width
5162 + CELL_SPACING + COLUMN_INSET - 1 <= clist->clist_window_width &&
5163 column < clist->columns - 1)
5166 case GTK_SCROLL_PAGE_BACKWARD:
5167 case GTK_SCROLL_PAGE_FORWARD:
5169 case GTK_SCROLL_JUMP:
5170 if (position >= 0 && position <= 1)
5171 column = position * (clist->columns - 1);
5179 if (COLUMN_LEFT_XPIXEL (clist, column) < CELL_SPACING + COLUMN_INSET)
5180 gtk_clist_moveto (clist, -1, column, 0, 0);
5181 else if (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET - 1
5182 + clist->column[column].area.width > clist->clist_window_width)
5184 if (column == clist->columns - 1)
5185 gtk_clist_moveto (clist, -1, column, 0, 0);
5187 gtk_clist_moveto (clist, -1, column, 0, 1);
5192 scroll_vertical (GtkCList *clist,
5193 GtkScrollType scroll_type,
5196 g_return_if_fail (clist != NULL);
5197 g_return_if_fail (GTK_IS_CLIST (clist));
5199 if (gdk_pointer_is_grabbed ())
5202 switch (clist->selection_mode)
5204 case GTK_SELECTION_EXTENDED:
5205 if (clist->anchor >= 0)
5207 if (!GTK_CLIST_ADD_MODE (clist))
5208 gtk_clist_unselect_all (clist);
5210 case GTK_SELECTION_BROWSE:
5212 if (clist->selection_mode == GTK_SELECTION_BROWSE)
5213 unselect_row (clist,clist->focus_row, -1, NULL);
5215 move_focus_row (clist, scroll_type, position);
5217 if (clist->selection_mode == GTK_SELECTION_EXTENDED &&
5218 GTK_CLIST_ADD_MODE (clist))
5221 switch (gtk_clist_row_is_visible (clist, clist->focus_row))
5223 case GTK_VISIBILITY_NONE:
5224 select_row (clist, clist->focus_row, -1, NULL);
5225 switch (scroll_type)
5227 case GTK_SCROLL_STEP_BACKWARD:
5228 case GTK_SCROLL_PAGE_BACKWARD:
5229 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5231 case GTK_SCROLL_STEP_FORWARD:
5232 case GTK_SCROLL_PAGE_FORWARD:
5233 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5235 case GTK_SCROLL_JUMP:
5236 gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
5243 case GTK_VISIBILITY_PARTIAL:
5244 switch (scroll_type)
5246 case GTK_SCROLL_STEP_BACKWARD:
5247 case GTK_SCROLL_PAGE_BACKWARD:
5248 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5250 case GTK_SCROLL_STEP_FORWARD:
5251 case GTK_SCROLL_PAGE_FORWARD:
5252 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5254 case GTK_SCROLL_JUMP:
5255 gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
5262 select_row (clist, clist->focus_row, -1, NULL);
5268 move_focus_row (clist, scroll_type, position);
5270 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
5271 clist->clist_window_height)
5272 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5273 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
5274 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5280 set_anchor (GtkCList *clist,
5285 g_return_if_fail (clist != NULL);
5286 g_return_if_fail (GTK_IS_CLIST (clist));
5288 if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor >= 0)
5291 g_list_free (clist->undo_selection);
5292 g_list_free (clist->undo_unselection);
5293 clist->undo_selection = NULL;
5294 clist->undo_unselection = NULL;
5297 fake_toggle_row (clist, anchor);
5300 GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist, anchor);
5301 clist->anchor_state = GTK_STATE_SELECTED;
5304 clist->anchor = anchor;
5305 clist->drag_pos = anchor;
5306 clist->undo_anchor = undo_anchor;
5310 resync_selection (GtkCList *clist,
5316 gboolean thaw = FALSE;
5318 GtkCListRow *clist_row;
5320 if (clist->anchor < 0)
5323 if (!GTK_CLIST_FROZEN (clist))
5325 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
5329 i = MIN (clist->anchor, clist->drag_pos);
5330 e = MAX (clist->anchor, clist->drag_pos);
5332 if (clist->undo_selection)
5335 list = clist->selection;
5336 clist->selection = clist->undo_selection;
5337 clist->selection_end = g_list_last (clist->selection);
5338 clist->undo_selection = list;
5339 list = clist->selection;
5342 row = GPOINTER_TO_INT (list->data);
5344 if (row < i || row > e)
5346 clist_row = g_list_nth (clist->row_list, row)->data;
5347 clist_row->state = GTK_STATE_SELECTED;
5348 unselect_row (clist, row, -1, event);
5349 clist->undo_selection = g_list_prepend
5350 (clist->undo_selection, GINT_TO_POINTER (row));
5355 for (list = g_list_nth (clist->row_list, i); i <= e; i++, list = list->next)
5356 if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
5358 if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
5360 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
5361 unselect_row (clist, i, -1, event);
5362 clist->undo_selection = g_list_prepend (clist->undo_selection,
5363 GINT_TO_POINTER (i));
5366 else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
5368 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
5369 clist->undo_unselection = g_list_prepend (clist->undo_unselection,
5370 GINT_TO_POINTER (i));
5373 for (list = clist->undo_unselection; list; list = list->next)
5374 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
5375 GPOINTER_TO_INT (list->data), -1, event);
5378 clist->drag_pos = -1;
5381 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
5385 update_extended_selection (GtkCList *clist,
5395 gint y1 = clist->clist_window_height;
5396 gint y2 = clist->clist_window_height;
5403 if (row >= clist->rows)
5404 row = clist->rows - 1;
5406 /* extending downwards */
5407 if (row > clist->drag_pos && clist->anchor <= clist->drag_pos)
5409 s2 = clist->drag_pos + 1;
5412 /* extending upwards */
5413 else if (row < clist->drag_pos && clist->anchor >= clist->drag_pos)
5416 e2 = clist->drag_pos - 1;
5418 else if (row < clist->drag_pos && clist->anchor < clist->drag_pos)
5420 e1 = clist->drag_pos;
5421 /* row and drag_pos on different sides of anchor :
5422 take back the selection between anchor and drag_pos,
5423 select between anchor and row */
5424 if (row < clist->anchor)
5426 s1 = clist->anchor + 1;
5428 e2 = clist->anchor - 1;
5430 /* take back the selection between anchor and drag_pos */
5434 else if (row > clist->drag_pos && clist->anchor > clist->drag_pos)
5436 s1 = clist->drag_pos;
5437 /* row and drag_pos on different sides of anchor :
5438 take back the selection between anchor and drag_pos,
5439 select between anchor and row */
5440 if (row > clist->anchor)
5442 e1 = clist->anchor - 1;
5443 s2 = clist->anchor + 1;
5446 /* take back the selection between anchor and drag_pos */
5451 clist->drag_pos = row;
5454 area.width = clist->clist_window_width;
5456 /* restore the elements between s1 and e1 */
5459 for (i = s1, list = g_list_nth (clist->row_list, i); i <= e1;
5460 i++, list = list->next)
5462 if (GTK_CLIST_CLASS_FW (clist)->selection_find (clist, i, list))
5463 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
5465 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
5468 top = ROW_TOP_YPIXEL (clist, clist->focus_row);
5470 if (top + clist->row_height <= 0)
5473 area.height = ROW_TOP_YPIXEL (clist, e1) + clist->row_height;
5474 draw_rows (clist, &area);
5475 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5477 else if (top >= clist->clist_window_height)
5479 area.y = ROW_TOP_YPIXEL (clist, s1);
5480 area.height = clist->clist_window_height - area.y;
5481 draw_rows (clist, &area);
5482 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5485 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5486 else if (top + clist->row_height > clist->clist_window_height)
5487 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5489 y1 = ROW_TOP_YPIXEL (clist, s1);
5490 h1 = (e1 - s1 + 1) * (clist->row_height + CELL_SPACING);
5493 /* extend the selection between s2 and e2 */
5496 for (i = s2, list = g_list_nth (clist->row_list, i); i <= e2;
5497 i++, list = list->next)
5498 if (GTK_CLIST_ROW (list)->state != clist->anchor_state)
5499 GTK_CLIST_ROW (list)->state = clist->anchor_state;
5501 top = ROW_TOP_YPIXEL (clist, clist->focus_row);
5503 if (top + clist->row_height <= 0)
5506 area.height = ROW_TOP_YPIXEL (clist, e2) + clist->row_height;
5507 draw_rows (clist, &area);
5508 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5510 else if (top >= clist->clist_window_height)
5512 area.y = ROW_TOP_YPIXEL (clist, s2);
5513 area.height = clist->clist_window_height - area.y;
5514 draw_rows (clist, &area);
5515 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5518 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5519 else if (top + clist->row_height > clist->clist_window_height)
5520 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5522 y2 = ROW_TOP_YPIXEL (clist, s2);
5523 h2 = (e2-s2+1) * (clist->row_height + CELL_SPACING);
5526 area.y = MAX (0, MIN (y1, y2));
5527 if (area.y > clist->clist_window_height)
5529 area.height = MIN (clist->clist_window_height, h1 + h2);
5530 if (s1 >= 0 && s2 >= 0)
5531 area.height += (clist->row_height + CELL_SPACING);
5532 draw_rows (clist, &area);
5536 start_selection (GtkCList *clist)
5538 g_return_if_fail (clist != NULL);
5539 g_return_if_fail (GTK_IS_CLIST (clist));
5541 if (gdk_pointer_is_grabbed ())
5544 set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
5549 end_selection (GtkCList *clist)
5551 g_return_if_fail (clist != NULL);
5552 g_return_if_fail (GTK_IS_CLIST (clist));
5554 if (gdk_pointer_is_grabbed () || clist->anchor == -1)
5557 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5561 extend_selection (GtkCList *clist,
5562 GtkScrollType scroll_type,
5564 gboolean auto_start_selection)
5566 g_return_if_fail (clist != NULL);
5567 g_return_if_fail (GTK_IS_CLIST (clist));
5569 if (gdk_pointer_is_grabbed () ||
5570 clist->selection_mode != GTK_SELECTION_EXTENDED)
5573 if (auto_start_selection)
5574 set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
5576 else if (clist->anchor == -1)
5579 move_focus_row (clist, scroll_type, position);
5581 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
5582 clist->clist_window_height)
5583 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5584 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
5585 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5587 update_extended_selection (clist, clist->focus_row);
5591 abort_column_resize (GtkCList *clist)
5593 g_return_if_fail (clist != NULL);
5594 g_return_if_fail (GTK_IS_CLIST (clist));
5596 if (!GTK_CLIST_IN_DRAG (clist))
5599 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
5600 gdk_pointer_ungrab (gdk_time_get());
5602 if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
5603 draw_xor_line (clist);
5605 if (GTK_CLIST_ADD_MODE (clist))
5607 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0);
5608 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
5613 gtk_clist_key_press (GtkWidget * widget,
5614 GdkEventKey * event)
5617 gboolean handled = FALSE;
5619 g_return_val_if_fail (widget != NULL, FALSE);
5620 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
5621 g_return_val_if_fail (event != NULL, FALSE);
5623 clist = GTK_CLIST (widget);
5626 if (event->keyval == GDK_Escape && GTK_CLIST_IN_DRAG (clist))
5628 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
5629 gdk_pointer_ungrab (event->time);
5631 if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
5632 draw_xor_line (clist);
5634 if (GTK_CLIST_ADD_MODE (clist))
5636 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH,
5638 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
5643 if (GTK_WIDGET_CLASS (parent_class)->key_press_event)
5644 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
5649 switch (event->keyval)
5652 case GDK_ISO_Left_Tab:
5653 if (event->state & GDK_SHIFT_MASK)
5654 return gtk_container_focus (GTK_CONTAINER (widget),
5655 GTK_DIR_TAB_BACKWARD);
5657 return gtk_container_focus (GTK_CONTAINER (widget),
5658 GTK_DIR_TAB_FORWARD);
5668 title_focus (GtkCList * clist,
5671 GtkWidget *focus_child;
5672 gboolean return_val = FALSE;
5677 if (!GTK_CLIST_SHOW_TITLES (clist))
5680 focus_child = GTK_CONTAINER (clist)->focus_child;
5684 case GTK_DIR_TAB_BACKWARD:
5686 if (!focus_child || focus_child == clist->hscrollbar ||
5687 focus_child == clist->hscrollbar ||
5688 !GTK_CLIST_CHILD_HAS_FOCUS (clist))
5690 if (dir == GTK_DIR_UP)
5691 i = COLUMN_FROM_XPIXEL (clist, 0);
5693 i = clist->columns - 1;
5694 focus_child = clist->column[i].button;
5695 dir = GTK_DIR_TAB_FORWARD;
5702 if (!focus_child || focus_child == clist->hscrollbar ||
5703 focus_child == clist->hscrollbar)
5705 i = clist->columns - 1;
5706 focus_child = clist->column[i].button;
5710 if (!focus_child || focus_child == clist->hscrollbar ||
5711 focus_child == clist->hscrollbar)
5714 focus_child = clist->column[i].button;
5720 while (i < clist->columns)
5722 if (clist->column[i].button == focus_child)
5724 if (clist->column[i].button &&
5725 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
5726 GTK_IS_CONTAINER (clist->column[i].button) &&
5727 !GTK_WIDGET_HAS_FOCUS (clist->column[i].button))
5728 if (gtk_container_focus
5729 (GTK_CONTAINER (clist->column[i].button), dir))
5734 if (!return_val && dir == GTK_DIR_UP)
5745 while (j >= 0 && j < clist->columns)
5747 if (clist->column[j].button &&
5748 GTK_WIDGET_VISIBLE (clist->column[j].button))
5750 if (GTK_IS_CONTAINER (clist->column[j].button) &&
5752 (GTK_CONTAINER (clist->column[j].button), dir))
5757 else if (GTK_WIDGET_CAN_FOCUS (clist->column[j].button))
5759 gtk_widget_grab_focus (clist->column[j].button);
5769 if (COLUMN_LEFT_XPIXEL (clist, j) < CELL_SPACING + COLUMN_INSET)
5770 gtk_clist_moveto (clist, -1, j, 0, 0);
5771 else if (COLUMN_LEFT_XPIXEL(clist, j) + clist->column[j].area.width >
5772 clist->clist_window_width)
5774 if (j == clist->columns-1)
5775 gtk_clist_moveto (clist, -1, j, 0, 0);
5777 gtk_clist_moveto (clist, -1, j, 0, 1);
5784 gtk_clist_focus (GtkContainer * container,
5785 GtkDirectionType direction)
5788 GtkWidget *focus_child;
5791 g_return_val_if_fail (container != NULL, FALSE);
5792 g_return_val_if_fail (GTK_IS_CLIST (container), FALSE);
5794 if (!GTK_WIDGET_SENSITIVE (container))
5797 clist = GTK_CLIST (container);
5798 focus_child = container->focus_child;
5799 old_row = clist->focus_row;
5805 if (GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
5806 (!focus_child || (focus_child && focus_child != clist->vscrollbar &&
5807 focus_child != clist->hscrollbar)))
5809 if (title_focus (clist, direction))
5811 gtk_container_set_focus_child (container, NULL);
5814 gtk_widget_grab_focus (GTK_WIDGET (container));
5817 case GTK_DIR_TAB_FORWARD:
5818 if (GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
5819 (!focus_child || (focus_child != clist->vscrollbar &&
5820 focus_child != clist->hscrollbar)))
5822 gboolean tf = FALSE;
5824 if (((focus_child && direction == GTK_DIR_DOWN) ||
5825 !(tf = title_focus (clist, GTK_DIR_TAB_FORWARD)))
5828 if (clist->focus_row < 0)
5830 clist->focus_row = 0;
5832 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
5833 clist->selection_mode == GTK_SELECTION_EXTENDED) &&
5835 select_row (clist, clist->focus_row, -1, NULL);
5837 gtk_widget_grab_focus (GTK_WIDGET (container));
5845 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
5847 if ((!GTK_CLIST_CHILD_HAS_FOCUS (clist) || !focus_child ||
5848 (focus_child != clist->vscrollbar &&
5849 focus_child != clist->hscrollbar)) &&
5850 GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
5851 GTK_WIDGET_CAN_FOCUS (clist->vscrollbar))
5853 gtk_widget_grab_focus (clist->vscrollbar);
5857 if ((!GTK_CLIST_CHILD_HAS_FOCUS (clist) || !focus_child ||
5858 focus_child != clist->hscrollbar) &&
5859 GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
5860 GTK_WIDGET_CAN_FOCUS (clist->hscrollbar))
5862 gtk_widget_grab_focus (clist->hscrollbar);
5867 case GTK_DIR_TAB_BACKWARD:
5868 if (!focus_child && GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
5869 GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
5870 GTK_WIDGET_CAN_FOCUS (clist->hscrollbar))
5872 gtk_widget_grab_focus (clist->hscrollbar);
5876 if ((!focus_child || focus_child == clist->hscrollbar) &&
5877 GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
5878 GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
5879 GTK_WIDGET_CAN_FOCUS (clist->vscrollbar))
5881 gtk_widget_grab_focus (clist->vscrollbar);
5885 if ((!focus_child || focus_child == clist->hscrollbar ||
5886 focus_child == clist->vscrollbar) &&
5887 GTK_CLIST_CHILD_HAS_FOCUS (clist) && clist->rows)
5889 if (clist->focus_row < 0)
5891 clist->focus_row = 0;
5892 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
5893 clist->selection_mode == GTK_SELECTION_EXTENDED) &&
5895 select_row (clist, clist->focus_row, -1, NULL);
5897 gtk_widget_grab_focus (GTK_WIDGET (container));
5901 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
5903 if (title_focus (clist, direction))
5912 gtk_container_set_focus_child (container, NULL);
5917 gtk_clist_unselect_all (GtkCList * clist)
5919 GTK_CLIST_CLASS_FW (clist)->unselect_all (clist);
5923 real_unselect_all (GtkCList * clist)
5928 g_return_if_fail (clist != NULL);
5929 g_return_if_fail (GTK_IS_CLIST (clist));
5931 if (gdk_pointer_is_grabbed ())
5934 switch (clist->selection_mode)
5936 case GTK_SELECTION_BROWSE:
5937 if (clist->focus_row >= 0)
5939 select_row (clist, clist->focus_row, -1, NULL);
5944 case GTK_SELECTION_EXTENDED:
5945 g_list_free (clist->undo_selection);
5946 g_list_free (clist->undo_unselection);
5947 clist->undo_selection = NULL;
5948 clist->undo_unselection = NULL;
5951 clist->drag_pos = -1;
5952 clist->undo_anchor = clist->focus_row;
5959 list = clist->selection;
5963 i = GPOINTER_TO_INT (list->data);
5965 unselect_row (clist, i, -1, NULL);
5970 gtk_clist_select_all (GtkCList * clist)
5972 GTK_CLIST_CLASS_FW (clist)->select_all (clist);
5976 real_select_all (GtkCList * clist)
5981 g_return_if_fail (clist != NULL);
5982 g_return_if_fail (GTK_IS_CLIST (clist));
5984 if (gdk_pointer_is_grabbed ())
5987 switch (clist->selection_mode)
5989 case GTK_SELECTION_SINGLE:
5990 case GTK_SELECTION_BROWSE:
5993 case GTK_SELECTION_EXTENDED:
5994 g_list_free (clist->undo_selection);
5995 g_list_free (clist->undo_unselection);
5996 clist->undo_selection = NULL;
5997 clist->undo_unselection = NULL;
6000 ((GtkCListRow *) (clist->row_list->data))->state !=
6002 fake_toggle_row (clist, 0);
6004 clist->anchor_state = GTK_STATE_SELECTED;
6006 clist->drag_pos = 0;
6007 clist->undo_anchor = clist->focus_row;
6008 update_extended_selection (clist, clist->rows);
6009 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
6012 case GTK_SELECTION_MULTIPLE:
6013 for (i = 0, list = clist->row_list; list; i++, list = list->next)
6015 if (((GtkCListRow *)(list->data))->state == GTK_STATE_NORMAL)
6016 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
6024 fake_unselect_all (GtkCList * clist,
6031 if (row >= 0 && (work = g_list_nth (clist->row_list, row)))
6033 if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
6035 GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
6037 if (!GTK_CLIST_FROZEN (clist) &&
6038 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
6039 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
6040 GTK_CLIST_ROW (work));
6044 clist->undo_selection = clist->selection;
6045 clist->selection = NULL;
6046 clist->selection_end = NULL;
6048 for (list = clist->undo_selection; list; list = list->next)
6050 if ((i = GPOINTER_TO_INT (list->data)) == row ||
6051 !(work = g_list_nth (clist->row_list, i)))
6054 GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
6055 if (!GTK_CLIST_FROZEN (clist) &&
6056 gtk_clist_row_is_visible (clist, i) != GTK_VISIBILITY_NONE)
6057 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, i,
6058 GTK_CLIST_ROW (work));
6063 fake_toggle_row (GtkCList *clist,
6068 if (!(work = g_list_nth (clist->row_list, row)))
6071 if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
6072 clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
6074 clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
6076 if (!GTK_CLIST_FROZEN (clist) &&
6077 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
6078 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
6079 GTK_CLIST_ROW (work));
6083 selection_find (GtkCList *clist,
6085 GList *row_list_element)
6087 return g_list_find (clist->selection, GINT_TO_POINTER (row_number));