gtktreeview.c 376 KB
Newer Older
1 2 3
/* gtktreeview.c
 * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
 *
4
 * This library is free software; you can redistribute it and/or
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * 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
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */


21
#include <config.h>
Manish Singh's avatar
Manish Singh committed
22 23 24
#include <string.h>
#include <gdk/gdkkeysyms.h>

25
#include "gtkalias.h"
26 27
#include "gtktreeview.h"
#include "gtkrbtree.h"
Havoc Pennington's avatar
Havoc Pennington committed
28
#include "gtktreednd.h"
29 30 31
#include "gtktreeprivate.h"
#include "gtkcellrenderer.h"
#include "gtkmain.h"
32
#include "gtkmarshalers.h"
33 34 35
#include "gtkbutton.h"
#include "gtkalignment.h"
#include "gtklabel.h"
Havoc Pennington's avatar
Havoc Pennington committed
36
#include "gtkhbox.h"
Jonathan Blandford's avatar
Jonathan Blandford committed
37
#include "gtkvbox.h"
Havoc Pennington's avatar
Havoc Pennington committed
38
#include "gtkarrow.h"
39
#include "gtkintl.h"
40
#include "gtkbindings.h"
41 42
#include "gtkcontainer.h"
#include "gtkentry.h"
43
#include "gtkframe.h"
Jonathan Blandford's avatar
Jonathan Blandford committed
44
#include "gtktreemodelsort.h"
45

Jonathan Blandford's avatar
Jonathan Blandford committed
46
#define GTK_TREE_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5)
47
#define GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC (GTK_TREE_VIEW_PRIORITY_VALIDATE + 2)
Jonathan Blandford's avatar
Jonathan Blandford committed
48
#define GTK_TREE_VIEW_NUM_ROWS_PER_IDLE 500
49
#define SCROLL_EDGE_SIZE 15
50
#define EXPANDER_EXTRA_PADDING 4
Jonathan Blandford's avatar
Jonathan Blandford committed
51
#define GTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT 5000
52 53
#define AUTO_EXPAND_TIMEOUT 500

Havoc Pennington's avatar
Havoc Pennington committed
54 55 56 57 58 59 60
/* The "background" areas of all rows/cells add up to cover the entire tree.
 * The background includes all inter-row and inter-cell spacing.
 * The "cell" areas are the cell_area passed in to gtk_cell_renderer_render(),
 * i.e. just the cells, no spacing.
 */

#define BACKGROUND_HEIGHT(node) (GTK_RBNODE_GET_HEIGHT (node))
Kristian Rietveld's avatar
Kristian Rietveld committed
61
#define CELL_HEIGHT(node, separator) ((BACKGROUND_HEIGHT (node)) - (separator))
Havoc Pennington's avatar
Havoc Pennington committed
62

63 64
#define TREE_WINDOW_Y_TO_RBTREE_Y(tree_view,y) ((y) + tree_view->priv->dy)
#define RBTREE_Y_TO_TREE_WINDOW_Y(tree_view,y) ((y) - tree_view->priv->dy)
65 66 67 68

/* This is in Window coordinates */
#define BACKGROUND_FIRST_PIXEL(tree_view,tree,node) (RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, _gtk_rbtree_node_find_offset ((tree), (node))))
#define CELL_FIRST_PIXEL(tree_view,tree,node,separator) (BACKGROUND_FIRST_PIXEL (tree_view,tree,node) + separator/2)
69

70 71
#define ROW_HEIGHT(tree_view,height) \
  ((height > 0) ? (height) : (tree_view)->priv->expander_size)
72

73

74
typedef struct _GtkTreeViewChild GtkTreeViewChild;
75 76 77 78 79
struct _GtkTreeViewChild
{
  GtkWidget *widget;
  gint x;
  gint y;
80 81
  gint width;
  gint height;
82 83
};

Jonathan Blandford's avatar
Jonathan Blandford committed
84

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
typedef struct _TreeViewDragInfo TreeViewDragInfo;
struct _TreeViewDragInfo
{
  GdkModifierType start_button_mask;
  GtkTargetList *source_target_list;
  GdkDragAction source_actions;

  GtkTargetList *dest_target_list;

  guint source_set : 1;
  guint dest_set : 1;
};


/* Signals */
100 101 102
enum
{
  ROW_ACTIVATED,
103 104 105 106
  TEST_EXPAND_ROW,
  TEST_COLLAPSE_ROW,
  ROW_EXPANDED,
  ROW_COLLAPSED,
107
  COLUMNS_CHANGED,
108
  CURSOR_CHANGED,
109
  MOVE_CURSOR,
110
  SELECT_ALL,
111
  UNSELECT_ALL,
112
  SELECT_CURSOR_ROW,
113 114 115
  TOGGLE_CURSOR_ROW,
  EXPAND_COLLAPSE_CURSOR_ROW,
  SELECT_CURSOR_PARENT,
116
  START_INTERACTIVE_SEARCH,
117 118 119
  LAST_SIGNAL
};

120
/* Properties */
121 122 123 124 125 126 127 128
enum {
  PROP_0,
  PROP_MODEL,
  PROP_HADJUSTMENT,
  PROP_VADJUSTMENT,
  PROP_HEADERS_VISIBLE,
  PROP_HEADERS_CLICKABLE,
  PROP_EXPANDER_COLUMN,
129
  PROP_REORDERABLE,
130 131
  PROP_RULES_HINT,
  PROP_ENABLE_SEARCH,
132
  PROP_SEARCH_COLUMN,
133
  PROP_FIXED_HEIGHT_MODE,
134 135
  PROP_HOVER_SELECTION,
  PROP_HOVER_EXPAND
136
};
137 138

static void     gtk_tree_view_class_init           (GtkTreeViewClass *klass);
139 140 141 142
static void     gtk_tree_view_init                 (GtkTreeView      *tree_view);

/* object signals */
static void     gtk_tree_view_finalize             (GObject          *object);
143 144 145
static void     gtk_tree_view_set_property         (GObject         *object,
						    guint            prop_id,
						    const GValue    *value,
Jonathan Blandford's avatar
Jonathan Blandford committed
146
						    GParamSpec      *pspec);
147 148 149
static void     gtk_tree_view_get_property         (GObject         *object,
						    guint            prop_id,
						    GValue          *value,
Jonathan Blandford's avatar
Jonathan Blandford committed
150
						    GParamSpec      *pspec);
151

152
/* gtkobject signals */
Jonathan Blandford's avatar
Jonathan Blandford committed
153 154
static void     gtk_tree_view_destroy              (GtkObject        *object);

155
/* gtkwidget signals */
156 157 158 159 160 161 162 163 164
static void     gtk_tree_view_realize              (GtkWidget        *widget);
static void     gtk_tree_view_unrealize            (GtkWidget        *widget);
static void     gtk_tree_view_map                  (GtkWidget        *widget);
static void     gtk_tree_view_size_request         (GtkWidget        *widget,
						    GtkRequisition   *requisition);
static void     gtk_tree_view_size_allocate        (GtkWidget        *widget,
						    GtkAllocation    *allocation);
static gboolean gtk_tree_view_expose               (GtkWidget        *widget,
						    GdkEventExpose   *event);
165 166
static gboolean gtk_tree_view_key_press            (GtkWidget        *widget,
						    GdkEventKey      *event);
Jonathan Blandford's avatar
Jonathan Blandford committed
167 168
static gboolean gtk_tree_view_key_release          (GtkWidget        *widget,
						    GdkEventKey      *event);
169 170 171 172 173 174 175 176 177 178
static gboolean gtk_tree_view_motion               (GtkWidget        *widget,
						    GdkEventMotion   *event);
static gboolean gtk_tree_view_enter_notify         (GtkWidget        *widget,
						    GdkEventCrossing *event);
static gboolean gtk_tree_view_leave_notify         (GtkWidget        *widget,
						    GdkEventCrossing *event);
static gboolean gtk_tree_view_button_press         (GtkWidget        *widget,
						    GdkEventButton   *event);
static gboolean gtk_tree_view_button_release       (GtkWidget        *widget,
						    GdkEventButton   *event);
179 180 181 182 183
#if 0
static gboolean gtk_tree_view_configure            (GtkWidget         *widget,
						    GdkEventConfigure *event);
#endif

184 185
static void     gtk_tree_view_set_focus_child      (GtkContainer     *container,
						    GtkWidget        *child);
186 187
static gint     gtk_tree_view_focus_out            (GtkWidget        *widget,
						    GdkEventFocus    *event);
188
static gint     gtk_tree_view_focus                (GtkWidget        *widget,
189
						    GtkDirectionType  direction);
190
static void     gtk_tree_view_grab_focus           (GtkWidget        *widget);
Kristian Rietveld's avatar
Kristian Rietveld committed
191 192
static void     gtk_tree_view_style_set            (GtkWidget        *widget,
						    GtkStyle         *previous_style);
193 194
static void     gtk_tree_view_grab_notify          (GtkWidget        *widget,
						    gboolean          was_grabbed);
195 196 197 198 199 200 201 202 203

/* container signals */
static void     gtk_tree_view_remove               (GtkContainer     *container,
						    GtkWidget        *widget);
static void     gtk_tree_view_forall               (GtkContainer     *container,
						    gboolean          include_internals,
						    GtkCallback       callback,
						    gpointer          callback_data);

Havoc Pennington's avatar
Havoc Pennington committed
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
/* Source side drag signals */
static void gtk_tree_view_drag_begin       (GtkWidget        *widget,
                                            GdkDragContext   *context);
static void gtk_tree_view_drag_end         (GtkWidget        *widget,
                                            GdkDragContext   *context);
static void gtk_tree_view_drag_data_get    (GtkWidget        *widget,
                                            GdkDragContext   *context,
                                            GtkSelectionData *selection_data,
                                            guint             info,
                                            guint             time);
static void gtk_tree_view_drag_data_delete (GtkWidget        *widget,
                                            GdkDragContext   *context);

/* Target side drag signals */
static void     gtk_tree_view_drag_leave         (GtkWidget        *widget,
                                                  GdkDragContext   *context,
                                                  guint             time);
static gboolean gtk_tree_view_drag_motion        (GtkWidget        *widget,
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  guint             time);
static gboolean gtk_tree_view_drag_drop          (GtkWidget        *widget,
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  guint             time);
static void     gtk_tree_view_drag_data_received (GtkWidget        *widget,
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  GtkSelectionData *selection_data,
                                                  guint             info,
                                                  guint             time);

239
/* tree_model signals */
240 241 242
static void gtk_tree_view_set_adjustments                 (GtkTreeView     *tree_view,
							   GtkAdjustment   *hadj,
							   GtkAdjustment   *vadj);
243
static gboolean gtk_tree_view_real_move_cursor            (GtkTreeView     *tree_view,
244
							   GtkMovementStep  step,
245
							   gint             count);
246 247 248
static gboolean gtk_tree_view_real_select_all             (GtkTreeView     *tree_view);
static gboolean gtk_tree_view_real_unselect_all           (GtkTreeView     *tree_view);
static gboolean gtk_tree_view_real_select_cursor_row      (GtkTreeView     *tree_view,
249
							   gboolean         start_editing);
250 251 252 253 254 255
static gboolean gtk_tree_view_real_toggle_cursor_row      (GtkTreeView     *tree_view);
static gboolean gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView     *tree_view,
							       gboolean         logical,
							       gboolean         expand,
							       gboolean         open_all);
static gboolean gtk_tree_view_real_select_cursor_parent   (GtkTreeView     *tree_view);
256
static void gtk_tree_view_row_changed                     (GtkTreeModel    *model,
257 258 259
							   GtkTreePath     *path,
							   GtkTreeIter     *iter,
							   gpointer         data);
260
static void gtk_tree_view_row_inserted                    (GtkTreeModel    *model,
261 262 263
							   GtkTreePath     *path,
							   GtkTreeIter     *iter,
							   gpointer         data);
264
static void gtk_tree_view_row_has_child_toggled           (GtkTreeModel    *model,
265 266 267
							   GtkTreePath     *path,
							   GtkTreeIter     *iter,
							   gpointer         data);
268
static void gtk_tree_view_row_deleted                     (GtkTreeModel    *model,
269 270
							   GtkTreePath     *path,
							   gpointer         data);
271
static void gtk_tree_view_rows_reordered                  (GtkTreeModel    *model,
272 273 274 275 276
							   GtkTreePath     *parent,
							   GtkTreeIter     *iter,
							   gint            *new_order,
							   gpointer         data);

Jonathan Blandford's avatar
Jonathan Blandford committed
277 278 279 280 281 282 283 284
/* Incremental reflow */
static gboolean validate_row             (GtkTreeView *tree_view,
					  GtkRBTree   *tree,
					  GtkRBNode   *node,
					  GtkTreeIter *iter,
					  GtkTreePath *path);
static void     validate_visible_area    (GtkTreeView *tree_view);
static gboolean validate_rows_handler    (GtkTreeView *tree_view);
285
static gboolean validate_rows            (GtkTreeView *tree_view);
Jonathan Blandford's avatar
Jonathan Blandford committed
286 287
static gboolean presize_handler_callback (gpointer     data);
static void     install_presize_handler  (GtkTreeView *tree_view);
288
static void     install_scroll_sync_handler (GtkTreeView *tree_view);
289
static void	gtk_tree_view_dy_to_top_row (GtkTreeView *tree_view);
290
static void     gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view);
291
static void     invalidate_empty_focus      (GtkTreeView *tree_view);
292

293
/* Internal functions */
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
static gboolean gtk_tree_view_is_expander_column             (GtkTreeView       *tree_view,
							      GtkTreeViewColumn *column);
static void     gtk_tree_view_add_move_binding               (GtkBindingSet     *binding_set,
							      guint              keyval,
							      guint              modmask,
							      GtkMovementStep    step,
							      gint               count);
static gint     gtk_tree_view_unref_and_check_selection_tree (GtkTreeView       *tree_view,
							      GtkRBTree         *tree);
static void     gtk_tree_view_queue_draw_path                (GtkTreeView       *tree_view,
							      GtkTreePath       *path,
							      GdkRectangle      *clip_rect);
static void     gtk_tree_view_queue_draw_arrow               (GtkTreeView       *tree_view,
							      GtkRBTree         *tree,
							      GtkRBNode         *node,
							      GdkRectangle      *clip_rect);
static void     gtk_tree_view_draw_arrow                     (GtkTreeView       *tree_view,
							      GtkRBTree         *tree,
							      GtkRBNode         *node,
							      gint               x,
							      gint               y);
static void     gtk_tree_view_get_arrow_xrange               (GtkTreeView       *tree_view,
316
							      GtkRBTree         *tree,
317 318 319 320 321 322 323 324 325 326 327
							      gint              *x1,
							      gint              *x2);
static gint     gtk_tree_view_new_column_width               (GtkTreeView       *tree_view,
							      gint               i,
							      gint              *x);
static void     gtk_tree_view_adjustment_changed             (GtkAdjustment     *adjustment,
							      GtkTreeView       *tree_view);
static void     gtk_tree_view_build_tree                     (GtkTreeView       *tree_view,
							      GtkRBTree         *tree,
							      GtkTreeIter       *iter,
							      gint               depth,
Jonathan Blandford's avatar
Jonathan Blandford committed
328
							      gboolean           recurse);
329 330 331
static gboolean gtk_tree_view_discover_dirty_iter            (GtkTreeView       *tree_view,
							      GtkTreeIter       *iter,
							      gint               depth,
332 333
							      gint              *height,
							      GtkRBNode         *node);
334 335 336 337 338 339 340
static void     gtk_tree_view_discover_dirty                 (GtkTreeView       *tree_view,
							      GtkRBTree         *tree,
							      GtkTreeIter       *iter,
							      gint               depth);
static void     gtk_tree_view_clamp_node_visible             (GtkTreeView       *tree_view,
							      GtkRBTree         *tree,
							      GtkRBNode         *node);
341 342
static void     gtk_tree_view_clamp_column_visible           (GtkTreeView       *tree_view,
							      GtkTreeViewColumn *column);
343 344 345 346 347 348 349 350 351 352 353 354 355 356
static gboolean gtk_tree_view_maybe_begin_dragging_row       (GtkTreeView       *tree_view,
							      GdkEventMotion    *event);
static void     gtk_tree_view_focus_to_cursor                (GtkTreeView       *tree_view);
static void     gtk_tree_view_move_cursor_up_down            (GtkTreeView       *tree_view,
							      gint               count);
static void     gtk_tree_view_move_cursor_page_up_down       (GtkTreeView       *tree_view,
							      gint               count);
static void     gtk_tree_view_move_cursor_left_right         (GtkTreeView       *tree_view,
							      gint               count);
static void     gtk_tree_view_move_cursor_start_end          (GtkTreeView       *tree_view,
							      gint               count);
static gboolean gtk_tree_view_real_collapse_row              (GtkTreeView       *tree_view,
							      GtkTreePath       *path,
							      GtkRBTree         *tree,
357 358
							      GtkRBNode         *node,
							      gboolean           animate);
359 360 361 362
static gboolean gtk_tree_view_real_expand_row                (GtkTreeView       *tree_view,
							      GtkTreePath       *path,
							      GtkRBTree         *tree,
							      GtkRBNode         *node,
363 364
							      gboolean           open_all,
							      gboolean           animate);
365 366
static void     gtk_tree_view_real_set_cursor                (GtkTreeView       *tree_view,
							      GtkTreePath       *path,
367 368
							      gboolean           clear_and_select,
							      gboolean           clamp_node);
369
static gboolean gtk_tree_view_has_special_cell               (GtkTreeView       *tree_view);
370 371 372
static void     column_sizing_notify                         (GObject           *object,
                                                              GParamSpec        *pspec,
                                                              gpointer           data);
Kristian Rietveld's avatar
Kristian Rietveld committed
373
static gboolean expand_collapse_timeout                      (gpointer           data);
Kristian Rietveld's avatar
Kristian Rietveld committed
374
static gboolean do_expand_collapse                           (GtkTreeView       *tree_view);
Kristian Rietveld's avatar
Kristian Rietveld committed
375

376
/* interactive search */
Jonathan Blandford's avatar
Jonathan Blandford committed
377
static void     gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view);
378
static void     gtk_tree_view_search_dialog_hide     (GtkWidget        *search_dialog,
379 380 381
							 GtkTreeView      *tree_view);
static void     gtk_tree_view_search_position_func      (GtkTreeView      *tree_view,
							 GtkWidget        *search_dialog);
382 383 384
static void     gtk_tree_view_search_disable_popdown    (GtkEntry         *entry,
							 GtkMenu          *menu,
							 gpointer          data);
Jonathan Blandford's avatar
Jonathan Blandford committed
385 386
static void     gtk_tree_view_search_preedit_changed    (GtkIMContext     *im_context,
							 GtkTreeView      *tree_view);
387 388
static void     gtk_tree_view_search_activate           (GtkEntry         *entry,
							 GtkTreeView      *tree_view);
389 390 391
static gboolean gtk_tree_view_real_search_enable_popdown(gpointer          data);
static void     gtk_tree_view_search_enable_popdown     (GtkWidget        *widget,
							 gpointer          data);
392 393 394 395 396 397 398 399 400 401 402 403 404 405
static gboolean gtk_tree_view_search_delete_event       (GtkWidget        *widget,
							 GdkEventAny      *event,
							 GtkTreeView      *tree_view);
static gboolean gtk_tree_view_search_button_press_event (GtkWidget        *widget,
							 GdkEventButton   *event,
							 GtkTreeView      *tree_view);
static gboolean gtk_tree_view_search_key_press_event    (GtkWidget        *entry,
							 GdkEventKey      *event,
							 GtkTreeView      *tree_view);
static void     gtk_tree_view_search_move               (GtkWidget        *window,
							 GtkTreeView      *tree_view,
							 gboolean          up);
static gboolean gtk_tree_view_search_equal_func         (GtkTreeModel     *model,
							 gint              column,
406
							 const gchar      *key,
407 408
							 GtkTreeIter      *iter,
							 gpointer          search_data);
409 410 411
static gboolean gtk_tree_view_search_iter               (GtkTreeModel     *model,
							 GtkTreeSelection *selection,
							 GtkTreeIter      *iter,
412
							 const gchar      *text,
413 414 415 416
							 gint             *count,
							 gint              n);
static void     gtk_tree_view_search_init               (GtkWidget        *entry,
							 GtkTreeView      *tree_view);
417 418 419 420 421 422
static void     gtk_tree_view_put                       (GtkTreeView      *tree_view,
							 GtkWidget        *child_widget,
							 gint              x,
							 gint              y,
							 gint              width,
							 gint              height);
423 424 425 426 427 428 429 430 431
static gboolean gtk_tree_view_start_editing             (GtkTreeView      *tree_view,
							 GtkTreePath      *cursor_path);
static void gtk_tree_view_real_start_editing (GtkTreeView       *tree_view,
					      GtkTreeViewColumn *column,
					      GtkTreePath       *path,
					      GtkCellEditable   *cell_editable,
					      GdkRectangle      *cell_area,
					      GdkEvent          *event,
					      guint              flags);
Jonathan Blandford's avatar
Jonathan Blandford committed
432 433
static void gtk_tree_view_stop_editing                  (GtkTreeView *tree_view,
							 gboolean     cancel_editing);
Jonathan Blandford's avatar
Jonathan Blandford committed
434 435 436
static gboolean gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view,
							     gboolean     keybinding);
static gboolean gtk_tree_view_start_interactive_search      (GtkTreeView *tree_view);
437 438 439
static GtkTreeViewColumn *gtk_tree_view_get_drop_column (GtkTreeView       *tree_view,
							 GtkTreeViewColumn *column,
							 gint               drop_position);
440

441 442 443 444 445
static void gtk_tree_view_tree_window_to_tree_coords (GtkTreeView *tree_view,
						      gint         wx,
						      gint         wy,
						      gint        *tx,
						      gint        *ty);
446

447 448

static GtkContainerClass *parent_class = NULL;
449
static guint tree_view_signals [LAST_SIGNAL] = { 0 };
450

451 452 453 454 455


/* GType Methods
 */

Manish Singh's avatar
Manish Singh committed
456
GType
457 458
gtk_tree_view_get_type (void)
{
Manish Singh's avatar
Manish Singh committed
459
  static GType tree_view_type = 0;
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475

  if (!tree_view_type)
    {
      static const GTypeInfo tree_view_info =
      {
        sizeof (GtkTreeViewClass),
	NULL,		/* base_init */
	NULL,		/* base_finalize */
        (GClassInitFunc) gtk_tree_view_class_init,
	NULL,		/* class_finalize */
	NULL,		/* class_data */
        sizeof (GtkTreeView),
	0,              /* n_preallocs */
        (GInstanceInitFunc) gtk_tree_view_init
      };

Manish Singh's avatar
Manish Singh committed
476 477 478
      tree_view_type =
	g_type_register_static (GTK_TYPE_CONTAINER, "GtkTreeView",
				&tree_view_info, 0);
479 480 481 482 483 484 485 486
    }

  return tree_view_type;
}

static void
gtk_tree_view_class_init (GtkTreeViewClass *class)
{
487
  GObjectClass *o_class;
488 489 490
  GtkObjectClass *object_class;
  GtkWidgetClass *widget_class;
  GtkContainerClass *container_class;
491
  GtkBindingSet *binding_set;
492

493
  parent_class = g_type_class_peek_parent (class);
494
  binding_set = gtk_binding_set_by_class (class);
495

496 497 498 499 500
  o_class = (GObjectClass *) class;
  object_class = (GtkObjectClass *) class;
  widget_class = (GtkWidgetClass *) class;
  container_class = (GtkContainerClass *) class;

501
  /* GObject signals */
502 503
  o_class->set_property = gtk_tree_view_set_property;
  o_class->get_property = gtk_tree_view_get_property;
504
  o_class->finalize = gtk_tree_view_finalize;
505

506
  /* GtkObject signals */
Jonathan Blandford's avatar
Jonathan Blandford committed
507
  object_class->destroy = gtk_tree_view_destroy;
508

509 510
  /* GtkWidget signals */
  widget_class->map = gtk_tree_view_map;
511 512 513 514
  widget_class->realize = gtk_tree_view_realize;
  widget_class->unrealize = gtk_tree_view_unrealize;
  widget_class->size_request = gtk_tree_view_size_request;
  widget_class->size_allocate = gtk_tree_view_size_allocate;
515 516
  widget_class->button_press_event = gtk_tree_view_button_press;
  widget_class->button_release_event = gtk_tree_view_button_release;
517
  /*widget_class->configure_event = gtk_tree_view_configure;*/
518
  widget_class->motion_notify_event = gtk_tree_view_motion;
519
  widget_class->expose_event = gtk_tree_view_expose;
520
  widget_class->key_press_event = gtk_tree_view_key_press;
Jonathan Blandford's avatar
Jonathan Blandford committed
521
  widget_class->key_release_event = gtk_tree_view_key_release;
522 523 524
  widget_class->enter_notify_event = gtk_tree_view_enter_notify;
  widget_class->leave_notify_event = gtk_tree_view_leave_notify;
  widget_class->focus_out_event = gtk_tree_view_focus_out;
Havoc Pennington's avatar
Havoc Pennington committed
525 526 527 528 529 530 531 532
  widget_class->drag_begin = gtk_tree_view_drag_begin;
  widget_class->drag_end = gtk_tree_view_drag_end;
  widget_class->drag_data_get = gtk_tree_view_drag_data_get;
  widget_class->drag_data_delete = gtk_tree_view_drag_data_delete;
  widget_class->drag_leave = gtk_tree_view_drag_leave;
  widget_class->drag_motion = gtk_tree_view_drag_motion;
  widget_class->drag_drop = gtk_tree_view_drag_drop;
  widget_class->drag_data_received = gtk_tree_view_drag_data_received;
533
  widget_class->focus = gtk_tree_view_focus;
534
  widget_class->grab_focus = gtk_tree_view_grab_focus;
Kristian Rietveld's avatar
Kristian Rietveld committed
535
  widget_class->style_set = gtk_tree_view_style_set;
536
  widget_class->grab_notify = gtk_tree_view_grab_notify;
537

538
  /* GtkContainer signals */
539
  container_class->remove = gtk_tree_view_remove;
540 541
  container_class->forall = gtk_tree_view_forall;
  container_class->set_focus_child = gtk_tree_view_set_focus_child;
542 543

  class->set_scroll_adjustments = gtk_tree_view_set_adjustments;
544
  class->move_cursor = gtk_tree_view_real_move_cursor;
545
  class->select_all = gtk_tree_view_real_select_all;
546
  class->unselect_all = gtk_tree_view_real_unselect_all;
547
  class->select_cursor_row = gtk_tree_view_real_select_cursor_row;
548 549 550
  class->toggle_cursor_row = gtk_tree_view_real_toggle_cursor_row;
  class->expand_collapse_cursor_row = gtk_tree_view_real_expand_collapse_cursor_row;
  class->select_cursor_parent = gtk_tree_view_real_select_cursor_parent;
Jonathan Blandford's avatar
Jonathan Blandford committed
551
  class->start_interactive_search = gtk_tree_view_start_interactive_search;
552

553
  /* Properties */
554

555 556
  g_object_class_install_property (o_class,
                                   PROP_MODEL,
Tim Janik's avatar
Tim Janik committed
557
                                   g_param_spec_object ("model",
558 559
							P_("TreeView Model"),
							P_("The model for the tree view"),
Tim Janik's avatar
Tim Janik committed
560 561
							GTK_TYPE_TREE_MODEL,
							G_PARAM_READWRITE));
Jonathan Blandford's avatar
Jonathan Blandford committed
562

563 564 565
  g_object_class_install_property (o_class,
                                   PROP_HADJUSTMENT,
                                   g_param_spec_object ("hadjustment",
566 567
							P_("Horizontal Adjustment"),
                                                        P_("Horizontal Adjustment for the widget"),
568 569 570 571 572 573
                                                        GTK_TYPE_ADJUSTMENT,
                                                        G_PARAM_READWRITE));

  g_object_class_install_property (o_class,
                                   PROP_VADJUSTMENT,
                                   g_param_spec_object ("vadjustment",
574 575
							P_("Vertical Adjustment"),
                                                        P_("Vertical Adjustment for the widget"),
576 577 578 579 580 581
                                                        GTK_TYPE_ADJUSTMENT,
                                                        G_PARAM_READWRITE));

  g_object_class_install_property (o_class,
                                   PROP_HEADERS_VISIBLE,
                                   g_param_spec_boolean ("headers_visible",
582
							 P_("Headers Visible"),
583
							 P_("Show the column header buttons"),
584
							 TRUE,
585 586 587 588 589
							 G_PARAM_READWRITE));

  g_object_class_install_property (o_class,
                                   PROP_HEADERS_CLICKABLE,
                                   g_param_spec_boolean ("headers_clickable",
590 591
							 P_("Headers Clickable"),
							 P_("Column headers respond to click events"),
592
							 FALSE,
593
							 G_PARAM_READWRITE));
594 595 596

  g_object_class_install_property (o_class,
                                   PROP_EXPANDER_COLUMN,
597
                                   g_param_spec_object ("expander_column",
598 599
							P_("Expander Column"),
							P_("Set the column for the expander column"),
600 601
							GTK_TYPE_TREE_VIEW_COLUMN,
							G_PARAM_READWRITE));
602

603 604 605
  g_object_class_install_property (o_class,
                                   PROP_REORDERABLE,
                                   g_param_spec_boolean ("reorderable",
606 607
							 P_("Reorderable"),
							 P_("View is reorderable"),
608 609 610
							 FALSE,
							 G_PARAM_READWRITE));

611 612 613
  g_object_class_install_property (o_class,
                                   PROP_RULES_HINT,
                                   g_param_spec_boolean ("rules_hint",
614 615
							 P_("Rules Hint"),
							 P_("Set a hint to the theme engine to draw rows in alternating colors"),
616 617 618
							 FALSE,
							 G_PARAM_READWRITE));

619 620 621
    g_object_class_install_property (o_class,
				     PROP_ENABLE_SEARCH,
				     g_param_spec_boolean ("enable_search",
622 623
							   P_("Enable Search"),
							   P_("View allows user to search through columns interactively"),
624 625
							   TRUE,
							   G_PARAM_READWRITE));
626

627 628 629
    g_object_class_install_property (o_class,
				     PROP_SEARCH_COLUMN,
				     g_param_spec_int ("search_column",
630 631
						       P_("Search Column"),
						       P_("Model column to search through when searching through code"),
632 633
						       -1,
						       G_MAXINT,
634
						       -1,
635
						       G_PARAM_READWRITE));
636

637 638 639 640 641 642 643 644 645 646 647
    /**
     * GtkTreeView:fixed-height-mode:
     *
     * Setting the ::fixed-height-mode property to %TRUE speeds up 
     * #GtkTreeView by assuming that all rows have the same height. 
     * Only enable this option if all rows are the same height.  
     * Please see gtk_tree_view_set_fixed_height_mode() for more 
     * information on this option.
     *
     * Since: 2.4
     **/
648 649 650
    g_object_class_install_property (o_class,
                                     PROP_FIXED_HEIGHT_MODE,
                                     g_param_spec_boolean ("fixed_height_mode",
651 652
                                                           P_("Fixed Height Mode"),
                                                           P_("Speeds up GtkTreeView by assuming that all rows have the same height"),
653 654
                                                           FALSE,
                                                           G_PARAM_READWRITE));
655 656 657 658 659 660
    
    /**
     * GtkTreeView:hover-selection:
     * 
     * Enables of disables the hover selection mode of @tree_view.
     * Hover selection makes the selected row follow the pointer.
Matthias Clasen's avatar
Matthias Clasen committed
661 662 663
     * Currently, this works only for the selection modes 
     * %GTK_SELECTION_SINGLE and %GTK_SELECTION_BROWSE.
     *
664 665 666 667 668 669 670 671 672 673 674 675
     * This mode is primarily indended for treeviews in popups, e.g.
     * in #GtkComboBox or #GtkEntryCompletion.
     *
     * Since: 2.6
     */
    g_object_class_install_property (o_class,
                                     PROP_HOVER_SELECTION,
                                     g_param_spec_boolean ("hover_selection",
                                                           P_("Hover Selection"),
                                                           P_("Whether the selection should follow the pointer"),
                                                           FALSE,
                                                           G_PARAM_READWRITE));
676

677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
    /**
     * GtkTreeView:hover-expand:
     * 
     * Enables of disables the hover expansion mode of @tree_view.
     * Hover expansion makes rows expand or collaps if the pointer moves 
     * over them.
     *
     * This mode is primarily indended for treeviews in popups, e.g.
     * in #GtkComboBox or #GtkEntryCompletion.
     *
     * Since: 2.6
     */
    g_object_class_install_property (o_class,
                                     PROP_HOVER_EXPAND,
                                     g_param_spec_boolean ("hover_expand",
                                                           P_("Hover Expand"),
693
                                                           P_("Whether rows should be expanded/collapsed when the pointer moves over them"),
694 695 696
                                                           FALSE,
                                                           G_PARAM_READWRITE));

697
  /* Style properties */
698
#define _TREE_VIEW_EXPANDER_SIZE 12
699
#define _TREE_VIEW_VERTICAL_SEPARATOR 2
700
#define _TREE_VIEW_HORIZONTAL_SEPARATOR 2
701
    
702
  gtk_widget_class_install_style_property (widget_class,
703
					   g_param_spec_int ("expander_size",
704 705
							     P_("Expander Size"),
							     P_("Size of the expander arrow"),
706 707
							     0,
							     G_MAXINT,
708
							     _TREE_VIEW_EXPANDER_SIZE,
709
							     G_PARAM_READABLE));
710

711 712
  gtk_widget_class_install_style_property (widget_class,
					   g_param_spec_int ("vertical_separator",
713 714
							     P_("Vertical Separator Width"),
							     P_("Vertical space between cells.  Must be an even number"),
715 716 717 718
							     0,
							     G_MAXINT,
							     _TREE_VIEW_VERTICAL_SEPARATOR,
							     G_PARAM_READABLE));
719

720
  gtk_widget_class_install_style_property (widget_class,
721
					   g_param_spec_int ("horizontal_separator",
722 723
							     P_("Horizontal Separator Width"),
							     P_("Horizontal space between cells.  Must be an even number"),
724 725 726 727 728
							     0,
							     G_MAXINT,
							     _TREE_VIEW_HORIZONTAL_SEPARATOR,
							     G_PARAM_READABLE));

729 730
  gtk_widget_class_install_style_property (widget_class,
					   g_param_spec_boolean ("allow_rules",
731 732
								 P_("Allow Rules"),
								 P_("Allow drawing of alternating color rows"),
733 734 735
								 TRUE,
								 G_PARAM_READABLE));

736 737
  gtk_widget_class_install_style_property (widget_class,
					   g_param_spec_boolean ("indent_expanders",
738 739
								 P_("Indent Expanders"),
								 P_("Make the expanders indented"),
740
								 TRUE,
741
								 G_PARAM_READABLE));
Manish Singh's avatar
Manish Singh committed
742

743 744
  gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_boxed ("even_row_color",
745 746
                                                               P_("Even Row Color"),
                                                               P_("Color to use for even rows"),
747 748 749 750 751
							       GDK_TYPE_COLOR,
G_PARAM_READABLE));

  gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_boxed ("odd_row_color",
752 753
                                                               P_("Odd Row Color"),
                                                               P_("Color to use for odd rows"),
754 755 756
							       GDK_TYPE_COLOR,
G_PARAM_READABLE));

757
  /* Signals */
758
  widget_class->set_scroll_adjustments_signal =
Manish Singh's avatar
Manish Singh committed
759 760 761 762 763 764 765 766 767
    g_signal_new ("set_scroll_adjustments",
		  G_TYPE_FROM_CLASS (o_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTreeViewClass, set_scroll_adjustments),
		  NULL, NULL,
		  _gtk_marshal_VOID__OBJECT_OBJECT,
		  G_TYPE_NONE, 2,
		  GTK_TYPE_ADJUSTMENT,
		  GTK_TYPE_ADJUSTMENT);
768

769
  tree_view_signals[ROW_ACTIVATED] =
Manish Singh's avatar
Manish Singh committed
770 771 772 773 774 775 776 777 778
    g_signal_new ("row_activated",
		  G_TYPE_FROM_CLASS (o_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTreeViewClass, row_activated),
		  NULL, NULL,
		  _gtk_marshal_VOID__BOXED_OBJECT,
		  G_TYPE_NONE, 2,
		  GTK_TYPE_TREE_PATH,
		  GTK_TYPE_TREE_VIEW_COLUMN);
779

780
  tree_view_signals[TEST_EXPAND_ROW] =
781
    g_signal_new ("test_expand_row",
Manish Singh's avatar
Manish Singh committed
782 783 784 785 786 787 788 789
		  G_TYPE_FROM_CLASS (o_class),
		  G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (GtkTreeViewClass, test_expand_row),
		  _gtk_boolean_handled_accumulator, NULL,
		  _gtk_marshal_BOOLEAN__BOXED_BOXED,
		  G_TYPE_BOOLEAN, 2,
		  GTK_TYPE_TREE_ITER,
		  GTK_TYPE_TREE_PATH);
790

791
  tree_view_signals[TEST_COLLAPSE_ROW] =
792
    g_signal_new ("test_collapse_row",
Manish Singh's avatar
Manish Singh committed
793 794 795 796 797 798 799 800
		  G_TYPE_FROM_CLASS (o_class),
		  G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (GtkTreeViewClass, test_collapse_row),
		  _gtk_boolean_handled_accumulator, NULL,
		  _gtk_marshal_BOOLEAN__BOXED_BOXED,
		  G_TYPE_BOOLEAN, 2,
		  GTK_TYPE_TREE_ITER,
		  GTK_TYPE_TREE_PATH);
801

802
  tree_view_signals[ROW_EXPANDED] =
803
    g_signal_new ("row_expanded",
Manish Singh's avatar
Manish Singh committed
804 805 806 807 808 809 810 811
		  G_TYPE_FROM_CLASS (o_class),
		  G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (GtkTreeViewClass, row_expanded),
		  NULL, NULL,
		  _gtk_marshal_VOID__BOXED_BOXED,
		  G_TYPE_NONE, 2,
		  GTK_TYPE_TREE_ITER,
		  GTK_TYPE_TREE_PATH);
812 813

  tree_view_signals[ROW_COLLAPSED] =
814
    g_signal_new ("row_collapsed",
Manish Singh's avatar
Manish Singh committed
815 816 817 818 819 820 821 822
		  G_TYPE_FROM_CLASS (o_class),
		  G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (GtkTreeViewClass, row_collapsed),
		  NULL, NULL,
		  _gtk_marshal_VOID__BOXED_BOXED,
		  G_TYPE_NONE, 2,
		  GTK_TYPE_TREE_ITER,
		  GTK_TYPE_TREE_PATH);
823

824
  tree_view_signals[COLUMNS_CHANGED] =
825
    g_signal_new ("columns_changed",
Manish Singh's avatar
Manish Singh committed
826 827 828 829 830 831
		  G_TYPE_FROM_CLASS (o_class),
		  G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (GtkTreeViewClass, columns_changed),
		  NULL, NULL,
		  _gtk_marshal_NONE__NONE,
		  G_TYPE_NONE, 0);
832

833 834
  tree_view_signals[CURSOR_CHANGED] =
    g_signal_new ("cursor_changed",
Manish Singh's avatar
Manish Singh committed
835 836 837 838 839 840
		  G_TYPE_FROM_CLASS (o_class),
		  G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (GtkTreeViewClass, cursor_changed),
		  NULL, NULL,
		  _gtk_marshal_NONE__NONE,
		  G_TYPE_NONE, 0);
841

842
  tree_view_signals[MOVE_CURSOR] =
843
    g_signal_new ("move_cursor",
Manish Singh's avatar
Manish Singh committed
844 845 846 847 848 849 850 851
		  G_TYPE_FROM_CLASS (object_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTreeViewClass, move_cursor),
		  NULL, NULL,
		  _gtk_marshal_BOOLEAN__ENUM_INT,
		  G_TYPE_BOOLEAN, 2,
		  GTK_TYPE_MOVEMENT_STEP,
		  G_TYPE_INT);
852

853 854
  tree_view_signals[SELECT_ALL] =
    g_signal_new ("select_all",
Manish Singh's avatar
Manish Singh committed
855 856 857 858
		  G_TYPE_FROM_CLASS (object_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTreeViewClass, select_all),
		  NULL, NULL,
859 860
		  _gtk_marshal_BOOLEAN__NONE,
		  G_TYPE_BOOLEAN, 0);
861

862 863 864
  tree_view_signals[UNSELECT_ALL] =
    g_signal_new ("unselect_all",
		  G_TYPE_FROM_CLASS (object_class),
Manish Singh's avatar
Manish Singh committed
865
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
866 867
		  G_STRUCT_OFFSET (GtkTreeViewClass, unselect_all),
		  NULL, NULL,
868 869
		  _gtk_marshal_BOOLEAN__NONE,
		  G_TYPE_BOOLEAN, 0);
870

871
  tree_view_signals[SELECT_CURSOR_ROW] =
872
    g_signal_new ("select_cursor_row",
Manish Singh's avatar
Manish Singh committed
873 874 875 876
		  G_TYPE_FROM_CLASS (object_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_row),
		  NULL, NULL,
877 878
		  _gtk_marshal_BOOLEAN__BOOLEAN,
		  G_TYPE_BOOLEAN, 1,
879
		  G_TYPE_BOOLEAN);
880

881
  tree_view_signals[TOGGLE_CURSOR_ROW] =
882
    g_signal_new ("toggle_cursor_row",
Manish Singh's avatar
Manish Singh committed
883 884 885 886
		  G_TYPE_FROM_CLASS (object_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTreeViewClass, toggle_cursor_row),
		  NULL, NULL,
887 888
		  _gtk_marshal_BOOLEAN__NONE,
		  G_TYPE_BOOLEAN, 0);
889

890
  tree_view_signals[EXPAND_COLLAPSE_CURSOR_ROW] =
891
    g_signal_new ("expand_collapse_cursor_row",
Manish Singh's avatar
Manish Singh committed
892 893 894 895
		  G_TYPE_FROM_CLASS (object_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTreeViewClass, expand_collapse_cursor_row),
		  NULL, NULL,
896 897
		  _gtk_marshal_BOOLEAN__BOOLEAN_BOOLEAN_BOOLEAN,
		  G_TYPE_BOOLEAN, 3,
Manish Singh's avatar
Manish Singh committed
898 899 900
		  G_TYPE_BOOLEAN,
		  G_TYPE_BOOLEAN,
		  G_TYPE_BOOLEAN);
901

902
  tree_view_signals[SELECT_CURSOR_PARENT] =
903
    g_signal_new ("select_cursor_parent",
Manish Singh's avatar
Manish Singh committed
904 905 906 907
		  G_TYPE_FROM_CLASS (object_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_parent),
		  NULL, NULL,
908 909
		  _gtk_marshal_BOOLEAN__NONE,
		  G_TYPE_BOOLEAN, 0);
910

911 912
  tree_view_signals[START_INTERACTIVE_SEARCH] =
    g_signal_new ("start_interactive_search",
Manish Singh's avatar
Manish Singh committed
913 914 915 916
		  G_TYPE_FROM_CLASS (object_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTreeViewClass, start_interactive_search),
		  NULL, NULL,
917 918
		  _gtk_marshal_BOOLEAN__NONE,
		  G_TYPE_BOOLEAN, 0);
919

920
  /* Key bindings */
921 922
  gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0,
				  GTK_MOVEMENT_DISPLAY_LINES, -1);
923 924
  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Up, 0,
				  GTK_MOVEMENT_DISPLAY_LINES, -1);
925 926 927

  gtk_tree_view_add_move_binding (binding_set, GDK_Down, 0,
				  GTK_MOVEMENT_DISPLAY_LINES, 1);
928 929
  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Down, 0,
				  GTK_MOVEMENT_DISPLAY_LINES, 1);
930 931 932 933 934 935 936 937 938

  gtk_tree_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK,
				  GTK_MOVEMENT_DISPLAY_LINES, -1);

  gtk_tree_view_add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK,
				  GTK_MOVEMENT_DISPLAY_LINES, 1);

  gtk_tree_view_add_move_binding (binding_set, GDK_Home, 0,
				  GTK_MOVEMENT_BUFFER_ENDS, -1);
939 940
  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Home, 0,
				  GTK_MOVEMENT_BUFFER_ENDS, -1);
941 942 943

  gtk_tree_view_add_move_binding (binding_set, GDK_End, 0,
				  GTK_MOVEMENT_BUFFER_ENDS, 1);
944 945
  gtk_tree_view_add_move_binding (binding_set, GDK_KP_End, 0,
				  GTK_MOVEMENT_BUFFER_ENDS, 1);
946 947 948

  gtk_tree_view_add_move_binding (binding_set, GDK_Page_Up, 0,
				  GTK_MOVEMENT_PAGES, -1);
949 950
  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Page_Up, 0,
				  GTK_MOVEMENT_PAGES, -1);
951 952 953

  gtk_tree_view_add_move_binding (binding_set, GDK_Page_Down, 0,
				  GTK_MOVEMENT_PAGES, 1);
954 955