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

Revision 15781, 30.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 "gtklabel.h"
28#include "gtktree.h"
29#include "gtktreeitem.h"
30#include "gtkeventbox.h"
31#include "gtkpixmap.h"
32#include "gtkmain.h"
33#include "gtksignal.h"
34
35#include "tree_plus.xpm"
36#include "tree_minus.xpm"
37
38#define DEFAULT_DELTA 9
39
40enum {
41  COLLAPSE_TREE,
42  EXPAND_TREE,
43  LAST_SIGNAL
44};
45
46typedef struct _GtkTreePixmaps GtkTreePixmaps;
47
48struct _GtkTreePixmaps {
49  gint refcount;
50  GdkColormap *colormap;
51 
52  GdkPixmap *pixmap_plus;
53  GdkPixmap *pixmap_minus;
54  GdkBitmap *mask_plus;
55  GdkBitmap *mask_minus;
56};
57
58static GList *pixmaps = NULL;
59
60static void gtk_tree_item_class_init (GtkTreeItemClass *klass);
61static void gtk_tree_item_init       (GtkTreeItem      *tree_item);
62static void gtk_tree_item_realize       (GtkWidget        *widget);
63static void gtk_tree_item_size_request  (GtkWidget        *widget,
64                                         GtkRequisition   *requisition);
65static void gtk_tree_item_size_allocate (GtkWidget        *widget,
66                                         GtkAllocation    *allocation);
67static void gtk_tree_item_draw          (GtkWidget        *widget,
68                                         GdkRectangle     *area);
69static void gtk_tree_item_draw_focus    (GtkWidget        *widget);
70static void gtk_tree_item_paint         (GtkWidget        *widget,
71                                         GdkRectangle     *area);
72static gint gtk_tree_item_button_press  (GtkWidget        *widget,
73                                         GdkEventButton   *event);
74static gint gtk_tree_item_expose        (GtkWidget        *widget,
75                                         GdkEventExpose   *event);
76static gint gtk_tree_item_focus_in      (GtkWidget        *widget,
77                                         GdkEventFocus    *event);
78static gint gtk_tree_item_focus_out     (GtkWidget        *widget,
79                                         GdkEventFocus    *event);
80static void gtk_tree_item_forall        (GtkContainer    *container,
81                                         gboolean         include_internals,
82                                         GtkCallback      callback,
83                                         gpointer         callback_data);
84
85static void gtk_real_tree_item_select   (GtkItem          *item);
86static void gtk_real_tree_item_deselect (GtkItem          *item);
87static void gtk_real_tree_item_toggle   (GtkItem          *item);
88static void gtk_real_tree_item_expand   (GtkTreeItem      *item);
89static void gtk_real_tree_item_collapse (GtkTreeItem      *item);
90static void gtk_real_tree_item_expand   (GtkTreeItem      *item);
91static void gtk_real_tree_item_collapse (GtkTreeItem      *item);
92static void gtk_tree_item_destroy        (GtkObject *object);
93static void gtk_tree_item_subtree_button_click (GtkWidget *widget);
94static void gtk_tree_item_subtree_button_changed_state (GtkWidget *widget);
95
96static void gtk_tree_item_map(GtkWidget*);
97static void gtk_tree_item_unmap(GtkWidget*);
98
99static void gtk_tree_item_add_pixmaps    (GtkTreeItem       *tree_item);
100static void gtk_tree_item_remove_pixmaps (GtkTreeItem       *tree_item);
101
102static GtkItemClass *parent_class = NULL;
103static guint tree_item_signals[LAST_SIGNAL] = { 0 };
104
105GtkType
106gtk_tree_item_get_type (void)
107{
108  static GtkType tree_item_type = 0;
109
110  if (!tree_item_type)
111    {
112      static const GtkTypeInfo tree_item_info =
113      {
114        "GtkTreeItem",
115        sizeof (GtkTreeItem),
116        sizeof (GtkTreeItemClass),
117        (GtkClassInitFunc) gtk_tree_item_class_init,
118        (GtkObjectInitFunc) gtk_tree_item_init,
119        /* reserved_1 */ NULL,
120        /* reserved_2 */ NULL,
121        (GtkClassInitFunc) NULL,
122      };
123
124      tree_item_type = gtk_type_unique (gtk_item_get_type (), &tree_item_info);
125    }
126
127  return tree_item_type;
128}
129
130static void
131gtk_tree_item_class_init (GtkTreeItemClass *class)
132{
133  GtkObjectClass *object_class;
134  GtkWidgetClass *widget_class;
135  GtkContainerClass *container_class;
136  GtkItemClass *item_class;
137
138  object_class = (GtkObjectClass*) class;
139  widget_class = (GtkWidgetClass*) class;
140  item_class = (GtkItemClass*) class;
141  container_class = (GtkContainerClass*) class;
142
143  parent_class = gtk_type_class (gtk_item_get_type ());
144 
145  tree_item_signals[EXPAND_TREE] =
146    gtk_signal_new ("expand",
147                    GTK_RUN_FIRST,
148                    object_class->type,
149                    GTK_SIGNAL_OFFSET (GtkTreeItemClass, expand),
150                    gtk_marshal_NONE__NONE,
151                    GTK_TYPE_NONE, 0);
152  tree_item_signals[COLLAPSE_TREE] =
153    gtk_signal_new ("collapse",
154                    GTK_RUN_FIRST,
155                    object_class->type,
156                    GTK_SIGNAL_OFFSET (GtkTreeItemClass, collapse),
157                    gtk_marshal_NONE__NONE,
158                    GTK_TYPE_NONE, 0);
159
160  gtk_object_class_add_signals (object_class, tree_item_signals, LAST_SIGNAL);
161
162  object_class->destroy = gtk_tree_item_destroy;
163
164  widget_class->realize = gtk_tree_item_realize;
165  widget_class->size_request = gtk_tree_item_size_request;
166  widget_class->size_allocate = gtk_tree_item_size_allocate;
167  widget_class->draw = gtk_tree_item_draw;
168  widget_class->draw_focus = gtk_tree_item_draw_focus;
169  widget_class->button_press_event = gtk_tree_item_button_press;
170  widget_class->expose_event = gtk_tree_item_expose;
171  widget_class->focus_in_event = gtk_tree_item_focus_in;
172  widget_class->focus_out_event = gtk_tree_item_focus_out;
173  widget_class->map = gtk_tree_item_map;
174  widget_class->unmap = gtk_tree_item_unmap;
175
176  container_class->forall = gtk_tree_item_forall;
177
178  item_class->select = gtk_real_tree_item_select;
179  item_class->deselect = gtk_real_tree_item_deselect;
180  item_class->toggle = gtk_real_tree_item_toggle;
181
182  class->expand = gtk_real_tree_item_expand;
183  class->collapse = gtk_real_tree_item_collapse;
184}
185
186/* callback for event box mouse event */
187static void
188gtk_tree_item_subtree_button_click (GtkWidget *widget)
189{
190  GtkTreeItem* item;
191 
192  g_return_if_fail (widget != NULL);
193  g_return_if_fail (GTK_IS_EVENT_BOX (widget));
194 
195  item = (GtkTreeItem*) gtk_object_get_user_data (GTK_OBJECT (widget));
196  if (!GTK_WIDGET_IS_SENSITIVE (item))
197    return;
198 
199  if (item->expanded)
200    gtk_tree_item_collapse (item);
201  else
202    gtk_tree_item_expand (item);
203}
204
205/* callback for event box state changed */
206static void
207gtk_tree_item_subtree_button_changed_state (GtkWidget *widget)
208{
209  g_return_if_fail (widget != NULL);
210  g_return_if_fail (GTK_IS_EVENT_BOX (widget));
211 
212  if (GTK_WIDGET_VISIBLE (widget))
213    {
214     
215      if (widget->state == GTK_STATE_NORMAL)
216        gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
217      else
218        gdk_window_set_background (widget->window, &widget->style->bg[widget->state]);
219     
220      if (GTK_WIDGET_DRAWABLE (widget))
221        gdk_window_clear_area (widget->window, 0, 0,
222                               widget->allocation.width, widget->allocation.height);
223    }
224}
225
226static void
227gtk_tree_item_init (GtkTreeItem *tree_item)
228{
229  GtkWidget *eventbox, *pixmapwid;
230 
231  g_return_if_fail (tree_item != NULL);
232  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
233
234  tree_item->expanded = FALSE;
235  tree_item->subtree = NULL;
236  GTK_WIDGET_SET_FLAGS (tree_item, GTK_CAN_FOCUS);
237 
238  /* create an event box containing one pixmaps */
239  eventbox = gtk_event_box_new();
240  gtk_widget_set_events (eventbox, GDK_BUTTON_PRESS_MASK);
241  gtk_signal_connect(GTK_OBJECT(eventbox), "state_changed",
242                     (GtkSignalFunc)gtk_tree_item_subtree_button_changed_state,
243                     (gpointer)NULL);
244  gtk_signal_connect(GTK_OBJECT(eventbox), "realize",
245                     (GtkSignalFunc)gtk_tree_item_subtree_button_changed_state,
246                     (gpointer)NULL);
247  gtk_signal_connect(GTK_OBJECT(eventbox), "button_press_event",
248                     (GtkSignalFunc)gtk_tree_item_subtree_button_click,
249                     (gpointer)NULL);
250  gtk_object_set_user_data(GTK_OBJECT(eventbox), tree_item);
251  tree_item->pixmaps_box = eventbox;
252
253  /* create pixmap for button '+' */
254  pixmapwid = gtk_type_new (gtk_pixmap_get_type ());
255  if (!tree_item->expanded)
256    gtk_container_add (GTK_CONTAINER (eventbox), pixmapwid);
257  gtk_widget_show (pixmapwid);
258  tree_item->plus_pix_widget = pixmapwid;
259  gtk_widget_ref (tree_item->plus_pix_widget);
260  gtk_object_sink (GTK_OBJECT (tree_item->plus_pix_widget));
261 
262  /* create pixmap for button '-' */
263  pixmapwid = gtk_type_new (gtk_pixmap_get_type ());
264  if (tree_item->expanded)
265    gtk_container_add (GTK_CONTAINER (eventbox), pixmapwid);
266  gtk_widget_show (pixmapwid);
267  tree_item->minus_pix_widget = pixmapwid;
268  gtk_widget_ref (tree_item->minus_pix_widget);
269  gtk_object_sink (GTK_OBJECT (tree_item->minus_pix_widget));
270 
271  gtk_widget_set_parent (eventbox, GTK_WIDGET (tree_item));
272}
273
274
275GtkWidget*
276gtk_tree_item_new (void)
277{
278  GtkWidget *tree_item;
279
280  tree_item = GTK_WIDGET (gtk_type_new (gtk_tree_item_get_type ()));
281
282  return tree_item;
283}
284
285GtkWidget*
286gtk_tree_item_new_with_label (const gchar *label)
287{
288  GtkWidget *tree_item;
289  GtkWidget *label_widget;
290
291  tree_item = gtk_tree_item_new ();
292  label_widget = gtk_label_new (label);
293  gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
294
295  gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
296  gtk_widget_show (label_widget);
297
298
299  return tree_item;
300}
301
302void
303gtk_tree_item_set_subtree (GtkTreeItem *tree_item,
304                           GtkWidget   *subtree)
305{
306  g_return_if_fail (tree_item != NULL);
307  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
308  g_return_if_fail (subtree != NULL);
309  g_return_if_fail (GTK_IS_TREE (subtree));
310
311  if (tree_item->subtree)
312    {
313      g_warning("there is already a subtree for this tree item\n");
314      return;
315    }
316
317  tree_item->subtree = subtree;
318  GTK_TREE (subtree)->tree_owner = GTK_WIDGET (tree_item);
319
320  /* show subtree button */
321  if (tree_item->pixmaps_box)
322    gtk_widget_show (tree_item->pixmaps_box);
323
324  if (tree_item->expanded)
325    gtk_widget_show (subtree);
326  else
327    gtk_widget_hide (subtree);
328
329  gtk_widget_set_parent (subtree, GTK_WIDGET (tree_item)->parent);
330
331  if (GTK_WIDGET_REALIZED (subtree->parent))
332    gtk_widget_realize (subtree);
333
334  if (GTK_WIDGET_VISIBLE (subtree->parent) && GTK_WIDGET_VISIBLE (subtree))
335    {
336      if (GTK_WIDGET_MAPPED (subtree->parent))
337        gtk_widget_map (subtree);
338
339      gtk_widget_queue_resize (subtree);
340    }
341}
342
343void
344gtk_tree_item_select (GtkTreeItem *tree_item)
345{
346  g_return_if_fail (tree_item != NULL);
347  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
348
349  gtk_item_select (GTK_ITEM (tree_item));
350}
351
352void
353gtk_tree_item_deselect (GtkTreeItem *tree_item)
354{
355  g_return_if_fail (tree_item != NULL);
356  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
357
358  gtk_item_deselect (GTK_ITEM (tree_item));
359}
360
361void
362gtk_tree_item_expand (GtkTreeItem *tree_item)
363{
364  g_return_if_fail (tree_item != NULL);
365  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
366
367  gtk_signal_emit (GTK_OBJECT (tree_item), tree_item_signals[EXPAND_TREE], NULL);
368}
369
370void
371gtk_tree_item_collapse (GtkTreeItem *tree_item)
372{
373  g_return_if_fail (tree_item != NULL);
374  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
375
376  gtk_signal_emit (GTK_OBJECT (tree_item), tree_item_signals[COLLAPSE_TREE], NULL);
377}
378
379static void
380gtk_tree_item_add_pixmaps (GtkTreeItem *tree_item)
381{
382  GList *tmp_list;
383  GdkColormap *colormap;
384  GtkTreePixmaps *pixmap_node = NULL;
385
386  g_return_if_fail (tree_item != NULL);
387  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
388
389  if (tree_item->pixmaps)
390    return;
391
392  colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_item));
393
394  tmp_list = pixmaps;
395  while (tmp_list)
396    {
397      pixmap_node = (GtkTreePixmaps *)tmp_list->data;
398
399      if (pixmap_node->colormap == colormap)
400        break;
401     
402      tmp_list = tmp_list->next;
403    }
404
405  if (tmp_list)
406    {
407      pixmap_node->refcount++;
408      tree_item->pixmaps = tmp_list;
409    }
410  else
411    {
412      pixmap_node = g_new (GtkTreePixmaps, 1);
413
414      pixmap_node->colormap = colormap;
415      gdk_colormap_ref (colormap);
416
417      pixmap_node->refcount = 1;
418
419      /* create pixmaps for plus icon */
420      pixmap_node->pixmap_plus =
421        gdk_pixmap_create_from_xpm_d (GTK_WIDGET (tree_item)->window,
422                                      &pixmap_node->mask_plus,
423                                      NULL,
424                                      tree_plus);
425     
426      /* create pixmaps for minus icon */
427      pixmap_node->pixmap_minus =
428        gdk_pixmap_create_from_xpm_d (GTK_WIDGET (tree_item)->window,
429                                      &pixmap_node->mask_minus,
430                                      NULL,
431                                      tree_minus);
432
433      tree_item->pixmaps = pixmaps = g_list_prepend (pixmaps, pixmap_node);
434    }
435 
436  gtk_pixmap_set (GTK_PIXMAP (tree_item->plus_pix_widget),
437                  pixmap_node->pixmap_plus, pixmap_node->mask_plus);
438  gtk_pixmap_set (GTK_PIXMAP (tree_item->minus_pix_widget),
439                  pixmap_node->pixmap_minus, pixmap_node->mask_minus);
440}
441
442static void
443gtk_tree_item_remove_pixmaps (GtkTreeItem *tree_item)
444{
445  g_return_if_fail (tree_item != NULL);
446  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
447
448  if (tree_item->pixmaps)
449    {
450      GtkTreePixmaps *pixmap_node = (GtkTreePixmaps *)tree_item->pixmaps->data;
451     
452      g_assert (pixmap_node->refcount > 0);
453     
454      if (--pixmap_node->refcount == 0)
455        {
456          gdk_colormap_unref (pixmap_node->colormap);
457          gdk_pixmap_unref (pixmap_node->pixmap_plus);
458          gdk_bitmap_unref (pixmap_node->mask_plus);
459          gdk_pixmap_unref (pixmap_node->pixmap_minus);
460          gdk_bitmap_unref (pixmap_node->mask_minus);
461         
462          pixmaps = g_list_remove_link (pixmaps, tree_item->pixmaps);
463          g_list_free_1 (tree_item->pixmaps);
464          g_free (pixmap_node);
465        }
466
467      tree_item->pixmaps = NULL;
468    }
469}
470
471static void
472gtk_tree_item_realize (GtkWidget *widget)
473{   
474  g_return_if_fail (widget != NULL);
475  g_return_if_fail (GTK_IS_TREE_ITEM (widget));
476
477  if (GTK_WIDGET_CLASS (parent_class)->realize)
478    (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
479 
480  gdk_window_set_background (widget->window,
481                             &widget->style->base[GTK_STATE_NORMAL]);
482
483  gtk_tree_item_add_pixmaps (GTK_TREE_ITEM (widget));
484}
485
486static void
487gtk_tree_item_size_request (GtkWidget      *widget,
488                            GtkRequisition *requisition)
489{
490  GtkBin *bin;
491  GtkTreeItem* item;
492  GtkRequisition child_requisition;
493
494  g_return_if_fail (widget != NULL);
495  g_return_if_fail (GTK_IS_TREE_ITEM (widget));
496  g_return_if_fail (requisition != NULL);
497
498  bin = GTK_BIN (widget);
499  item = GTK_TREE_ITEM(widget);
500
501  requisition->width = (GTK_CONTAINER (widget)->border_width +
502                        widget->style->klass->xthickness) * 2;
503  requisition->height = GTK_CONTAINER (widget)->border_width * 2;
504
505  if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
506    {
507      GtkRequisition pix_requisition;
508     
509      gtk_widget_size_request (bin->child, &child_requisition);
510
511      requisition->width += child_requisition.width;
512
513      gtk_widget_size_request (item->pixmaps_box,
514                               &pix_requisition);
515      requisition->width += pix_requisition.width + DEFAULT_DELTA +
516        GTK_TREE (widget->parent)->current_indent;
517
518      requisition->height += MAX (child_requisition.height,
519                                  pix_requisition.height);
520    }
521}
522
523static void
524gtk_tree_item_size_allocate (GtkWidget     *widget,
525                             GtkAllocation *allocation)
526{
527  GtkBin *bin;
528  GtkTreeItem* item;
529  GtkAllocation child_allocation;
530  gint border_width;
531  int temp;
532
533  g_return_if_fail (widget != NULL);
534  g_return_if_fail (GTK_IS_TREE_ITEM (widget));
535  g_return_if_fail (allocation != NULL);
536
537  widget->allocation = *allocation;
538  if (GTK_WIDGET_REALIZED (widget))
539    gdk_window_move_resize (widget->window,
540                            allocation->x, allocation->y,
541                            allocation->width, allocation->height);
542
543  bin = GTK_BIN (widget);
544  item = GTK_TREE_ITEM(widget);
545
546  if (bin->child)
547    {
548      border_width = (GTK_CONTAINER (widget)->border_width +
549                      widget->style->klass->xthickness);
550
551      child_allocation.x = border_width + GTK_TREE(widget->parent)->current_indent;
552      child_allocation.y = GTK_CONTAINER (widget)->border_width;
553
554      child_allocation.width = item->pixmaps_box->requisition.width;
555      child_allocation.height = item->pixmaps_box->requisition.height;
556     
557      temp = allocation->height - child_allocation.height;
558      child_allocation.y += ( temp / 2 ) + ( temp % 2 );
559
560      gtk_widget_size_allocate (item->pixmaps_box, &child_allocation);
561
562      child_allocation.y = GTK_CONTAINER (widget)->border_width;
563      child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2);
564      child_allocation.x += item->pixmaps_box->requisition.width+DEFAULT_DELTA;
565
566      child_allocation.width =
567        MAX (1, (gint)allocation->width - ((gint)child_allocation.x + border_width));
568
569      gtk_widget_size_allocate (bin->child, &child_allocation);
570    }
571}
572
573static void
574gtk_tree_item_draw_lines (GtkWidget *widget)
575{
576  GtkTreeItem* item;
577  GtkTree* tree;
578  guint lx1, ly1, lx2, ly2;
[15780]579  GdkGC* gc;
[14481]580
581  g_return_if_fail (widget != NULL);
582  g_return_if_fail (GTK_IS_TREE_ITEM (widget));
583
584  item = GTK_TREE_ITEM(widget);
585  tree = GTK_TREE(widget->parent);
586
587  if (!tree->view_line)
588    return;
589
[15780]590  gc = widget->style->text_gc[GTK_STATE_NORMAL];
591
[14481]592  /* draw vertical line */
593  lx1 = item->pixmaps_box->allocation.width;
594  lx1 = lx2 = ((lx1 / 2) + (lx1 % 2) +
595               GTK_CONTAINER (widget)->border_width + 1 + tree->current_indent);
596  ly1 = 0;
597  ly2 = widget->allocation.height;
598
599  if (g_list_last (tree->children)->data == widget)
600    ly2 = (ly2 / 2) + (ly2 % 2);
601
602  if (tree != tree->root_tree)
[15780]603    gdk_draw_line (widget->window, gc, lx1, ly1, lx2, ly2);
[14481]604
605  /* draw vertical line for subtree connecting */
606  if(g_list_last(tree->children)->data != (gpointer)widget)
607    ly2 = (ly2 / 2) + (ly2 % 2);
608 
609  lx2 += DEFAULT_DELTA;
610
611  if (item->subtree && item->expanded)
[15780]612    gdk_draw_line (widget->window, gc,
[14481]613                   lx2, ly2, lx2, widget->allocation.height);
614
615  /* draw horizontal line */
616  ly1 = ly2;
617  lx2 += 2;
618
[15780]619  gdk_draw_line (widget->window, gc, lx1, ly1, lx2, ly2);
[14481]620
621  lx2 -= DEFAULT_DELTA+2;
622  ly1 = 0;
623  ly2 = widget->allocation.height;
624
625  if (tree != tree->root_tree)
626    {
627      item = GTK_TREE_ITEM (tree->tree_owner);
628      tree = GTK_TREE (GTK_WIDGET (tree)->parent);
629      while (tree != tree->root_tree)
630        {
631          lx1 = lx2 -= tree->indent_value;
632         
633          if (g_list_last (tree->children)->data != item)
[15780]634            gdk_draw_line (widget->window, gc, lx1, ly1, lx2, ly2);
[14481]635          item = GTK_TREE_ITEM (tree->tree_owner);
636          tree = GTK_TREE (GTK_WIDGET (tree)->parent);
637        }
638    }
639}
640
641static void
642gtk_tree_item_paint (GtkWidget    *widget,
643                     GdkRectangle *area)
644{
645  GtkBin *bin;
646  GdkRectangle child_area, item_area;
647  GtkTreeItem* tree_item;
648
649  g_return_if_fail (widget != NULL);
650  g_return_if_fail (GTK_IS_TREE_ITEM (widget));
651  g_return_if_fail (area != NULL);
652
653  /* FIXME: We should honor tree->view_mode, here - I think
654   * the desired effect is that when the mode is VIEW_ITEM,
655   * only the subitem is drawn as selected, not the entire
656   * line. (Like the way that the tree in Windows Explorer
657   * works).
658   */
659  if (GTK_WIDGET_DRAWABLE (widget))
660    {
661      bin = GTK_BIN (widget);
662      tree_item = GTK_TREE_ITEM(widget);
663
664      if (widget->state == GTK_STATE_NORMAL)
665        {
666          gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
667          gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
668        }
669      else
670        {
671          if (!GTK_WIDGET_IS_SENSITIVE (widget))
672            gtk_paint_flat_box(widget->style, widget->window,
673                               widget->state, GTK_STATE_INSENSITIVE,
674                               area, widget, "treeitem",
675                               0, 0, -1, -1);
676          else
677            gtk_paint_flat_box(widget->style, widget->window,
678                               widget->state, GTK_SHADOW_ETCHED_OUT,
679                               area, widget, "treeitem",
680                               0, 0, -1, -1);
681        }
682
683      /* draw left size of tree item */
684      item_area.x = 0;
685      item_area.y = 0;
686      item_area.width = (tree_item->pixmaps_box->allocation.width + DEFAULT_DELTA +
687                         GTK_TREE (widget->parent)->current_indent + 2);
688      item_area.height = widget->allocation.height;
689
690
691      if (gdk_rectangle_intersect(&item_area, area, &child_area))
692        {
693         
694          gtk_tree_item_draw_lines(widget);
695
696          if (tree_item->pixmaps_box &&
697              GTK_WIDGET_VISIBLE(tree_item->pixmaps_box) &&
698              gtk_widget_intersect (tree_item->pixmaps_box, area, &child_area))
699            gtk_widget_draw (tree_item->pixmaps_box, &child_area);
700        }
701
702      if (GTK_WIDGET_HAS_FOCUS (widget))
703        gtk_paint_focus (widget->style, widget->window,
704                         NULL, widget, "treeitem",
705                         0, 0,
706                         widget->allocation.width - 1,
707                         widget->allocation.height - 1);
708     
709    }
710}
711
712static void
713gtk_tree_item_draw (GtkWidget    *widget,
714                    GdkRectangle *area)
715{
716  GtkBin *bin;
717  GdkRectangle child_area;
718
719  g_return_if_fail (widget != NULL);
720  g_return_if_fail (GTK_IS_TREE_ITEM (widget));
721  g_return_if_fail (area != NULL);
722
723  if (GTK_WIDGET_DRAWABLE (widget))
724    {
725      bin = GTK_BIN (widget);
726
727      gtk_tree_item_paint (widget, area);
728     
729      if (bin->child &&
730          gtk_widget_intersect (bin->child, area, &child_area))
731        gtk_widget_draw (bin->child, &child_area);
732
733    }
734}
735
736static void
737gtk_tree_item_draw_focus (GtkWidget *widget)
738{
739  g_return_if_fail (widget != NULL);
740  g_return_if_fail (GTK_IS_TREE_ITEM (widget));
741
742  gtk_widget_draw(widget, NULL);
743}
744
745static gint
746gtk_tree_item_button_press (GtkWidget      *widget,
747                            GdkEventButton *event)
748{
749
750  g_return_val_if_fail (widget != NULL, FALSE);
751  g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
752  g_return_val_if_fail (event != NULL, FALSE);
753
754  if (event->type == GDK_BUTTON_PRESS
755        && GTK_WIDGET_IS_SENSITIVE(widget)
756        && !GTK_WIDGET_HAS_FOCUS (widget))
757      gtk_widget_grab_focus (widget);
758
759  return FALSE;
760}
761
762static gint
763gtk_tree_item_expose (GtkWidget      *widget,
764                      GdkEventExpose *event)
765{
766  GdkEventExpose child_event;
767  GtkBin *bin;
768
769  g_return_val_if_fail (widget != NULL, FALSE);
770  g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
771  g_return_val_if_fail (event != NULL, FALSE);
772
773  if (GTK_WIDGET_DRAWABLE (widget))
774    {
775      bin = GTK_BIN (widget);
776     
777      gtk_tree_item_paint (widget, &event->area);
778
779      child_event = *event;
780      if (bin->child && GTK_WIDGET_NO_WINDOW (bin->child) &&
781          gtk_widget_intersect (bin->child, &event->area, &child_event.area))
782        gtk_widget_event (bin->child, (GdkEvent*) &child_event);
783   }
784
785  return FALSE;
786}
787
788static gint
789gtk_tree_item_focus_in (GtkWidget     *widget,
790                        GdkEventFocus *event)
791{
792  g_return_val_if_fail (widget != NULL, FALSE);
793  g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
794  g_return_val_if_fail (event != NULL, FALSE);
795
796  GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
797  gtk_widget_draw_focus (widget);
798
799
800  return FALSE;
801}
802
803static gint
804gtk_tree_item_focus_out (GtkWidget     *widget,
805                         GdkEventFocus *event)
806{
807  g_return_val_if_fail (widget != NULL, FALSE);
808  g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
809  g_return_val_if_fail (event != NULL, FALSE);
810
811  GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
812  gtk_widget_draw_focus (widget);
813
814
815  return FALSE;
816}
817
818static void
819gtk_real_tree_item_select (GtkItem *item)
820{   
821  GtkTreeItem *tree_item;
822  GtkWidget *widget;
823
824  g_return_if_fail (item != NULL);
825  g_return_if_fail (GTK_IS_TREE_ITEM (item));
826
827  tree_item = GTK_TREE_ITEM (item);
828  widget = GTK_WIDGET (item);
829
830  gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED);
831
832  if (!widget->parent || GTK_TREE (widget->parent)->view_mode == GTK_TREE_VIEW_LINE)
833    gtk_widget_set_state (GTK_TREE_ITEM (item)->pixmaps_box, GTK_STATE_SELECTED);
834}
835
836static void
837gtk_real_tree_item_deselect (GtkItem *item)
838{
839  GtkTreeItem *tree_item;
840  GtkWidget *widget;
841
842  g_return_if_fail (item != NULL);
843  g_return_if_fail (GTK_IS_TREE_ITEM (item));
844
845  tree_item = GTK_TREE_ITEM (item);
846  widget = GTK_WIDGET (item);
847
848  gtk_widget_set_state (widget, GTK_STATE_NORMAL);
849
850  if (!widget->parent || GTK_TREE (widget->parent)->view_mode == GTK_TREE_VIEW_LINE)
851    gtk_widget_set_state (tree_item->pixmaps_box, GTK_STATE_NORMAL);
852}
853
854static void
855gtk_real_tree_item_toggle (GtkItem *item)
856{
857  g_return_if_fail (item != NULL);
858  g_return_if_fail (GTK_IS_TREE_ITEM (item));
859
860  if(!GTK_WIDGET_IS_SENSITIVE(item))
861    return;
862
863  if (GTK_WIDGET (item)->parent && GTK_IS_TREE (GTK_WIDGET (item)->parent))
864    gtk_tree_select_child (GTK_TREE (GTK_WIDGET (item)->parent),
865                           GTK_WIDGET (item));
866  else
867    {
868      /* Should we really bother with this bit? A listitem not in a list?
869       * -Johannes Keukelaar
870       * yes, always be on the safe side!
871       * -timj
872       */
873      if (GTK_WIDGET (item)->state == GTK_STATE_SELECTED)
874        gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL);
875      else
876        gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED);
877    }
878}
879
880static void
881gtk_real_tree_item_expand (GtkTreeItem *tree_item)
882{
883  GtkTree* tree;
884 
885  g_return_if_fail (tree_item != NULL);
886  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
887 
888  if (tree_item->subtree && !tree_item->expanded)
889    {
890      tree = GTK_TREE (GTK_WIDGET (tree_item)->parent);
891     
892      /* hide subtree widget */
893      gtk_widget_show (tree_item->subtree);
894     
895      /* hide button '+' and show button '-' */
896      if (tree_item->pixmaps_box)
897        {
898          gtk_container_remove (GTK_CONTAINER (tree_item->pixmaps_box),
899                                tree_item->plus_pix_widget);
900          gtk_container_add (GTK_CONTAINER (tree_item->pixmaps_box),
901                             tree_item->minus_pix_widget);
902        }
903      if (tree->root_tree)
904        gtk_widget_queue_resize (GTK_WIDGET (tree->root_tree));
905      tree_item->expanded = TRUE;
906    }
907}
908
909static void
910gtk_real_tree_item_collapse (GtkTreeItem *tree_item)
911{
912  GtkTree* tree;
913 
914  g_return_if_fail (tree_item != NULL);
915  g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
916 
917  if (tree_item->subtree && tree_item->expanded)
918    {
919      tree = GTK_TREE (GTK_WIDGET (tree_item)->parent);
920     
921      /* hide subtree widget */
922      gtk_widget_hide (tree_item->subtree);
923     
924      /* hide button '-' and show button '+' */
925      if (tree_item->pixmaps_box)
926        {
927          gtk_container_remove (GTK_CONTAINER (tree_item->pixmaps_box),
928                                tree_item->minus_pix_widget);
929          gtk_container_add (GTK_CONTAINER (tree_item->pixmaps_box),
930                             tree_item->plus_pix_widget);
931        }
932      if (tree->root_tree)
933        gtk_widget_queue_resize (GTK_WIDGET (tree->root_tree));
934      tree_item->expanded = FALSE;
935    }
936}
937
938static void
939gtk_tree_item_destroy (GtkObject *object)
940{
941  GtkTreeItem* item;
942  GtkWidget* child;
943
944  g_return_if_fail (object != NULL);
945  g_return_if_fail (GTK_IS_TREE_ITEM (object));
946
947#ifdef TREE_DEBUG
948  g_message("+ gtk_tree_item_destroy [object %#x]\n", (int)object);
949#endif /* TREE_DEBUG */
950
951  item = GTK_TREE_ITEM(object);
952
953  /* free sub tree if it exist */
954  child = item->subtree;
955  if (child)
956    {
957      gtk_widget_ref (child);
958      gtk_widget_unparent (child);
959      gtk_widget_destroy (child);
960      gtk_widget_unref (child);
961      item->subtree = NULL;
962    }
963 
964  /* free pixmaps box */
965  child = item->pixmaps_box;
966  if (child)
967    {
968      gtk_widget_ref (child);
969      gtk_widget_unparent (child);
970      gtk_widget_destroy (child);
971      gtk_widget_unref (child);
972      item->pixmaps_box = NULL;
973    }
974 
975 
976  /* destroy plus pixmap */
977  if (item->plus_pix_widget)
978    {
979      gtk_widget_destroy (item->plus_pix_widget);
980      gtk_widget_unref (item->plus_pix_widget);
981      item->plus_pix_widget = NULL;
982    }
983 
984  /* destroy minus pixmap */
985  if (item->minus_pix_widget)
986    {
987      gtk_widget_destroy (item->minus_pix_widget);
988      gtk_widget_unref (item->minus_pix_widget);
989      item->minus_pix_widget = NULL;
990    }
991 
992  /* By removing the pixmaps here, and not in unrealize, we depend on
993   * the fact that a widget can never change colormap or visual.
994   */
995  gtk_tree_item_remove_pixmaps (item);
996 
997  GTK_OBJECT_CLASS (parent_class)->destroy (object);
998 
999#ifdef TREE_DEBUG
1000  g_message("- gtk_tree_item_destroy\n");
1001#endif /* TREE_DEBUG */
1002}
1003
1004void
1005gtk_tree_item_remove_subtree (GtkTreeItem* item)
1006{
1007  g_return_if_fail (item != NULL);
1008  g_return_if_fail (GTK_IS_TREE_ITEM(item));
1009  g_return_if_fail (item->subtree != NULL);
1010 
1011  if (GTK_TREE (item->subtree)->children)
1012    {
1013      /* The following call will remove the children and call
1014       * gtk_tree_item_remove_subtree() again. So we are done.
1015       */
1016      gtk_tree_remove_items (GTK_TREE (item->subtree),
1017                             GTK_TREE (item->subtree)->children);
1018      return;
1019    }
1020
1021  if (GTK_WIDGET_MAPPED (item->subtree))
1022    gtk_widget_unmap (item->subtree);
1023     
1024  gtk_widget_unparent (item->subtree);
1025 
1026  if (item->pixmaps_box)
1027    gtk_widget_hide (item->pixmaps_box);
1028 
1029  item->subtree = NULL;
1030
1031  if (item->expanded)
1032    {
1033      item->expanded = FALSE;
1034      if (item->pixmaps_box)
1035        {
1036          gtk_container_remove (GTK_CONTAINER (item->pixmaps_box),
1037                                item->minus_pix_widget);
1038          gtk_container_add (GTK_CONTAINER (item->pixmaps_box),
1039                             item->plus_pix_widget);
1040        }
1041    }
1042}
1043
1044static void
1045gtk_tree_item_map (GtkWidget *widget)
1046{
1047  GtkBin *bin;
1048  GtkTreeItem* item;
1049
1050  g_return_if_fail (widget != NULL);
1051  g_return_if_fail (GTK_IS_TREE_ITEM (widget));
1052
1053  bin = GTK_BIN (widget);
1054  item = GTK_TREE_ITEM(widget);
1055
1056  GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1057
1058  if(item->pixmaps_box &&
1059     GTK_WIDGET_VISIBLE (item->pixmaps_box) &&
1060     !GTK_WIDGET_MAPPED (item->pixmaps_box))
1061    gtk_widget_map (item->pixmaps_box);
1062
1063  if (bin->child &&
1064      GTK_WIDGET_VISIBLE (bin->child) &&
1065      !GTK_WIDGET_MAPPED (bin->child))
1066    gtk_widget_map (bin->child);
1067
1068  gdk_window_show (widget->window);
1069}
1070
1071static void
1072gtk_tree_item_unmap (GtkWidget *widget)
1073{
1074  GtkBin *bin;
1075  GtkTreeItem* item;
1076
1077  g_return_if_fail (widget != NULL);
1078  g_return_if_fail (GTK_IS_TREE_ITEM (widget));
1079
1080  GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1081  bin = GTK_BIN (widget);
1082  item = GTK_TREE_ITEM(widget);
1083
1084  gdk_window_hide (widget->window);
1085
1086  if(item->pixmaps_box &&
1087     GTK_WIDGET_VISIBLE (item->pixmaps_box) &&
1088     GTK_WIDGET_MAPPED (item->pixmaps_box))
1089    gtk_widget_unmap (bin->child);
1090
1091  if (bin->child &&
1092      GTK_WIDGET_VISIBLE (bin->child) &&
1093      GTK_WIDGET_MAPPED (bin->child))
1094    gtk_widget_unmap (bin->child);
1095}
1096
1097static void
1098gtk_tree_item_forall (GtkContainer *container,
1099                      gboolean      include_internals,
1100                      GtkCallback   callback,
1101                      gpointer      callback_data)
1102{
1103  GtkBin *bin;
1104  GtkTreeItem *tree_item;
1105
1106  g_return_if_fail (container != NULL);
1107  g_return_if_fail (GTK_IS_TREE_ITEM (container));
1108  g_return_if_fail (callback != NULL);
1109
1110  bin = GTK_BIN (container);
1111  tree_item = GTK_TREE_ITEM (container);
1112
1113  if (bin->child)
1114    (* callback) (bin->child, callback_data);
1115  if (include_internals && tree_item->subtree)
1116    (* callback) (tree_item->subtree, callback_data);
1117}
Note: See TracBrowser for help on using the repository browser.