source: trunk/third/gtk/gtk/gtktree.c @ 15781

Revision 15781, 32.2 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15780, which included commits to RCS files with non-trunk default branches.
RevLine 
[14481]1/* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20/*
21 * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22 * file for a list of people on the GTK+ Team.  See the ChangeLog
23 * files for a list of changes.  These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25 */
26
27#include "gtktree.h"
28#include "gtktreeitem.h"
29#include "gtkmain.h"
30#include "gtksignal.h"
31#include "gtklist.h"
32
33enum {
34  SELECTION_CHANGED,
35  SELECT_CHILD,
36  UNSELECT_CHILD,
37  LAST_SIGNAL
38};
39
40static void gtk_tree_class_init      (GtkTreeClass   *klass);
41static void gtk_tree_init            (GtkTree        *tree);
42static void gtk_tree_destroy         (GtkObject      *object);
43static void gtk_tree_map             (GtkWidget      *widget);
[15780]44static void gtk_tree_parent_set      (GtkWidget      *widget,
45                                      GtkWidget      *previous_parent);
[14481]46static void gtk_tree_unmap           (GtkWidget      *widget);
47static void gtk_tree_realize         (GtkWidget      *widget);
48static void gtk_tree_draw            (GtkWidget      *widget,
49                                      GdkRectangle   *area);
50static gint gtk_tree_expose          (GtkWidget      *widget,
51                                      GdkEventExpose *event);
52static gint gtk_tree_motion_notify   (GtkWidget      *widget,
53                                      GdkEventMotion *event);
54static gint gtk_tree_button_press    (GtkWidget      *widget,
55                                      GdkEventButton *event);
56static gint gtk_tree_button_release  (GtkWidget      *widget,
57                                      GdkEventButton *event);
58static void gtk_tree_size_request    (GtkWidget      *widget,
59                                      GtkRequisition *requisition);
60static void gtk_tree_size_allocate   (GtkWidget      *widget,
61                                      GtkAllocation  *allocation);
62static void gtk_tree_add             (GtkContainer   *container,
63                                      GtkWidget      *widget);
64static void gtk_tree_forall          (GtkContainer   *container,
65                                      gboolean        include_internals,
66                                      GtkCallback     callback,
67                                      gpointer        callback_data);
68
69static void gtk_real_tree_select_child   (GtkTree       *tree,
70                                          GtkWidget     *child);
71static void gtk_real_tree_unselect_child (GtkTree       *tree,
72                                          GtkWidget     *child);
73
74static GtkType gtk_tree_child_type  (GtkContainer   *container);
75
76static GtkContainerClass *parent_class = NULL;
77static guint tree_signals[LAST_SIGNAL] = { 0 };
78
79GtkType
80gtk_tree_get_type (void)
81{
82  static GtkType tree_type = 0;
83 
84  if (!tree_type)
85    {
86      static const GtkTypeInfo tree_info =
87      {
88        "GtkTree",
89        sizeof (GtkTree),
90        sizeof (GtkTreeClass),
91        (GtkClassInitFunc) gtk_tree_class_init,
92        (GtkObjectInitFunc) gtk_tree_init,
93        /* reserved_1 */ NULL,
94        /* reserved_2 */ NULL,
95        (GtkClassInitFunc) NULL,
96      };
97     
98      tree_type = gtk_type_unique (gtk_container_get_type (), &tree_info);
99    }
100 
101  return tree_type;
102}
103
104static void
105gtk_tree_class_init (GtkTreeClass *class)
106{
107  GtkObjectClass *object_class;
108  GtkWidgetClass *widget_class;
109  GtkContainerClass *container_class;
110 
111  object_class = (GtkObjectClass*) class;
112  widget_class = (GtkWidgetClass*) class;
113  container_class = (GtkContainerClass*) class;
114 
115  parent_class = gtk_type_class (gtk_container_get_type ());
116 
117  tree_signals[SELECTION_CHANGED] =
118    gtk_signal_new ("selection_changed",
119                    GTK_RUN_FIRST,
120                    object_class->type,
121                    GTK_SIGNAL_OFFSET (GtkTreeClass, selection_changed),
122                    gtk_marshal_NONE__NONE,
123                    GTK_TYPE_NONE, 0);
124  tree_signals[SELECT_CHILD] =
125    gtk_signal_new ("select_child",
126                    GTK_RUN_FIRST,
127                    object_class->type,
128                    GTK_SIGNAL_OFFSET (GtkTreeClass, select_child),
129                    gtk_marshal_NONE__POINTER,
130                    GTK_TYPE_NONE, 1,
131                    GTK_TYPE_WIDGET);
132  tree_signals[UNSELECT_CHILD] =
133    gtk_signal_new ("unselect_child",
134                    GTK_RUN_FIRST,
135                    object_class->type,
136                    GTK_SIGNAL_OFFSET (GtkTreeClass, unselect_child),
137                    gtk_marshal_NONE__POINTER,
138                    GTK_TYPE_NONE, 1,
139                    GTK_TYPE_WIDGET);
140 
141  gtk_object_class_add_signals (object_class, tree_signals, LAST_SIGNAL);
142 
143  object_class->destroy = gtk_tree_destroy;
144 
145  widget_class->map = gtk_tree_map;
146  widget_class->unmap = gtk_tree_unmap;
[15780]147  widget_class->parent_set = gtk_tree_parent_set;
[14481]148  widget_class->realize = gtk_tree_realize;
149  widget_class->draw = gtk_tree_draw;
150  widget_class->expose_event = gtk_tree_expose;
151  widget_class->motion_notify_event = gtk_tree_motion_notify;
152  widget_class->button_press_event = gtk_tree_button_press;
153  widget_class->button_release_event = gtk_tree_button_release;
154  widget_class->size_request = gtk_tree_size_request;
155  widget_class->size_allocate = gtk_tree_size_allocate;
156 
157  container_class->add = gtk_tree_add;
158  container_class->remove =
159    (void (*)(GtkContainer *, GtkWidget *)) gtk_tree_remove_item;
160  container_class->forall = gtk_tree_forall;
161  container_class->child_type = gtk_tree_child_type;
162 
163  class->selection_changed = NULL;
164  class->select_child = gtk_real_tree_select_child;
165  class->unselect_child = gtk_real_tree_unselect_child;
166}
167
168static GtkType
169gtk_tree_child_type (GtkContainer     *container)
170{
171  return GTK_TYPE_TREE_ITEM;
172}
173
174static void
175gtk_tree_init (GtkTree *tree)
176{
177  tree->children = NULL;
[15780]178  tree->root_tree = tree;
[14481]179  tree->selection = NULL;
180  tree->tree_owner = NULL;
181  tree->selection_mode = GTK_SELECTION_SINGLE;
182  tree->indent_value = 9;
183  tree->current_indent = 0;
184  tree->level = 0;
185  tree->view_mode = GTK_TREE_VIEW_LINE;
186  tree->view_line = 1;
187}
188
189GtkWidget*
190gtk_tree_new (void)
191{
192  return GTK_WIDGET (gtk_type_new (gtk_tree_get_type ()));
193}
194
195void
196gtk_tree_append (GtkTree   *tree,
197                 GtkWidget *tree_item)
198{
199  g_return_if_fail (tree != NULL);
200  g_return_if_fail (GTK_IS_TREE (tree));
201  g_return_if_fail (tree_item != NULL);
202  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
203 
204  gtk_tree_insert (tree, tree_item, -1);
205}
206
207void
208gtk_tree_prepend (GtkTree   *tree,
209                  GtkWidget *tree_item)
210{
211  g_return_if_fail (tree != NULL);
212  g_return_if_fail (GTK_IS_TREE (tree));
213  g_return_if_fail (tree_item != NULL);
214  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
215 
216  gtk_tree_insert (tree, tree_item, 0);
217}
218
219void
220gtk_tree_insert (GtkTree   *tree,
221                 GtkWidget *tree_item,
222                 gint       position)
223{
224  gint nchildren;
225 
226  g_return_if_fail (tree != NULL);
227  g_return_if_fail (GTK_IS_TREE (tree));
228  g_return_if_fail (tree_item != NULL);
229  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
230 
231  nchildren = g_list_length (tree->children);
232 
233  if ((position < 0) || (position > nchildren))
234    position = nchildren;
235 
236  if (position == nchildren)
237    tree->children = g_list_append (tree->children, tree_item);
238  else
239    tree->children = g_list_insert (tree->children, tree_item, position);
240 
241  gtk_widget_set_parent (tree_item, GTK_WIDGET (tree));
242 
243  if (GTK_WIDGET_REALIZED (tree_item->parent))
244    gtk_widget_realize (tree_item);
245
246  if (GTK_WIDGET_VISIBLE (tree_item->parent) && GTK_WIDGET_VISIBLE (tree_item))
247    {
248      if (GTK_WIDGET_MAPPED (tree_item->parent))
249        gtk_widget_map (tree_item);
250
251      gtk_widget_queue_resize (tree_item);
252    }
253}
254
255static void
256gtk_tree_add (GtkContainer *container,
257              GtkWidget    *child)
258{
259  GtkTree *tree;
260 
261  g_return_if_fail (container != NULL);
262  g_return_if_fail (GTK_IS_TREE (container));
263  g_return_if_fail (GTK_IS_TREE_ITEM (child));
264 
265  tree = GTK_TREE (container);
266 
267  tree->children = g_list_append (tree->children, child);
268 
269  gtk_widget_set_parent (child, GTK_WIDGET (container));
270 
271  if (GTK_WIDGET_REALIZED (child->parent))
272    gtk_widget_realize (child);
273
274  if (GTK_WIDGET_VISIBLE (child->parent) && GTK_WIDGET_VISIBLE (child))
275    {
276      if (GTK_WIDGET_MAPPED (child->parent))
277        gtk_widget_map (child);
278
279      gtk_widget_queue_resize (child);
280    }
281 
282  if (!tree->selection && (tree->selection_mode == GTK_SELECTION_BROWSE))
283    gtk_tree_select_child (tree, child);
284}
285
286static gint
287gtk_tree_button_press (GtkWidget      *widget,
288                       GdkEventButton *event)
289{
290  GtkTree *tree;
291  GtkWidget *item;
292 
293  g_return_val_if_fail (widget != NULL, FALSE);
294  g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
295  g_return_val_if_fail (event != NULL, FALSE);
296 
297  tree = GTK_TREE (widget);
298  item = gtk_get_event_widget ((GdkEvent*) event);
299 
300  while (item && !GTK_IS_TREE_ITEM (item))
301    item = item->parent;
302 
303  if (!item || (item->parent != widget))
304    return FALSE;
305 
306  switch(event->button)
307    {
308    case 1:
309      gtk_tree_select_child (tree, item);
310      break;
311    case 2:
312      if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_expand(GTK_TREE_ITEM(item));
313      break;
314    case 3:
315      if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_collapse(GTK_TREE_ITEM(item));
316      break;
317    }
318 
319  return TRUE;
320}
321
322static gint
323gtk_tree_button_release (GtkWidget      *widget,
324                         GdkEventButton *event)
325{
326  GtkTree *tree;
327  GtkWidget *item;
328 
329  g_return_val_if_fail (widget != NULL, FALSE);
330  g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
331  g_return_val_if_fail (event != NULL, FALSE);
332 
333  tree = GTK_TREE (widget);
334  item = gtk_get_event_widget ((GdkEvent*) event);
335 
336  return TRUE;
337}
338
339gint
340gtk_tree_child_position (GtkTree   *tree,
341                         GtkWidget *child)
342{
343  GList *children;
344  gint pos;
345 
346 
347  g_return_val_if_fail (tree != NULL, -1);
348  g_return_val_if_fail (GTK_IS_TREE (tree), -1);
349  g_return_val_if_fail (child != NULL, -1);
350 
351  pos = 0;
352  children = tree->children;
353 
354  while (children)
355    {
356      if (child == GTK_WIDGET (children->data))
357        return pos;
358     
359      pos += 1;
360      children = children->next;
361    }
362 
363 
364  return -1;
365}
366
367void
368gtk_tree_clear_items (GtkTree *tree,
369                      gint     start,
370                      gint     end)
371{
372  GtkWidget *widget;
373  GList *clear_list;
374  GList *tmp_list;
375  guint nchildren;
376  guint index;
377 
378  g_return_if_fail (tree != NULL);
379  g_return_if_fail (GTK_IS_TREE (tree));
380 
381  nchildren = g_list_length (tree->children);
382 
383  if (nchildren > 0)
384    {
385      if ((end < 0) || (end > nchildren))
386        end = nchildren;
387     
388      if (start >= end)
389        return;
390     
391      tmp_list = g_list_nth (tree->children, start);
392      clear_list = NULL;
393      index = start;
394      while (tmp_list && index <= end)
395        {
396          widget = tmp_list->data;
397          tmp_list = tmp_list->next;
398          index++;
399         
400          clear_list = g_list_prepend (clear_list, widget);
401        }
402     
403      gtk_tree_remove_items (tree, clear_list);
404    }
405}
406
407static void
408gtk_tree_destroy (GtkObject *object)
409{
410  GtkTree *tree;
411  GtkWidget *child;
412  GList *children;
413 
414  g_return_if_fail (object != NULL);
415  g_return_if_fail (GTK_IS_TREE (object));
416 
417  tree = GTK_TREE (object);
418 
419  children = tree->children;
420  while (children)
421    {
422      child = children->data;
423      children = children->next;
424     
425      gtk_widget_ref (child);
426      gtk_widget_unparent (child);
427      gtk_widget_destroy (child);
428      gtk_widget_unref (child);
429    }
430 
431  g_list_free (tree->children);
432  tree->children = NULL;
433 
434  if (tree->root_tree == tree)
435    {
436      GList *node;
437      for (node = tree->selection; node; node = node->next)
438        gtk_widget_unref ((GtkWidget *)node->data);
439      g_list_free (tree->selection);
440      tree->selection = NULL;
441    }
442 
443  if (GTK_OBJECT_CLASS (parent_class)->destroy)
444    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
445}
446
447static void
448gtk_tree_draw (GtkWidget    *widget,
449               GdkRectangle *area)
450{
451  GtkTree *tree;
452  GtkWidget *subtree;
453  GtkWidget *child;
454  GdkRectangle child_area;
455  GList *children;
456 
457 
458  g_return_if_fail (widget != NULL);
459  g_return_if_fail (GTK_IS_TREE (widget));
460  g_return_if_fail (area != NULL);
461 
462  if (GTK_WIDGET_DRAWABLE (widget))
463    {
464      tree = GTK_TREE (widget);
465     
466      children = tree->children;
467      while (children)
468        {
469          child = children->data;
470          children = children->next;
471         
472          if (gtk_widget_intersect (child, area, &child_area))
473            gtk_widget_draw (child, &child_area);
474         
475          if((subtree = GTK_TREE_ITEM(child)->subtree) &&
476             GTK_WIDGET_VISIBLE(subtree) &&
477             gtk_widget_intersect (subtree, area, &child_area))
478            gtk_widget_draw (subtree, &child_area);
479        }
480    }
481 
482}
483
484static gint
485gtk_tree_expose (GtkWidget      *widget,
486                 GdkEventExpose *event)
487{
488  GtkTree *tree;
489  GtkWidget *child;
490  GdkEventExpose child_event;
491  GList *children;
492 
493 
494  g_return_val_if_fail (widget != NULL, FALSE);
495  g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
496  g_return_val_if_fail (event != NULL, FALSE);
497 
498  if (GTK_WIDGET_DRAWABLE (widget))
499    {
500      tree = GTK_TREE (widget);
501     
502      child_event = *event;
503     
504      children = tree->children;
505      while (children)
506        {
507          child = children->data;
508          children = children->next;
509         
510          if (GTK_WIDGET_NO_WINDOW (child) &&
511              gtk_widget_intersect (child, &event->area, &child_event.area))
512            gtk_widget_event (child, (GdkEvent*) &child_event);
513        }
514    }
515 
516 
517  return FALSE;
518}
519
520static void
521gtk_tree_forall (GtkContainer *container,
522                 gboolean      include_internals,
523                 GtkCallback   callback,
524                 gpointer      callback_data)
525{
526  GtkTree *tree;
527  GtkWidget *child;
528  GList *children;
529 
530 
531  g_return_if_fail (container != NULL);
532  g_return_if_fail (GTK_IS_TREE (container));
533  g_return_if_fail (callback != NULL);
534 
535  tree = GTK_TREE (container);
536  children = tree->children;
537 
538  while (children)
539    {
540      child = children->data;
541      children = children->next;
542     
543      (* callback) (child, callback_data);
544    }
545}
546
547static void
[15780]548gtk_tree_unselect_all (GtkTree *tree)
[14481]549{
[15780]550  GList *tmp_list, *selection;
551  GtkWidget *tmp_item;
552     
553  selection = tree->selection;
554  tree->selection = NULL;
555
556  tmp_list = selection;
557  while (tmp_list)
558    {
559      tmp_item = selection->data;
560
561      if (tmp_item->parent &&
562          GTK_IS_TREE (tmp_item->parent) &&
563          GTK_TREE (tmp_item->parent)->root_tree == tree)
564        gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
565
566      gtk_widget_unref (tmp_item);
567
568      tmp_list = tmp_list->next;
569    }
570
571  g_list_free (selection);
572}
573
574static void
575gtk_tree_parent_set (GtkWidget *widget,
576                     GtkWidget *previous_parent)
577{
578  GtkTree *tree = GTK_TREE (widget);
[14481]579  GtkWidget *child;
580  GList *children;
581 
[15780]582  if (widget->parent && GTK_IS_TREE (widget->parent))
[14481]583    {
[15780]584      gtk_tree_unselect_all (tree);
585     
[14481]586      /* set root tree for this tree */
587      tree->root_tree = GTK_TREE(widget->parent)->root_tree;
588     
589      tree->level = GTK_TREE(GTK_WIDGET(tree)->parent)->level+1;
590      tree->indent_value = GTK_TREE(GTK_WIDGET(tree)->parent)->indent_value;
591      tree->current_indent = GTK_TREE(GTK_WIDGET(tree)->parent)->current_indent +
592        tree->indent_value;
593      tree->view_mode = GTK_TREE(GTK_WIDGET(tree)->parent)->view_mode;
594      tree->view_line = GTK_TREE(GTK_WIDGET(tree)->parent)->view_line;
[15780]595    }
[14481]596  else
[15780]597    {
598      tree->root_tree = tree;
599     
600      tree->level = 0;
601      tree->current_indent = 0;
602    }
603
604  children = tree->children;
605  while (children)
606    {
607      child = children->data;
608      children = children->next;
609     
610      if (GTK_TREE_ITEM (child)->subtree)
611        gtk_tree_parent_set (GTK_TREE_ITEM (child)->subtree, child);
612    }
613}
614
615static void
616gtk_tree_map (GtkWidget *widget)
617{
618  GtkTree *tree = GTK_TREE (widget);
619  GtkWidget *child;
620  GList *children;
[14481]621 
[15780]622  GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
623 
[14481]624  children = tree->children;
625  while (children)
626    {
627      child = children->data;
628      children = children->next;
629     
630      if (GTK_WIDGET_VISIBLE (child) &&
631          !GTK_WIDGET_MAPPED (child))
632        gtk_widget_map (child);
633     
634      if (GTK_TREE_ITEM (child)->subtree)
635        {
636          child = GTK_WIDGET (GTK_TREE_ITEM (child)->subtree);
637         
638          if (GTK_WIDGET_VISIBLE (child) && !GTK_WIDGET_MAPPED (child))
639            gtk_widget_map (child);
640        }
641    }
642
643  gdk_window_show (widget->window);
644}
645
646static gint
647gtk_tree_motion_notify (GtkWidget      *widget,
648                        GdkEventMotion *event)
649{
650  g_return_val_if_fail (widget != NULL, FALSE);
651  g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
652  g_return_val_if_fail (event != NULL, FALSE);
653 
654#ifdef TREE_DEBUG
655  g_message("gtk_tree_motion_notify\n");
656#endif /* TREE_DEBUG */
657 
658  return FALSE;
659}
660
661static void
662gtk_tree_realize (GtkWidget *widget)
663{
664  GdkWindowAttr attributes;
665  gint attributes_mask;
666 
667 
668  g_return_if_fail (widget != NULL);
669  g_return_if_fail (GTK_IS_TREE (widget));
670 
671  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
672 
673  attributes.window_type = GDK_WINDOW_CHILD;
674  attributes.x = widget->allocation.x;
675  attributes.y = widget->allocation.y;
676  attributes.width = widget->allocation.width;
677  attributes.height = widget->allocation.height;
678  attributes.wclass = GDK_INPUT_OUTPUT;
679  attributes.visual = gtk_widget_get_visual (widget);
680  attributes.colormap = gtk_widget_get_colormap (widget);
681  attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
682 
683  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
684 
685  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
686  gdk_window_set_user_data (widget->window, widget);
687 
688  widget->style = gtk_style_attach (widget->style, widget->window);
689  gdk_window_set_background (widget->window,
690                             &widget->style->base[GTK_STATE_NORMAL]);
691}
692
693void
694gtk_tree_remove_item (GtkTree      *container,
695                      GtkWidget    *widget)
696{
697  GList *item_list;
698 
699  g_return_if_fail (container != NULL);
700  g_return_if_fail (GTK_IS_TREE (container));
701  g_return_if_fail (widget != NULL);
702  g_return_if_fail (container == GTK_TREE (widget->parent));
703 
704  item_list = g_list_append (NULL, widget);
705 
706  gtk_tree_remove_items (GTK_TREE (container), item_list);
707 
708  g_list_free (item_list);
709}
710
711/* used by gtk_tree_remove_items to make the function independant of
712   order in list of items to remove.
713   Sort item bu depth in tree */
714static gint
715gtk_tree_sort_item_by_depth(GtkWidget* a, GtkWidget* b)
716{
717  if((GTK_TREE(a->parent)->level) < (GTK_TREE(b->parent)->level))
718    return 1;
719  if((GTK_TREE(a->parent)->level) > (GTK_TREE(b->parent)->level))
720    return -1;
721 
722  return 0;
723}
724
725void
726gtk_tree_remove_items (GtkTree *tree,
727                       GList   *items)
728{
729  GtkWidget *widget;
730  GList *selected_widgets;
731  GList *tmp_list;
732  GList *sorted_list;
733  GtkTree *real_tree;
734  GtkTree *root_tree;
735 
736  g_return_if_fail (tree != NULL);
737  g_return_if_fail (GTK_IS_TREE (tree));
738 
739#ifdef TREE_DEBUG
740  g_message("+ gtk_tree_remove_items [ tree %#x items list %#x ]\n", (int)tree, (int)items);
741#endif /* TREE_DEBUG */
742 
743  /* We may not yet be mapped, so we actively have to find our
744   * root tree
745   */
746  if (tree->root_tree)
747    root_tree = tree->root_tree;
748  else
749    {
750      GtkWidget *tmp = GTK_WIDGET (tree);
751      while (tmp->parent && GTK_IS_TREE (tmp->parent))
752        tmp = tmp->parent;
753     
754      root_tree = GTK_TREE (tmp);
755    }
756 
757  tmp_list = items;
758  selected_widgets = NULL;
759  sorted_list = NULL;
760  widget = NULL;
761 
762#ifdef TREE_DEBUG
763  g_message("* sort list by depth\n");
764#endif /* TREE_DEBUG */
765 
766  while (tmp_list)
767    {
768     
769#ifdef TREE_DEBUG
770      g_message ("* item [%#x] depth [%d]\n",
771                 (int)tmp_list->data,
772                 (int)GTK_TREE(GTK_WIDGET(tmp_list->data)->parent)->level);
773#endif /* TREE_DEBUG */
774     
775      sorted_list = g_list_insert_sorted(sorted_list,
776                                         tmp_list->data,
777                                         (GCompareFunc)gtk_tree_sort_item_by_depth);
778      tmp_list = g_list_next(tmp_list);
779    }
780 
781#ifdef TREE_DEBUG
782  /* print sorted list */
783  g_message("* sorted list result\n");
784  tmp_list = sorted_list;
785  while(tmp_list)
786    {
787      g_message("* item [%#x] depth [%d]\n",
788                (int)tmp_list->data,
789                (int)GTK_TREE(GTK_WIDGET(tmp_list->data)->parent)->level);
790      tmp_list = g_list_next(tmp_list);
791    }
792#endif /* TREE_DEBUG */
793 
794#ifdef TREE_DEBUG
795  g_message("* scan sorted list\n");
796#endif /* TREE_DEBUG */
797 
798  tmp_list = sorted_list;
799  while (tmp_list)
800    {
801      widget = tmp_list->data;
802      tmp_list = tmp_list->next;
803     
804#ifdef TREE_DEBUG
805      g_message("* item [%#x] subtree [%#x]\n",
806                (int)widget, (int)GTK_TREE_ITEM_SUBTREE(widget));
807#endif /* TREE_DEBUG */
808     
809      /* get real owner of this widget */
810      real_tree = GTK_TREE(widget->parent);
811#ifdef TREE_DEBUG
812      g_message("* subtree having this widget [%#x]\n", (int)real_tree);
813#endif /* TREE_DEBUG */
814     
815     
816      if (widget->state == GTK_STATE_SELECTED)
817        {
818          selected_widgets = g_list_prepend (selected_widgets, widget);
819#ifdef TREE_DEBUG
820          g_message("* selected widget - adding it in selected list [%#x]\n",
821                    (int)selected_widgets);
822#endif /* TREE_DEBUG */
823        }
824     
825      /* remove this item from its real parent */
826#ifdef TREE_DEBUG
827      g_message("* remove widget from its owner tree\n");
828#endif /* TREE_DEBUG */
829      real_tree->children = g_list_remove (real_tree->children, widget);
830     
831      /* remove subtree associate at this item if it exist */     
832      if(GTK_TREE_ITEM(widget)->subtree)
833        {
834#ifdef TREE_DEBUG
835          g_message("* remove subtree associate at this item [%#x]\n",
836                    (int) GTK_TREE_ITEM(widget)->subtree);
837#endif /* TREE_DEBUG */
838          if (GTK_WIDGET_MAPPED (GTK_TREE_ITEM(widget)->subtree))
839            gtk_widget_unmap (GTK_TREE_ITEM(widget)->subtree);
840         
841          gtk_widget_unparent (GTK_TREE_ITEM(widget)->subtree);
842          GTK_TREE_ITEM(widget)->subtree = NULL;
843        }
844     
845      /* really remove widget for this item */
846#ifdef TREE_DEBUG
847      g_message("* unmap and unparent widget [%#x]\n", (int)widget);
848#endif /* TREE_DEBUG */
849      if (GTK_WIDGET_MAPPED (widget))
850        gtk_widget_unmap (widget);
851     
852      gtk_widget_unparent (widget);
853     
854      /* delete subtree if there is no children in it */
855      if(real_tree->children == NULL &&
856         real_tree != root_tree)
857        {
858#ifdef TREE_DEBUG
859          g_message("* owner tree don't have children ... destroy it\n");
860#endif /* TREE_DEBUG */
861          gtk_tree_item_remove_subtree(GTK_TREE_ITEM(real_tree->tree_owner));
862        }
863     
864#ifdef TREE_DEBUG
865      g_message("* next item in list\n");
866#endif /* TREE_DEBUG */
867    }
868 
869  if (selected_widgets)
870    {
871#ifdef TREE_DEBUG
872      g_message("* scan selected item list\n");
873#endif /* TREE_DEBUG */
874      tmp_list = selected_widgets;
875      while (tmp_list)
876        {
877          widget = tmp_list->data;
878          tmp_list = tmp_list->next;
879         
880#ifdef TREE_DEBUG
881          g_message("* widget [%#x] subtree [%#x]\n",
882                    (int)widget, (int)GTK_TREE_ITEM_SUBTREE(widget));
883#endif /* TREE_DEBUG */
884         
885          /* remove widget of selection */
886          root_tree->selection = g_list_remove (root_tree->selection, widget);
887         
888          /* unref it to authorize is destruction */
889          gtk_widget_unref (widget);
890        }
891     
892      /* emit only one selection_changed signal */
893      gtk_signal_emit (GTK_OBJECT (root_tree),
894                       tree_signals[SELECTION_CHANGED]);
895    }
896 
897#ifdef TREE_DEBUG
898  g_message("* free selected_widgets list\n");
899#endif /* TREE_DEBUG */
900  g_list_free (selected_widgets);
901  g_list_free (sorted_list);
902 
903  if (root_tree->children && !root_tree->selection &&
904      (root_tree->selection_mode == GTK_SELECTION_BROWSE))
905    {
906#ifdef TREE_DEBUG
907      g_message("* BROWSE mode, select another item\n");
908#endif /* TREE_DEBUG */
909      widget = root_tree->children->data;
910      gtk_tree_select_child (root_tree, widget);
911    }
912 
913  if (GTK_WIDGET_VISIBLE (root_tree))
914    {
915#ifdef TREE_DEBUG
916      g_message("* query queue resizing for root_tree\n");
917#endif /* TREE_DEBUG */     
918      gtk_widget_queue_resize (GTK_WIDGET (root_tree));
919    }
920}
921
922void
923gtk_tree_select_child (GtkTree   *tree,
924                       GtkWidget *tree_item)
925{
926  g_return_if_fail (tree != NULL);
927  g_return_if_fail (GTK_IS_TREE (tree));
928  g_return_if_fail (tree_item != NULL);
929  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
930 
931  gtk_signal_emit (GTK_OBJECT (tree), tree_signals[SELECT_CHILD], tree_item);
932}
933
934void
935gtk_tree_select_item (GtkTree   *tree,
936                      gint       item)
937{
938  GList *tmp_list;
939 
940  g_return_if_fail (tree != NULL);
941  g_return_if_fail (GTK_IS_TREE (tree));
942 
943  tmp_list = g_list_nth (tree->children, item);
944  if (tmp_list)
945    gtk_tree_select_child (tree, GTK_WIDGET (tmp_list->data));
946 
947}
948
949static void
950gtk_tree_size_allocate (GtkWidget     *widget,
951                        GtkAllocation *allocation)
952{
953  GtkTree *tree;
954  GtkWidget *child, *subtree;
955  GtkAllocation child_allocation;
956  GList *children;
957 
958 
959  g_return_if_fail (widget != NULL);
960  g_return_if_fail (GTK_IS_TREE (widget));
961  g_return_if_fail (allocation != NULL);
962 
963  tree = GTK_TREE (widget);
964 
965  widget->allocation = *allocation;
966  if (GTK_WIDGET_REALIZED (widget))
967    gdk_window_move_resize (widget->window,
968                            allocation->x, allocation->y,
969                            allocation->width, allocation->height);
970 
971  if (tree->children)
972    {
973      child_allocation.x = GTK_CONTAINER (tree)->border_width;
974      child_allocation.y = GTK_CONTAINER (tree)->border_width;
975      child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
976     
977      children = tree->children;
978     
979      while (children)
980        {
981          child = children->data;
982          children = children->next;
983         
984          if (GTK_WIDGET_VISIBLE (child))
985            {
986              GtkRequisition child_requisition;
987              gtk_widget_get_child_requisition (child, &child_requisition);
988             
989              child_allocation.height = child_requisition.height;
990             
991              gtk_widget_size_allocate (child, &child_allocation);
992             
993              child_allocation.y += child_allocation.height;
994             
995              if((subtree = GTK_TREE_ITEM(child)->subtree))
996                if(GTK_WIDGET_VISIBLE (subtree))
997                  {
998                    child_allocation.height = subtree->requisition.height;
999                    gtk_widget_size_allocate (subtree, &child_allocation);
1000                    child_allocation.y += child_allocation.height;
1001                  }
1002            }
1003        }
1004    }
1005 
1006}
1007
1008static void
1009gtk_tree_size_request (GtkWidget      *widget,
1010                       GtkRequisition *requisition)
1011{
1012  GtkTree *tree;
1013  GtkWidget *child, *subtree;
1014  GList *children;
1015  GtkRequisition child_requisition;
1016 
1017 
1018  g_return_if_fail (widget != NULL);
1019  g_return_if_fail (GTK_IS_TREE (widget));
1020  g_return_if_fail (requisition != NULL);
1021 
1022  tree = GTK_TREE (widget);
1023  requisition->width = 0;
1024  requisition->height = 0;
1025 
1026  children = tree->children;
1027  while (children)
1028    {
1029      child = children->data;
1030      children = children->next;
1031     
1032      if (GTK_WIDGET_VISIBLE (child))
1033        {
1034          gtk_widget_size_request (child, &child_requisition);
1035         
1036          requisition->width = MAX (requisition->width, child_requisition.width);
1037          requisition->height += child_requisition.height;
1038         
1039          if((subtree = GTK_TREE_ITEM(child)->subtree) &&
1040             GTK_WIDGET_VISIBLE (subtree))
1041            {
1042              gtk_widget_size_request (subtree, &child_requisition);
1043             
1044              requisition->width = MAX (requisition->width,
1045                                        child_requisition.width);
1046             
1047              requisition->height += child_requisition.height;
1048            }
1049        }
1050    }
1051 
1052  requisition->width += GTK_CONTAINER (tree)->border_width * 2;
1053  requisition->height += GTK_CONTAINER (tree)->border_width * 2;
1054 
1055  requisition->width = MAX (requisition->width, 1);
1056  requisition->height = MAX (requisition->height, 1);
1057 
1058}
1059
1060static void
1061gtk_tree_unmap (GtkWidget *widget)
1062{
1063 
1064  g_return_if_fail (widget != NULL);
1065  g_return_if_fail (GTK_IS_TREE (widget));
1066 
1067  GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1068  gdk_window_hide (widget->window);
1069 
1070}
1071
1072void
1073gtk_tree_unselect_child (GtkTree   *tree,
1074                         GtkWidget *tree_item)
1075{
1076  g_return_if_fail (tree != NULL);
1077  g_return_if_fail (GTK_IS_TREE (tree));
1078  g_return_if_fail (tree_item != NULL);
1079  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
1080 
1081  gtk_signal_emit (GTK_OBJECT (tree), tree_signals[UNSELECT_CHILD], tree_item);
1082}
1083
1084void
1085gtk_tree_unselect_item (GtkTree *tree,
1086                        gint     item)
1087{
1088  GList *tmp_list;
1089 
1090  g_return_if_fail (tree != NULL);
1091  g_return_if_fail (GTK_IS_TREE (tree));
1092 
1093  tmp_list = g_list_nth (tree->children, item);
1094  if (tmp_list)
1095    gtk_tree_unselect_child (tree, GTK_WIDGET (tmp_list->data));
1096 
1097}
1098
1099static void
1100gtk_real_tree_select_child (GtkTree   *tree,
1101                            GtkWidget *child)
1102{
1103  GList *selection, *root_selection;
1104  GList *tmp_list;
1105  GtkWidget *tmp_item;
1106 
1107  g_return_if_fail (tree != NULL);
1108  g_return_if_fail (GTK_IS_TREE (tree));
1109  g_return_if_fail (child != NULL);
1110  g_return_if_fail (GTK_IS_TREE_ITEM (child));
[15780]1111
[14481]1112  root_selection = tree->root_tree->selection;
1113 
1114  switch (tree->root_tree->selection_mode)
1115    {
1116    case GTK_SELECTION_SINGLE:
1117     
1118      selection = root_selection;
1119     
1120      /* remove old selection list */
1121      while (selection)
1122        {
1123          tmp_item = selection->data;
1124         
1125          if (tmp_item != child)
1126            {
1127              gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1128             
1129              tmp_list = selection;
1130              selection = selection->next;
1131             
1132              root_selection = g_list_remove_link (root_selection, tmp_list);
1133              gtk_widget_unref (tmp_item);
1134             
1135              g_list_free (tmp_list);
1136            }
1137          else
1138            selection = selection->next;
1139        }
1140     
1141      if (child->state == GTK_STATE_NORMAL)
1142        {
1143          gtk_tree_item_select (GTK_TREE_ITEM (child));
1144          root_selection = g_list_prepend (root_selection, child);
1145          gtk_widget_ref (child);
1146        }
1147      else if (child->state == GTK_STATE_SELECTED)
1148        {
1149          gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1150          root_selection = g_list_remove (root_selection, child);
1151          gtk_widget_unref (child);
1152        }
1153     
1154      tree->root_tree->selection = root_selection;
1155     
1156      gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1157                       tree_signals[SELECTION_CHANGED]);
1158      break;
1159     
1160     
1161    case GTK_SELECTION_BROWSE:
1162      selection = root_selection;
1163     
1164      while (selection)
1165        {
1166          tmp_item = selection->data;
1167         
1168          if (tmp_item != child)
1169            {
1170              gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1171             
1172              tmp_list = selection;
1173              selection = selection->next;
1174             
1175              root_selection = g_list_remove_link (root_selection, tmp_list);
1176              gtk_widget_unref (tmp_item);
1177             
1178              g_list_free (tmp_list);
1179            }
1180          else
1181            selection = selection->next;
1182        }
1183     
1184      tree->root_tree->selection = root_selection;
1185     
1186      if (child->state == GTK_STATE_NORMAL)
1187        {
1188          gtk_tree_item_select (GTK_TREE_ITEM (child));
1189          root_selection = g_list_prepend (root_selection, child);
1190          gtk_widget_ref (child);
1191          tree->root_tree->selection = root_selection;
1192          gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1193                           tree_signals[SELECTION_CHANGED]);
1194        }
1195      break;
1196     
1197    case GTK_SELECTION_MULTIPLE:
1198      if (child->state == GTK_STATE_NORMAL)
1199        {
1200          gtk_tree_item_select (GTK_TREE_ITEM (child));
1201          root_selection = g_list_prepend (root_selection, child);
1202          gtk_widget_ref (child);
1203          tree->root_tree->selection = root_selection;
1204          gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1205                           tree_signals[SELECTION_CHANGED]);
1206        }
1207      else if (child->state == GTK_STATE_SELECTED)
1208        {
1209          gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1210          root_selection = g_list_remove (root_selection, child);
1211          gtk_widget_unref (child);
1212          tree->root_tree->selection = root_selection;
1213          gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1214                           tree_signals[SELECTION_CHANGED]);
1215        }
1216      break;
1217     
1218    case GTK_SELECTION_EXTENDED:
1219      break;
1220    }
1221}
1222
1223static void
1224gtk_real_tree_unselect_child (GtkTree   *tree,
1225                              GtkWidget *child)
1226{
1227  g_return_if_fail (tree != NULL);
1228  g_return_if_fail (GTK_IS_TREE (tree));
1229  g_return_if_fail (child != NULL);
1230  g_return_if_fail (GTK_IS_TREE_ITEM (child));
1231 
1232  switch (tree->selection_mode)
1233    {
1234    case GTK_SELECTION_SINGLE:
1235    case GTK_SELECTION_MULTIPLE:
1236    case GTK_SELECTION_BROWSE:
1237      if (child->state == GTK_STATE_SELECTED)
1238        {
1239          GtkTree* root_tree = GTK_TREE_ROOT_TREE(tree);
1240          gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1241          root_tree->selection = g_list_remove (root_tree->selection, child);
1242          gtk_widget_unref (child);
1243          gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1244                           tree_signals[SELECTION_CHANGED]);
1245        }
1246      break;
1247     
1248    case GTK_SELECTION_EXTENDED:
1249      break;
1250    }
1251}
1252
1253void
1254gtk_tree_set_selection_mode (GtkTree       *tree,
1255                             GtkSelectionMode mode)
1256{
1257  g_return_if_fail (tree != NULL);
1258  g_return_if_fail (GTK_IS_TREE (tree));
1259 
1260  tree->selection_mode = mode;
1261}
1262
1263void
1264gtk_tree_set_view_mode (GtkTree       *tree,
1265                        GtkTreeViewMode mode)
1266{
1267  g_return_if_fail (tree != NULL);
1268  g_return_if_fail (GTK_IS_TREE (tree));
1269 
1270  tree->view_mode = mode;
1271}
1272
1273void
1274gtk_tree_set_view_lines (GtkTree       *tree,
1275                         guint          flag)
1276{
1277  g_return_if_fail (tree != NULL);
1278  g_return_if_fail (GTK_IS_TREE (tree));
1279 
1280  tree->view_line = flag;
1281}
Note: See TracBrowser for help on using the repository browser.