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

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