gtkclist.c 206 KB
Newer Older
1
2
/* GTK - The GIMP Toolkit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, Josh MacDonald, 
3
 * Copyright (C) 1997-1998 Jay Painter <jpaint@serv.net><jpaint@gimp.org>  
4
 *
5
6
7
8
9
10
11
12
13
14
15
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
16
17
18
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
19
 */
20
21
22
23
24
25
26
27

/*
 * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

28
#include <stdlib.h>
29
#include <string.h>
30
#include "config.h"
31
#include "gtkmain.h"
32
#include "gtkclist.h"
33
#include "gtkbindings.h"
34
#include "gtkdnd.h"
35
#include <gdk/gdkkeysyms.h>
36

37
38
39
/* length of button_actions array */
#define MAX_BUTTON 5

40
/* the number rows memchunk expands at a time */
41
#define CLIST_OPTIMUM_SIZE 64
42

43
/* the width of the column resize windows */
44
#define DRAG_WIDTH  6
45
46
47
48
49
50
51
52
53
54

/* minimum allowed width of a column */
#define COLUMN_MIN_WIDTH 5

/* this defigns the base grid spacing */
#define CELL_SPACING 1

/* added the horizontal space at the beginning and end of a row*/
#define COLUMN_INSET 3

55
56
57
/* used for auto-scrolling */
#define SCROLL_TIME  100

58
59
/* gives the top pixel of the given row in context of
 * the clist's voffset */
60
61
#define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
				    (((row) + 1) * CELL_SPACING) + \
62
63
64
65
				    (clist)->voffset)

/* returns the row index from a y pixel location in the 
 * context of the clist's voffset */
66
#define ROW_FROM_YPIXEL(clist, y)  (((y) - (clist)->voffset) / \
67
68
69
70
				    ((clist)->row_height + CELL_SPACING))

/* gives the left pixel of the given column in context of
 * the clist's hoffset */
71
#define COLUMN_LEFT_XPIXEL(clist, colnum)  ((clist)->column[(colnum)].area.x + \
72
73
74
75
					    (clist)->hoffset)

/* returns the column index from a x pixel location in the 
 * context of the clist's hoffset */
76
static inline gint
77
78
79
80
COLUMN_FROM_XPIXEL (GtkCList * clist,
		    gint x)
{
  gint i, cx;
81

82
  for (i = 0; i < clist->columns; i++)
Lars Hamann's avatar
Lars Hamann committed
83
84
85
    if (clist->column[i].visible)
      {
	cx = clist->column[i].area.x + clist->hoffset;
86

Lars Hamann's avatar
Lars Hamann committed
87
88
89
90
	if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
	    x <= (cx + clist->column[i].area.width + COLUMN_INSET))
	  return i;
      }
91

92
93
94
95
96
97
98
99
100
101
  /* no match */
  return -1;
}

/* returns the top pixel of the given row in the context of
 * the list height */
#define ROW_TOP(clist, row)        (((clist)->row_height + CELL_SPACING) * (row))

/* returns the left pixel of the given column in the context of
 * the list width */
102
#define COLUMN_LEFT(clist, colnum) ((clist)->column[(colnum)].area.x)
103
104
105
106
107

/* returns the total height of the list */
#define LIST_HEIGHT(clist)         (((clist)->row_height * ((clist)->rows)) + \
				    (CELL_SPACING * ((clist)->rows + 1)))

108

109
/* returns the total width of the list */
110
111
112
113
static inline gint
LIST_WIDTH (GtkCList * clist) 
{
  gint last_column;
114

115
116
  for (last_column = clist->columns - 1;
       last_column >= 0 && !clist->column[last_column].visible; last_column--);
117

118
119
120
121
122
123
  if (last_column >= 0)
    return (clist->column[last_column].area.x +
	    clist->column[last_column].area.width +
	    COLUMN_INSET + CELL_SPACING);
  return 0;
}
124

Owen Taylor's avatar
Owen Taylor committed
125
126
127
128
129
130
/* returns the GList item for the nth row */
#define	ROW_ELEMENT(clist, row)	(((row) == (clist)->rows - 1) ? \
				 (clist)->row_list_end : \
				 g_list_nth ((clist)->row_list, (row)))


131
132
133
134
/* redraw the list if it's not frozen */
#define CLIST_UNFROZEN(clist)     (((GtkCList*) (clist))->freeze_count == 0)
#define	CLIST_REFRESH(clist)	G_STMT_START { \
  if (CLIST_UNFROZEN (clist)) \
135
    GTK_CLIST_GET_CLASS (clist)->refresh ((GtkCList*) (clist)); \
136
} G_STMT_END
137
138


139
/* Signals */
140
enum {
141
142
  SELECT_ROW,
  UNSELECT_ROW,
143
  ROW_MOVE,
144
  CLICK_COLUMN,
145
  RESIZE_COLUMN,
146
147
148
149
150
151
152
153
154
155
156
  TOGGLE_FOCUS_ROW,
  SELECT_ALL,
  UNSELECT_ALL,
  UNDO_SELECTION,
  START_SELECTION,
  END_SELECTION,
  TOGGLE_ADD_MODE,
  EXTEND_SELECTION,
  SCROLL_VERTICAL,
  SCROLL_HORIZONTAL,
  ABORT_COLUMN_RESIZE,
157
158
159
  LAST_SIGNAL
};

160
enum {
161
162
163
164
  SYNC_REMOVE,
  SYNC_INSERT
};

165
166
enum {
  ARG_0,
167
168
169
  ARG_N_COLUMNS,
  ARG_SHADOW_TYPE,
  ARG_SELECTION_MODE,
170
  ARG_ROW_HEIGHT,
Tim Janik's avatar
Tim Janik committed
171
  ARG_TITLES_ACTIVE,
172
  ARG_REORDERABLE,
173
174
  ARG_USE_DRAG_ICONS,
  ARG_SORT_TYPE
175
176
};

177
/* GtkCList Methods */
178
179
static void gtk_clist_class_init (GtkCListClass *klass);
static void gtk_clist_init       (GtkCList      *clist);
180
181

/* GtkObject Methods */
182
static void gtk_clist_destroy  (GtkObject *object);
183
static void gtk_clist_finalize (GObject   *object);
184
185
186
187
188
189
static void gtk_clist_set_arg  (GtkObject *object,
				GtkArg    *arg,
				guint      arg_id);
static void gtk_clist_get_arg  (GtkObject *object,
				GtkArg    *arg,
				guint      arg_id);
190
191

/* GtkWidget Methods */
192
193
194
static void gtk_clist_set_scroll_adjustments (GtkCList      *clist,
					      GtkAdjustment *hadjustment,
					      GtkAdjustment *vadjustment);
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
static void gtk_clist_realize         (GtkWidget        *widget);
static void gtk_clist_unrealize       (GtkWidget        *widget);
static void gtk_clist_map             (GtkWidget        *widget);
static void gtk_clist_unmap           (GtkWidget        *widget);
static void gtk_clist_draw            (GtkWidget        *widget,
			               GdkRectangle     *area);
static gint gtk_clist_expose          (GtkWidget        *widget,
			               GdkEventExpose   *event);
static gint gtk_clist_key_press       (GtkWidget        *widget,
				       GdkEventKey      *event);
static gint gtk_clist_button_press    (GtkWidget        *widget,
				       GdkEventButton   *event);
static gint gtk_clist_button_release  (GtkWidget        *widget,
				       GdkEventButton   *event);
static gint gtk_clist_motion          (GtkWidget        *widget, 
			               GdkEventMotion   *event);
static void gtk_clist_size_request    (GtkWidget        *widget,
				       GtkRequisition   *requisition);
static void gtk_clist_size_allocate   (GtkWidget        *widget,
				       GtkAllocation    *allocation);
static void gtk_clist_draw_focus      (GtkWidget        *widget);
static gint gtk_clist_focus_in        (GtkWidget        *widget,
				       GdkEventFocus    *event);
static gint gtk_clist_focus_out       (GtkWidget        *widget,
				       GdkEventFocus    *event);
static gint gtk_clist_focus           (GtkContainer     *container,
				       GtkDirectionType  direction);
static void gtk_clist_style_set       (GtkWidget        *widget,
				       GtkStyle         *previous_style);
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
static void gtk_clist_drag_begin      (GtkWidget        *widget,
				       GdkDragContext   *context);
static gint gtk_clist_drag_motion     (GtkWidget        *widget,
				       GdkDragContext   *context,
				       gint              x,
				       gint              y,
				       guint             time);
static void gtk_clist_drag_leave      (GtkWidget        *widget,
				       GdkDragContext   *context,
				       guint             time);
static void gtk_clist_drag_end        (GtkWidget        *widget,
				       GdkDragContext   *context);
static gboolean gtk_clist_drag_drop   (GtkWidget      *widget,
				       GdkDragContext *context,
				       gint            x,
				       gint            y,
				       guint           time);
static void gtk_clist_drag_data_get   (GtkWidget        *widget,
				       GdkDragContext   *context,
				       GtkSelectionData *selection_data,
				       guint             info,
				       guint             time);
static void gtk_clist_drag_data_received (GtkWidget        *widget,
					  GdkDragContext   *context,
					  gint              x,
					  gint              y,
					  GtkSelectionData *selection_data,
					  guint             info,
252
					  guint             time);
253
254

/* GtkContainer Methods */
255
256
257
258
259
260
static void gtk_clist_set_focus_child (GtkContainer  *container,
				       GtkWidget     *child);
static void gtk_clist_forall          (GtkContainer  *container,
			               gboolean       include_internals,
			               GtkCallback    callback,
			               gpointer       callback_data);
261
262

/* Selection */
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
static void toggle_row                (GtkCList      *clist,
			               gint           row,
			               gint           column,
			               GdkEvent      *event);
static void real_select_row           (GtkCList      *clist,
			               gint           row,
			               gint           column,
			               GdkEvent      *event);
static void real_unselect_row         (GtkCList      *clist,
			               gint           row,
			               gint           column,
			               GdkEvent      *event);
static void update_extended_selection (GtkCList      *clist,
				       gint           row);
static GList *selection_find          (GtkCList      *clist,
			               gint           row_number,
			               GList         *row_list_element);
static void real_select_all           (GtkCList      *clist);
static void real_unselect_all         (GtkCList      *clist);
static void move_vertical             (GtkCList      *clist,
			               gint           row,
			               gfloat         align);
static void move_horizontal           (GtkCList      *clist,
			               gint           diff);
static void real_undo_selection       (GtkCList      *clist);
static void fake_unselect_all         (GtkCList      *clist,
			               gint           row);
static void fake_toggle_row           (GtkCList      *clist,
			               gint           row);
static void resync_selection          (GtkCList      *clist,
			               GdkEvent      *event);
static void sync_selection            (GtkCList      *clist,
	                               gint           row,
                                       gint           mode);
static void set_anchor                (GtkCList      *clist,
			               gboolean       add_mode,
			               gint           anchor,
			               gint           undo_anchor);
static void start_selection           (GtkCList      *clist);
static void end_selection             (GtkCList      *clist);
static void toggle_add_mode           (GtkCList      *clist);
static void toggle_focus_row          (GtkCList      *clist);
static void extend_selection          (GtkCList      *clist,
			               GtkScrollType  scroll_type,
			               gfloat         position,
			               gboolean       auto_start_selection);
static gint get_selection_info        (GtkCList       *clist,
				       gint            x,
				       gint            y,
				       gint           *row,
				       gint           *column);
314

315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
/* Scrolling */
static void move_focus_row     (GtkCList      *clist,
			        GtkScrollType  scroll_type,
			        gfloat         position);
static void scroll_horizontal  (GtkCList      *clist,
			        GtkScrollType  scroll_type,
			        gfloat         position);
static void scroll_vertical    (GtkCList      *clist,
			        GtkScrollType  scroll_type,
			        gfloat         position);
static void move_horizontal    (GtkCList      *clist,
				gint           diff);
static void move_vertical      (GtkCList      *clist,
				gint           row,
				gfloat         align);
static gint horizontal_timeout (GtkCList      *clist);
static gint vertical_timeout   (GtkCList      *clist);
static void remove_grab        (GtkCList      *clist);


335
/* Resize Columns */
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
static void draw_xor_line             (GtkCList       *clist);
static gint new_column_width          (GtkCList       *clist,
			               gint            column,
			               gint           *x);
static void column_auto_resize        (GtkCList       *clist,
				       GtkCListRow    *clist_row,
				       gint            column,
				       gint            old_width);
static void real_resize_column        (GtkCList       *clist,
				       gint            column,
				       gint            width);
static void abort_column_resize       (GtkCList       *clist);
static void cell_size_request         (GtkCList       *clist,
			               GtkCListRow    *clist_row,
			               gint            column,
				       GtkRequisition *requisition);
352
353

/* Buttons */
354
355
356
357
static void column_button_create      (GtkCList       *clist,
				       gint            column);
static void column_button_clicked     (GtkWidget      *widget,
				       gpointer        data);
358

359
360
361
/* Adjustments */
static void adjust_adjustments        (GtkCList       *clist,
				       gboolean        block_resize);
362
363
364
365
366
367
368
369
370
static void check_exposures           (GtkCList       *clist);
static void vadjustment_changed       (GtkAdjustment  *adjustment,
				       gpointer        data);
static void vadjustment_value_changed (GtkAdjustment  *adjustment,
				       gpointer        data);
static void hadjustment_changed       (GtkAdjustment  *adjustment,
				       gpointer        data);
static void hadjustment_value_changed (GtkAdjustment  *adjustment,
				       gpointer        data);
371

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
/* Drawing */
static void get_cell_style   (GtkCList      *clist,
			      GtkCListRow   *clist_row,
			      gint           state,
			      gint           column,
			      GtkStyle     **style,
			      GdkGC        **fg_gc,
			      GdkGC        **bg_gc);
static gint draw_cell_pixmap (GdkWindow     *window,
			      GdkRectangle  *clip_rectangle,
			      GdkGC         *fg_gc,
			      GdkPixmap     *pixmap,
			      GdkBitmap     *mask,
			      gint           x,
			      gint           y,
			      gint           width,
			      gint           height);
static void draw_row         (GtkCList      *clist,
			      GdkRectangle  *area,
			      gint           row,
			      GtkCListRow   *clist_row);
static void draw_rows        (GtkCList      *clist,
			      GdkRectangle  *area);
395
static void clist_refresh    (GtkCList      *clist);
396
397
398
399
static void draw_drag_highlight (GtkCList        *clist,
				 GtkCListRow     *dest_row,
				 gint             dest_row_number,
				 GtkCListDragPos  drag_pos);
400
     
401
/* Size Allocation / Requisition */
402
static void size_allocate_title_buttons (GtkCList *clist);
Lars Hamann's avatar
Lars Hamann committed
403
404
static void size_allocate_columns       (GtkCList *clist,
					 gboolean  block_resize);
405
static gint list_requisition_width      (GtkCList *clist);
Stefan Jeske's avatar
Stefan Jeske committed
406

407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
/* Memory Allocation/Distruction Routines */
static GtkCListColumn *columns_new (GtkCList      *clist);
static void column_title_new       (GtkCList      *clist,
			            gint           column,
			            const gchar   *title);
static void columns_delete         (GtkCList      *clist);
static GtkCListRow *row_new        (GtkCList      *clist);
static void row_delete             (GtkCList      *clist,
			            GtkCListRow   *clist_row);
static void set_cell_contents      (GtkCList      *clist,
			            GtkCListRow   *clist_row,
				    gint           column,
				    GtkCellType    type,
				    const gchar   *text,
				    guint8         spacing,
				    GdkPixmap     *pixmap,
				    GdkBitmap     *mask);
static gint real_insert_row        (GtkCList      *clist,
				    gint           row,
				    gchar         *text[]);
static void real_remove_row        (GtkCList      *clist,
				    gint           row);
static void real_clear             (GtkCList      *clist);
430

431
432
433
434
435
436
437
438
439
440
441
442
/* Sorting */
static gint default_compare        (GtkCList      *clist,
			            gconstpointer  row1,
			            gconstpointer  row2);
static void real_sort_list         (GtkCList      *clist);
static GList *gtk_clist_merge      (GtkCList      *clist,
				    GList         *a,
				    GList         *b);
static GList *gtk_clist_mergesort  (GtkCList      *clist,
				    GList         *list,
				    gint           num);
/* Misc */
443
444
445
446
447
448
449
450
static gboolean title_focus           (GtkCList  *clist,
			               gint       dir);
static void real_row_move             (GtkCList  *clist,
			               gint       source_row,
			               gint       dest_row);
static gint column_title_passive_func (GtkWidget *widget, 
				       GdkEvent  *event,
				       gpointer   data);
Lars Hamann's avatar
Lars Hamann committed
451
452
453
454
static void drag_dest_cell            (GtkCList         *clist,
				       gint              x,
				       gint              y,
				       GtkCListDestInfo *dest_info);
455

456

457

458
static GtkContainerClass *parent_class = NULL;
459
static guint clist_signals[LAST_SIGNAL] = {0};
460

461
static GtkTargetEntry clist_target_table = { "gtk-clist-drag-reorder", 0, 0};
462

463
GtkType
464
gtk_clist_get_type (void)
465
{
466
  static GtkType clist_type = 0;
467

468
469
  if (!clist_type)
    {
470
      static const GtkTypeInfo clist_info =
471
472
473
474
475
476
      {
	"GtkCList",
	sizeof (GtkCList),
	sizeof (GtkCListClass),
	(GtkClassInitFunc) gtk_clist_class_init,
	(GtkObjectInitFunc) gtk_clist_init,
477
	/* reserved_1 */ NULL,
478
479
	/* reserved_2 */ NULL,
	(GtkClassInitFunc) NULL,
480
      };
481

482
      clist_type = gtk_type_unique (GTK_TYPE_CONTAINER, &clist_info);
483
    }
484

485
486
487
488
  return clist_type;
}

static void
489
gtk_clist_class_init (GtkCListClass *klass)
490
{
491
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
492
493
494
  GtkObjectClass *object_class;
  GtkWidgetClass *widget_class;
  GtkContainerClass *container_class;
495
  GtkBindingSet *binding_set;
496

497
498
499
  object_class = (GtkObjectClass *) klass;
  widget_class = (GtkWidgetClass *) klass;
  container_class = (GtkContainerClass *) klass;
500

501
  parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
502

503
504
505
506
507
508
  gobject_class->finalize = gtk_clist_finalize;
  
  object_class->set_arg = gtk_clist_set_arg;
  object_class->get_arg = gtk_clist_get_arg;
  object_class->destroy = gtk_clist_destroy;
  
509
510
511
512
513
514
  gtk_object_add_arg_type ("GtkCList::n_columns",
			   GTK_TYPE_UINT,
			   GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
			   ARG_N_COLUMNS);
  gtk_object_add_arg_type ("GtkCList::shadow_type",
			   GTK_TYPE_SHADOW_TYPE,
515
			   GTK_ARG_READWRITE,
516
517
518
			   ARG_SHADOW_TYPE);
  gtk_object_add_arg_type ("GtkCList::selection_mode",
			   GTK_TYPE_SELECTION_MODE,
519
			   GTK_ARG_READWRITE,
520
521
522
523
524
			   ARG_SELECTION_MODE);
  gtk_object_add_arg_type ("GtkCList::row_height",
			   GTK_TYPE_UINT,
			   GTK_ARG_READWRITE,
			   ARG_ROW_HEIGHT);
525
526
527
528
  gtk_object_add_arg_type ("GtkCList::reorderable",
			   GTK_TYPE_BOOL,
			   GTK_ARG_READWRITE,
			   ARG_REORDERABLE);
Tim Janik's avatar
Tim Janik committed
529
530
531
532
  gtk_object_add_arg_type ("GtkCList::titles_active",
			   GTK_TYPE_BOOL,
			   GTK_ARG_READWRITE,
			   ARG_TITLES_ACTIVE);
533
534
535
536
  gtk_object_add_arg_type ("GtkCList::use_drag_icons",
			   GTK_TYPE_BOOL,
			   GTK_ARG_READWRITE,
			   ARG_USE_DRAG_ICONS);
537
538
539
540
  gtk_object_add_arg_type ("GtkCList::sort_type",
			   GTK_TYPE_SORT_TYPE,
			   GTK_ARG_READWRITE,
			   ARG_SORT_TYPE);  
541

542
543
  widget_class->set_scroll_adjustments_signal =
    gtk_signal_new ("set_scroll_adjustments",
544
		    GTK_RUN_LAST,
545
		    GTK_CLASS_TYPE (object_class),
546
		    GTK_SIGNAL_OFFSET (GtkCListClass, set_scroll_adjustments),
547
548
		    gtk_marshal_NONE__POINTER_POINTER,
		    GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
549

550
551
  clist_signals[SELECT_ROW] =
    gtk_signal_new ("select_row",
552
		    GTK_RUN_FIRST,
553
		    GTK_CLASS_TYPE (object_class),
554
		    GTK_SIGNAL_OFFSET (GtkCListClass, select_row),
555
556
557
558
559
		    gtk_marshal_NONE__INT_INT_POINTER,
		    GTK_TYPE_NONE, 3,
		    GTK_TYPE_INT,
		    GTK_TYPE_INT,
		    GTK_TYPE_GDK_EVENT);
560
561
  clist_signals[UNSELECT_ROW] =
    gtk_signal_new ("unselect_row",
562
		    GTK_RUN_FIRST,
563
		    GTK_CLASS_TYPE (object_class),
564
		    GTK_SIGNAL_OFFSET (GtkCListClass, unselect_row),
565
		    gtk_marshal_NONE__INT_INT_POINTER,
566
567
568
569
570
		    GTK_TYPE_NONE, 3, GTK_TYPE_INT,
		    GTK_TYPE_INT, GTK_TYPE_GDK_EVENT);
  clist_signals[ROW_MOVE] =
    gtk_signal_new ("row_move",
		    GTK_RUN_LAST,
571
		    GTK_CLASS_TYPE (object_class),
572
573
574
		    GTK_SIGNAL_OFFSET (GtkCListClass, row_move),
		    gtk_marshal_NONE__INT_INT,
		    GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
575
576
  clist_signals[CLICK_COLUMN] =
    gtk_signal_new ("click_column",
577
		    GTK_RUN_FIRST,
578
		    GTK_CLASS_TYPE (object_class),
579
		    GTK_SIGNAL_OFFSET (GtkCListClass, click_column),
580
		    gtk_marshal_NONE__INT,
581
		    GTK_TYPE_NONE, 1, GTK_TYPE_INT);
582
583
584
  clist_signals[RESIZE_COLUMN] =
    gtk_signal_new ("resize_column",
		    GTK_RUN_LAST,
585
		    GTK_CLASS_TYPE (object_class),
586
587
588
		    GTK_SIGNAL_OFFSET (GtkCListClass, resize_column),
		    gtk_marshal_NONE__INT_INT,
		    GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
589

590
591
592
  clist_signals[TOGGLE_FOCUS_ROW] =
    gtk_signal_new ("toggle_focus_row",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
593
                    GTK_CLASS_TYPE (object_class),
594
                    GTK_SIGNAL_OFFSET (GtkCListClass, toggle_focus_row),
595
                    gtk_marshal_NONE__NONE,
596
597
598
599
                    GTK_TYPE_NONE, 0);
  clist_signals[SELECT_ALL] =
    gtk_signal_new ("select_all",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
600
                    GTK_CLASS_TYPE (object_class),
601
                    GTK_SIGNAL_OFFSET (GtkCListClass, select_all),
602
                    gtk_marshal_NONE__NONE,
603
604
605
606
                    GTK_TYPE_NONE, 0);
  clist_signals[UNSELECT_ALL] =
    gtk_signal_new ("unselect_all",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
607
                    GTK_CLASS_TYPE (object_class),
608
                    GTK_SIGNAL_OFFSET (GtkCListClass, unselect_all),
609
                    gtk_marshal_NONE__NONE,
610
611
612
613
                    GTK_TYPE_NONE, 0);
  clist_signals[UNDO_SELECTION] =
    gtk_signal_new ("undo_selection",
		    GTK_RUN_LAST | GTK_RUN_ACTION,
614
		    GTK_CLASS_TYPE (object_class),
615
		    GTK_SIGNAL_OFFSET (GtkCListClass, undo_selection),
616
		    gtk_marshal_NONE__NONE,
617
618
619
620
		    GTK_TYPE_NONE, 0);
  clist_signals[START_SELECTION] =
    gtk_signal_new ("start_selection",
		    GTK_RUN_LAST | GTK_RUN_ACTION,
621
		    GTK_CLASS_TYPE (object_class),
622
		    GTK_SIGNAL_OFFSET (GtkCListClass, start_selection),
623
		    gtk_marshal_NONE__NONE,
624
625
626
627
		    GTK_TYPE_NONE, 0);
  clist_signals[END_SELECTION] =
    gtk_signal_new ("end_selection",
		    GTK_RUN_LAST | GTK_RUN_ACTION,
628
		    GTK_CLASS_TYPE (object_class),
629
		    GTK_SIGNAL_OFFSET (GtkCListClass, end_selection),
630
		    gtk_marshal_NONE__NONE,
631
632
633
634
		    GTK_TYPE_NONE, 0);
  clist_signals[TOGGLE_ADD_MODE] =
    gtk_signal_new ("toggle_add_mode",
		    GTK_RUN_LAST | GTK_RUN_ACTION,
635
		    GTK_CLASS_TYPE (object_class),
636
		    GTK_SIGNAL_OFFSET (GtkCListClass, toggle_add_mode),
637
		    gtk_marshal_NONE__NONE,
638
639
640
641
		    GTK_TYPE_NONE, 0);
  clist_signals[EXTEND_SELECTION] =
    gtk_signal_new ("extend_selection",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
642
                    GTK_CLASS_TYPE (object_class),
643
                    GTK_SIGNAL_OFFSET (GtkCListClass, extend_selection),
644
                    gtk_marshal_NONE__ENUM_FLOAT_BOOL,
645
                    GTK_TYPE_NONE, 3,
646
		    GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT, GTK_TYPE_BOOL);
647
648
649
  clist_signals[SCROLL_VERTICAL] =
    gtk_signal_new ("scroll_vertical",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
650
                    GTK_CLASS_TYPE (object_class),
651
                    GTK_SIGNAL_OFFSET (GtkCListClass, scroll_vertical),
652
                    gtk_marshal_NONE__ENUM_FLOAT,
653
                    GTK_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT);
654
655
656
  clist_signals[SCROLL_HORIZONTAL] =
    gtk_signal_new ("scroll_horizontal",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
657
                    GTK_CLASS_TYPE (object_class),
658
                    GTK_SIGNAL_OFFSET (GtkCListClass, scroll_horizontal),
659
                    gtk_marshal_NONE__ENUM_FLOAT,
660
                    GTK_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT);
661
662
663
  clist_signals[ABORT_COLUMN_RESIZE] =
    gtk_signal_new ("abort_column_resize",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
664
                    GTK_CLASS_TYPE (object_class),
665
                    GTK_SIGNAL_OFFSET (GtkCListClass, abort_column_resize),
666
                    gtk_marshal_NONE__NONE,
667
                    GTK_TYPE_NONE, 0);
668
  gtk_object_class_add_signals (object_class, clist_signals, LAST_SIGNAL);
669

670
671
672
673
674
675
  widget_class->realize = gtk_clist_realize;
  widget_class->unrealize = gtk_clist_unrealize;
  widget_class->map = gtk_clist_map;
  widget_class->unmap = gtk_clist_unmap;
  widget_class->draw = gtk_clist_draw;
  widget_class->button_press_event = gtk_clist_button_press;
676
677
  widget_class->button_release_event = gtk_clist_button_release;
  widget_class->motion_notify_event = gtk_clist_motion;
678
679
680
  widget_class->expose_event = gtk_clist_expose;
  widget_class->size_request = gtk_clist_size_request;
  widget_class->size_allocate = gtk_clist_size_allocate;
681
682
683
684
  widget_class->key_press_event = gtk_clist_key_press;
  widget_class->focus_in_event = gtk_clist_focus_in;
  widget_class->focus_out_event = gtk_clist_focus_out;
  widget_class->draw_focus = gtk_clist_draw_focus;
685
  widget_class->style_set = gtk_clist_style_set;
686
687
688
689
690
691
692
  widget_class->drag_begin = gtk_clist_drag_begin;
  widget_class->drag_end = gtk_clist_drag_end;
  widget_class->drag_motion = gtk_clist_drag_motion;
  widget_class->drag_leave = gtk_clist_drag_leave;
  widget_class->drag_drop = gtk_clist_drag_drop;
  widget_class->drag_data_get = gtk_clist_drag_data_get;
  widget_class->drag_data_received = gtk_clist_drag_data_received;
693

694
  /* container_class->add = NULL; use the default GtkContainerClass warning */
695
  /* container_class->remove=NULL; use the default GtkContainerClass warning */
696

697
  container_class->forall = gtk_clist_forall;
698
699
  container_class->focus = gtk_clist_focus;
  container_class->set_focus_child = gtk_clist_set_focus_child;
700

701
  klass->set_scroll_adjustments = gtk_clist_set_scroll_adjustments;
702
  klass->refresh = clist_refresh;
703
704
  klass->select_row = real_select_row;
  klass->unselect_row = real_unselect_row;
705
  klass->row_move = real_row_move;
706
707
708
  klass->undo_selection = real_undo_selection;
  klass->resync_selection = resync_selection;
  klass->selection_find = selection_find;
709
  klass->click_column = NULL;
710
  klass->resize_column = real_resize_column;
711
  klass->draw_row = draw_row;
712
  klass->draw_drag_highlight = draw_drag_highlight;
713
714
  klass->insert_row = real_insert_row;
  klass->remove_row = real_remove_row;
715
  klass->clear = real_clear;
716
  klass->sort_list = real_sort_list;
717
718
719
720
721
722
723
724
725
726
727
  klass->select_all = real_select_all;
  klass->unselect_all = real_unselect_all;
  klass->fake_unselect_all = fake_unselect_all;
  klass->scroll_horizontal = scroll_horizontal;
  klass->scroll_vertical = scroll_vertical;
  klass->extend_selection = extend_selection;
  klass->toggle_focus_row = toggle_focus_row;
  klass->toggle_add_mode = toggle_add_mode;
  klass->start_selection = start_selection;
  klass->end_selection = end_selection;
  klass->abort_column_resize = abort_column_resize;
728
  klass->set_cell_contents = set_cell_contents;
729
  klass->cell_size_request = cell_size_request;
730

731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
  binding_set = gtk_binding_set_by_class (klass);
  gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
				"scroll_vertical", 2,
				GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
				GTK_TYPE_FLOAT, 0.0);
  gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
				"scroll_vertical", 2,
				GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
				GTK_TYPE_FLOAT, 0.0);
  gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
				"scroll_vertical", 2,
				GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
				GTK_TYPE_FLOAT, 0.0);
  gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
				"scroll_vertical", 2,
				GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
				GTK_TYPE_FLOAT, 0.0);
  gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
				"scroll_vertical", 2,
				GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
				GTK_TYPE_FLOAT, 0.0);
  gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
				"scroll_vertical", 2,
				GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
				GTK_TYPE_FLOAT, 1.0);
756

757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
  gtk_binding_entry_add_signal (binding_set, GDK_Up, GDK_SHIFT_MASK,
				"extend_selection", 3,
				GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
				GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
  gtk_binding_entry_add_signal (binding_set, GDK_Down, GDK_SHIFT_MASK,
				"extend_selection", 3,
				GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
				GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
  gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_SHIFT_MASK,
				"extend_selection", 3,
				GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
				GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
  gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_SHIFT_MASK,
				"extend_selection", 3,
				GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
				GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
  gtk_binding_entry_add_signal (binding_set, GDK_Home,
				GDK_SHIFT_MASK | GDK_CONTROL_MASK,
				"extend_selection", 3,
				GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
				GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
  gtk_binding_entry_add_signal (binding_set, GDK_End,
				GDK_SHIFT_MASK | GDK_CONTROL_MASK,
				"extend_selection", 3,
				GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
				GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
783

784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
  gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
				"scroll_horizontal", 2,
				GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
				GTK_TYPE_FLOAT, 0.0);
  gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
				"scroll_horizontal", 2,
				GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
				GTK_TYPE_FLOAT, 0.0);
  gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
				"scroll_horizontal", 2,
				GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
				GTK_TYPE_FLOAT, 0.0);
  gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
				"scroll_horizontal", 2,
				GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
				GTK_TYPE_FLOAT, 1.0);
800

801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
  gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
				"undo_selection", 0);
  gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
				"abort_column_resize", 0);
  gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
				"toggle_focus_row", 0);
  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
				"toggle_add_mode", 0);
  gtk_binding_entry_add_signal (binding_set, '/', GDK_CONTROL_MASK,
				"select_all", 0);
  gtk_binding_entry_add_signal (binding_set, '\\', GDK_CONTROL_MASK,
				"unselect_all", 0);
  gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
				GDK_RELEASE_MASK | GDK_SHIFT_MASK,
				"end_selection", 0);
  gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
				GDK_RELEASE_MASK | GDK_SHIFT_MASK,
				"end_selection", 0);
  gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
				GDK_RELEASE_MASK | GDK_SHIFT_MASK |
				GDK_CONTROL_MASK,
				"end_selection", 0);
  gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
				GDK_RELEASE_MASK | GDK_SHIFT_MASK |
				GDK_CONTROL_MASK,
				"end_selection", 0);
827
828
}

829
830
831
832
833
834
static void
gtk_clist_set_arg (GtkObject      *object,
		   GtkArg         *arg,
		   guint           arg_id)
{
  GtkCList *clist;
835

836
  clist = GTK_CLIST (object);
837

838
839
  switch (arg_id)
    {
840
841
    case ARG_N_COLUMNS: /* construct-only arg, only set when !GTK_CONSTRUCTED */
      gtk_clist_construct (clist, MAX (1, GTK_VALUE_UINT (*arg)), NULL);
842
      break;
843
844
845
846
847
848
849
850
    case ARG_SHADOW_TYPE:
      gtk_clist_set_shadow_type (clist, GTK_VALUE_ENUM (*arg));
      break;
    case ARG_SELECTION_MODE:
      gtk_clist_set_selection_mode (clist, GTK_VALUE_ENUM (*arg));
      break;
    case ARG_ROW_HEIGHT:
      gtk_clist_set_row_height (clist, GTK_VALUE_UINT (*arg));
851
      break;
852
853
854
    case ARG_REORDERABLE:
      gtk_clist_set_reorderable (clist, GTK_VALUE_BOOL (*arg));
      break;
Tim Janik's avatar
Tim Janik committed
855
856
857
858
859
860
    case ARG_TITLES_ACTIVE:
      if (GTK_VALUE_BOOL (*arg))
	gtk_clist_column_titles_active (clist);
      else
	gtk_clist_column_titles_passive (clist);
      break;
861
862
863
    case ARG_USE_DRAG_ICONS:
      gtk_clist_set_use_drag_icons (clist, GTK_VALUE_BOOL (*arg));
      break;
864
865
    case ARG_SORT_TYPE:
      gtk_clist_set_sort_type (clist, GTK_VALUE_ENUM (*arg));
866
867
868
869
870
871
872
873
874
875
      break;
    }
}

static void
gtk_clist_get_arg (GtkObject      *object,
		   GtkArg         *arg,
		   guint           arg_id)
{
  GtkCList *clist;
876

877
  clist = GTK_CLIST (object);
878

879
880
  switch (arg_id)
    {
Tim Janik's avatar
Tim Janik committed
881
      guint i;
882

883
884
885
886
887
    case ARG_N_COLUMNS:
      GTK_VALUE_UINT (*arg) = clist->columns;
      break;
    case ARG_SHADOW_TYPE:
      GTK_VALUE_ENUM (*arg) = clist->shadow_type;
888
      break;
889
890
891
892
    case ARG_SELECTION_MODE:
      GTK_VALUE_ENUM (*arg) = clist->selection_mode;
      break;
    case ARG_ROW_HEIGHT:
893
894
895
896
897
      GTK_VALUE_UINT (*arg) = GTK_CLIST_ROW_HEIGHT_SET(clist) ? clist->row_height : 0;
      break;
    case ARG_REORDERABLE:
      GTK_VALUE_BOOL (*arg) = GTK_CLIST_REORDERABLE (clist);
      break;
Tim Janik's avatar
Tim Janik committed
898
899
900
901
902
903
904
905
906
907
    case ARG_TITLES_ACTIVE:
      GTK_VALUE_BOOL (*arg) = TRUE;
      for (i = 0; i < clist->columns; i++)
	if (clist->column[i].button &&
	    !GTK_WIDGET_SENSITIVE (clist->column[i].button))
	  {
	    GTK_VALUE_BOOL (*arg) = FALSE;
	    break;
	  }
      break;
908
909
    case ARG_USE_DRAG_ICONS:
      GTK_VALUE_BOOL (*arg) = GTK_CLIST_USE_DRAG_ICONS (clist);
910
      break;
911
912
913
    case ARG_SORT_TYPE:
      GTK_VALUE_ENUM (*arg) = clist->sort_type;
      break;
914
915
916
917
918
919
    default:
      arg->type = GTK_TYPE_INVALID;
      break;
    }
}

920
static void
921
gtk_clist_init (GtkCList *clist)
922
923
{
  clist->flags = 0;
924

925
  GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
926
927
928
929
  GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
  GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
  GTK_CLIST_SET_FLAG (clist, CLIST_DRAW_DRAG_LINE);
  GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
930

Tim Janik's avatar
Tim Janik committed
931
932
  clist->row_mem_chunk = NULL;
  clist->cell_mem_chunk = NULL;
933

934
  clist->freeze_count = 0;
935

936
937
938
939
  clist->rows = 0;
  clist->row_height = 0;
  clist->row_list = NULL;
  clist->row_list_end = NULL;
940

941
  clist->columns = 0;
942

943
  clist->title_window = NULL;
944
945
  clist->column_title_area.x = 0;
  clist->column_title_area.y = 0;
Owen Taylor's avatar
Owen Taylor committed
946
947
  clist->column_title_area.width = 1;
  clist->column_title_area.height = 1;
948

949
  clist->clist_window = NULL;
Owen Taylor's avatar
Owen Taylor committed
950
951
  clist->clist_window_width = 1;
  clist->clist_window_height = 1;
952

953
954
  clist->hoffset = 0;
  clist->voffset = 0;
955

956
  clist->shadow_type = GTK_SHADOW_IN;
957
958
  clist->vadjustment = NULL;
  clist->hadjustment = NULL;
959

960
961
962
963
964
  clist->button_actions[0] = GTK_BUTTON_SELECTS | GTK_BUTTON_DRAGS;
  clist->button_actions[1] = GTK_BUTTON_IGNORED;
  clist->button_actions[2] = GTK_BUTTON_IGNORED;
  clist->button_actions[3] = GTK_BUTTON_IGNORED;
  clist->button_actions[4] = GTK_BUTTON_IGNORED;
965

966
967
968
969
970
  clist->cursor_drag = NULL;
  clist->xor_gc = NULL;
  clist->fg_gc = NULL;
  clist->bg_gc = NULL;
  clist->x_drag = 0;
971

972
  clist->selection_mode = GTK_SELECTION_SINGLE;
973
  clist->selection = NULL;
974
975
976
  clist->selection_end = NULL;
  clist->undo_selection = NULL;
  clist->undo_unselection = NULL;
977

978
979
  clist->focus_row = -1;
  clist->undo_anchor = -1;
980

981
982
983
984
985
  clist->anchor = -1;
  clist->anchor_state = GTK_STATE_SELECTED;
  clist->drag_pos = -1;
  clist->htimer = 0;
  clist->vtimer = 0;
986

987
988
  clist->click_cell.row = -1;
  clist->click_cell.column = -1;
989

Stefan Jeske's avatar
Stefan Jeske committed
990
991
992
  clist->compare = default_compare;
  clist->sort_type = GTK_SORT_ASCENDING;
  clist->sort_column = 0;
993
994
}

995
996
/* Constructors */
void
997
998
gtk_clist_construct (GtkCList *clist,
		     gint      columns,
999
		     gchar    *titles[])
1000
{
Tim Janik's avatar
Tim Janik committed
1001
1002
  g_return_if_fail (clist != NULL);
  g_return_if_fail (GTK_IS_CLIST (clist));
1003
1004
  g_return_if_fail (columns > 0);
  g_return_if_fail (GTK_OBJECT_CONSTRUCTED (clist) == FALSE);
1005

1006
1007
  /* mark the object as constructed */
  gtk_object_constructed (GTK_OBJECT (clist));
1008

1009
1010
1011
1012
1013
1014
  /* initalize memory chunks, if this has not been done by any
   * possibly derived widget
   */
  if (!clist->row_mem_chunk)
    clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
					    sizeof (GtkCListRow),
1015
1016
					    sizeof (GtkCListRow) *
					    CLIST_OPTIMUM_SIZE, 
1017
					    G_ALLOC_AND_FREE);
1018

1019
1020
1021
  if (!clist->cell_mem_chunk)
    clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
					     sizeof (GtkCell) * columns,
1022
1023
					     sizeof (GtkCell) * columns *
					     CLIST_OPTIMUM_SIZE, 
1024
					     G_ALLOC_AND_FREE);
1025

1026
1027
1028
  /* set number of columns, allocate memory */
  clist->columns = columns;
  clist->column = columns_new (clist);
1029

1030
1031
1032
1033
  /* there needs to be at least one column button 
   * because there is alot of code that will break if it
   * isn't there*/
  column_button_create (clist, 0);
1034

1035
1036
  if (titles)
    {
1037
1038
      guint i;
      
1039
      GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
1040
1041
1042
1043
1044
      for (i = 0; i < columns; i++)
	gtk_clist_set_column_title (clist, i, titles[i]);
    }
  else
    {
1045
      GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
1046
1047
1048
    }
}

1049
/* GTKCLIST PUBLIC INTERFACE
1050
 *   gtk_clist_new
1051
 *   gtk_clist_new_with_titles
1052
1053
1054
1055
 *   gtk_clist_set_hadjustment
 *   gtk_clist_set_vadjustment
 *   gtk_clist_get_hadjustment
 *   gtk_clist_get_vadjustment
1056
1057
1058
1059
 *   gtk_clist_set_shadow_type
 *   gtk_clist_set_selection_mode
 *   gtk_clist_freeze
 *   gtk_clist_thaw
1060
 */
1061
GtkWidget*
1062
gtk_clist_new (gint columns)
1063
{
1064
  return gtk_clist_new_with_titles (columns, NULL);
1065
}
1066
 
1067
GtkWidget*
1068
gtk_clist_new_with_titles (gint   columns,
1069
			   gchar *titles[])
1070
1071
{
  GtkWidget *widget;
1072

1073
1074
  widget = gtk_type_new (GTK_TYPE_CLIST);
  gtk_clist_construct (GTK_CLIST (widget), columns, titles);
1075

1076
1077
  return widget;
}
1078

1079
1080
1081
1082
void
gtk_clist_set_hadjustment (GtkCList      *clist,
			   GtkAdjustment *adjustment)
{
1083
  GtkAdjustment *old_adjustment;
1084

1085
1086
1087
1088
1089
  g_return_if_fail (clist != NULL);
  g_return_if_fail (GTK_IS_CLIST (clist));
  if (adjustment)
    g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
  
1090
1091
1092
1093
  if (clist->hadjustment == adjustment)
    return;
  
  old_adjustment = clist->hadjustment;
1094

1095
  if (clist->hadjustment)
1096
1097
1098
1099
    {
      gtk_signal_disconnect_by_data (GTK_OBJECT (clist->hadjustment), clist);
      gtk_object_unref (GTK_OBJECT (clist->hadjustment));
    }
1100

1101
  clist->hadjustment = adjustment;
1102

1103
  if (clist->hadjustment)
1104
1105
1106
    {
      gtk_object_ref (GTK_OBJECT (clist->hadjustment));
      gtk_object_sink (GTK_OBJECT (clist->hadjustment));
1107

1108
1109
1110
1111
1112
1113
1114
      gtk_signal_connect (GTK_OBJECT (clist->hadjustment), "changed",
			  (GtkSignalFunc) hadjustment_changed,
			  (gpointer) clist);
      gtk_signal_connect (GTK_OBJECT (clist->hadjustment), "value_changed",
			  (GtkSignalFunc) hadjustment_value_changed,
			  (gpointer) clist);
    }
1115

1116
1117
  if (!clist->hadjustment || !old_adjustment)
    gtk_widget_queue_resize (GTK_WIDGET (clist));
1118
1119
1120
1121
1122
1123
1124
}

GtkAdjustment *
gtk_clist_get_hadjustment (GtkCList *clist)
{
  g_return_val_if_fail (clist != NULL, NULL);
  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1125

1126
1127
1128
1129
1130
1131
1132
  return clist->hadjustment;
}

void
gtk_clist_set_vadjustment (GtkCList      *clist,
			   GtkAdjustment *adjustment)
{
1133
  GtkAdjustment *old_adjustment;
1134

1135
1136
1137
1138
  g_return_if_fail (clist != NULL);
  g_return_if_fail (GTK_IS_CLIST (clist));
  if (adjustment)
    g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
1139

1140
1141
  if (clist->vadjustment == adjustment)
    return;
1142
  
1143
  old_adjustment = clist->vadjustment;