]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtklist.c
Changed LGPL address for FSF in all .h and .c files
[~andy/gtk] / gtk / gtklist.c
index 7d7d4a66d72236b147e8b82ce116f0bc06a3b13c..cd47c69851ad4947b23fbebbc7f06f2207f852a2 100644 (file)
@@ -12,8 +12,9 @@
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
  */
 #include "gtklist.h"
 #include "gtklistitem.h"
@@ -74,7 +75,7 @@ static void gtk_list_marshal_signal (GtkObject      *object,
 
 
 static GtkContainerClass *parent_class = NULL;
-static gint list_signals[LAST_SIGNAL] = { 0 };
+static guint list_signals[LAST_SIGNAL] = { 0 };
 
 
 guint
@@ -91,7 +92,8 @@ gtk_list_get_type ()
        sizeof (GtkListClass),
        (GtkClassInitFunc) gtk_list_class_init,
        (GtkObjectInitFunc) gtk_list_init,
-       (GtkArgFunc) NULL,
+       (GtkArgSetFunc) NULL,
+        (GtkArgGetFunc) NULL,
       };
 
       list_type = gtk_type_unique (gtk_container_get_type (), &list_info);
@@ -180,6 +182,40 @@ gtk_list_new ()
   return GTK_WIDGET (gtk_type_new (gtk_list_get_type ()));
 }
 
+static void
+gtk_list_destroy (GtkObject *object)
+{
+  GList *node;
+
+  GtkList *list = GTK_LIST (object);
+
+  for (node = list->children; node; node = node->next)
+    {
+      GtkWidget *child;
+
+      child = (GtkWidget *)node->data;
+      gtk_widget_ref (child);
+      gtk_widget_unparent (child);
+      gtk_widget_destroy (child);
+      gtk_widget_unref (child);
+    }
+  g_list_free (list->children);
+  list->children = NULL;
+
+  for (node = list->selection; node; node = node->next)
+    {
+      GtkWidget *child;
+
+      child = (GtkWidget *)node->data;
+      gtk_widget_unref (child);
+    }
+  g_list_free (list->selection);
+  list->selection = NULL;
+
+  if (GTK_OBJECT_CLASS (parent_class)->destroy)
+    (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
 void
 gtk_list_insert_items (GtkList *list,
                       GList   *items,
@@ -279,37 +315,40 @@ gtk_list_prepend_items (GtkList *list,
   gtk_list_insert_items (list, items, 0);
 }
 
-void
-gtk_list_remove_items (GtkList *list,
-                      GList   *items)
+static void
+gtk_list_remove_items_internal (GtkList  *list,
+                               GList    *items,
+                               gboolean no_unref)
 {
   GtkWidget *widget;
   GList *selected_widgets;
   GList *tmp_list;
-
+  
   g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
-
+  
   tmp_list = items;
   selected_widgets = NULL;
   widget = NULL;
-
+  
   while (tmp_list)
     {
       widget = tmp_list->data;
       tmp_list = tmp_list->next;
-
+      
       if (widget->state == GTK_STATE_SELECTED)
        selected_widgets = g_list_prepend (selected_widgets, widget);
-
+      
       list->children = g_list_remove (list->children, widget);
-
+      
       if (GTK_WIDGET_MAPPED (widget))
        gtk_widget_unmap (widget);
-
+      
+      if (no_unref)
+       gtk_widget_ref (widget);
       gtk_widget_unparent (widget);
     }
-
+  
   if (selected_widgets)
     {
       tmp_list = selected_widgets;
@@ -317,26 +356,40 @@ gtk_list_remove_items (GtkList *list,
        {
          widget = tmp_list->data;
          tmp_list = tmp_list->next;
-
+         
          gtk_list_unselect_child (list, widget);
        }
-
+      
       gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
     }
-
+  
   g_list_free (selected_widgets);
-
+  
   if (list->children && !list->selection &&
       (list->selection_mode == GTK_SELECTION_BROWSE))
     {
       widget = list->children->data;
       gtk_list_select_child (list, widget);
     }
-
+  
   if (GTK_WIDGET_VISIBLE (list))
     gtk_widget_queue_resize (GTK_WIDGET (list));
 }
 
+void
+gtk_list_remove_items (GtkList  *list,
+                      GList    *items)
+{
+  gtk_list_remove_items_internal (list, items, FALSE);
+}
+
+void
+gtk_list_remove_items_no_unref (GtkList  *list,
+                               GList    *items)
+{
+  gtk_list_remove_items_internal (list, items, TRUE);
+}
+
 void
 gtk_list_clear_items (GtkList *list,
                      gint     start,
@@ -346,8 +399,8 @@ gtk_list_clear_items (GtkList *list,
   GList *start_list;
   GList *end_list;
   GList *tmp_list;
-  gint nchildren;
-  gint selection_changed;
+  guint nchildren;
+  gboolean selection_changed;
 
   g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
@@ -359,13 +412,14 @@ gtk_list_clear_items (GtkList *list,
       if ((end < 0) || (end > nchildren))
        end = nchildren;
 
-      g_return_if_fail (start < end);
+      if (start >= end)
+       return;
 
       start_list = g_list_nth (list->children, start);
       end_list = g_list_nth (list->children, end);
 
       if (start_list->prev)
-        start_list->prev->next = end_list;
+       start_list->prev->next = end_list;
       if (end_list && end_list->prev)
         end_list->prev->next = NULL;
       if (end_list)
@@ -386,19 +440,19 @@ gtk_list_clear_items (GtkList *list,
            {
              selection_changed = TRUE;
              list->selection = g_list_remove (list->selection, widget);
+             gtk_widget_unref (widget);
            }
 
-         /* list->children = g_list_remove (list->children, widget); */
-         /* gtk_widget_unparent (widget); */
-
-         gtk_widget_destroy (widget);
+         gtk_widget_unparent (widget);
        }
 
+      g_list_free (start_list);
+
       if (list->children && !list->selection &&
          (list->selection_mode == GTK_SELECTION_BROWSE))
        {
-         gtk_list_select_child (list, widget);
          widget = list->children->data;
+         gtk_list_select_child (list, widget);
        }
 
       if (selection_changed)
@@ -487,36 +541,6 @@ gtk_list_set_selection_mode (GtkList          *list,
 }
 
 
-static void
-gtk_list_destroy (GtkObject *object)
-{
-  GtkList *list;
-  GtkWidget *child;
-  GList *children;
-
-  g_return_if_fail (object != NULL);
-  g_return_if_fail (GTK_IS_LIST (object));
-
-  list = GTK_LIST (object);
-
-  children = list->children;
-  while (children)
-    {
-      child = children->data;
-      children = children->next;
-
-      child->parent = NULL;
-      gtk_object_unref (GTK_OBJECT (child));
-      gtk_widget_destroy (child);
-    }
-
-  g_list_free (list->children);
-  g_list_free (list->selection);
-
-  if (GTK_OBJECT_CLASS (parent_class)->destroy)
-    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
-}
-
 static void
 gtk_list_map (GtkWidget *widget)
 {
@@ -573,15 +597,16 @@ gtk_list_realize (GtkWidget *widget)
   attributes.wclass = GDK_INPUT_OUTPUT;
   attributes.visual = gtk_widget_get_visual (widget);
   attributes.colormap = gtk_widget_get_colormap (widget);
-  attributes.event_mask = GDK_EXPOSURE_MASK;
+  attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
 
   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
 
-  widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
   gdk_window_set_user_data (widget->window, widget);
 
   widget->style = gtk_style_attach (widget->style, widget->window);
-  gdk_window_set_background (widget->window, &widget->style->white);
+  gdk_window_set_background (widget->window, 
+                            &widget->style->base[GTK_STATE_NORMAL]);
 }
 
 static void
@@ -655,7 +680,7 @@ gtk_list_motion_notify (GtkWidget      *widget,
   g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
 
-  g_print ("gtk_list_motion_notify\n");
+  /* g_print ("gtk_list_motion_notify\n"); */
 
   return FALSE;
 }
@@ -673,10 +698,13 @@ gtk_list_button_press (GtkWidget      *widget,
 
   list = GTK_LIST (widget);
   item = gtk_get_event_widget ((GdkEvent*) event);
-
-  while (!gtk_type_is_a (GTK_WIDGET_TYPE (item), gtk_list_item_get_type ()))
+  
+  while (item && !GTK_IS_LIST_ITEM (item))
     item = item->parent;
 
+  if (!item || (item->parent != widget))
+    return FALSE;
+  
   gtk_list_select_child (list, item);
 
   return FALSE;
@@ -762,7 +790,7 @@ gtk_list_size_allocate (GtkWidget     *widget,
     {
       child_allocation.x = GTK_CONTAINER (list)->border_width;
       child_allocation.y = GTK_CONTAINER (list)->border_width;
-      child_allocation.width = allocation->width - child_allocation.x * 2;
+      child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2);
 
       children = list->children;
 
@@ -792,6 +820,7 @@ gtk_list_add (GtkContainer *container,
   g_return_if_fail (container != NULL);
   g_return_if_fail (GTK_IS_LIST (container));
   g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_LIST_ITEM (widget));
 
   list = GTK_LIST (container);
 
@@ -810,9 +839,7 @@ gtk_list_add (GtkContainer *container,
   list->children = g_list_append (list->children, widget);
 
   if (!list->selection && (list->selection_mode == GTK_SELECTION_BROWSE))
-    {
-      gtk_list_select_child (list, widget);
-    }
+    gtk_list_select_child (list, widget);
 
   if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
     gtk_widget_queue_resize (widget);
@@ -889,11 +916,12 @@ gtk_real_list_select_child (GtkList   *list,
          if (tmp_item != child)
            {
              gtk_list_item_deselect (GTK_LIST_ITEM (tmp_item));
-
+             
              tmp_list = selection;
              selection = selection->next;
 
              list->selection = g_list_remove_link (list->selection, tmp_list);
+             gtk_widget_unref (GTK_WIDGET (tmp_item));
 
              g_list_free (tmp_list);
            }
@@ -905,11 +933,13 @@ gtk_real_list_select_child (GtkList   *list,
        {
          gtk_list_item_select (GTK_LIST_ITEM (child));
          list->selection = g_list_prepend (list->selection, child);
+         gtk_widget_ref (child);
        }
       else if (child->state == GTK_STATE_SELECTED)
        {
          gtk_list_item_deselect (GTK_LIST_ITEM (child));
          list->selection = g_list_remove (list->selection, child);
+         gtk_widget_unref (child);
        }
 
       gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
@@ -925,11 +955,12 @@ gtk_real_list_select_child (GtkList   *list,
          if (tmp_item != child)
            {
              gtk_list_item_deselect (GTK_LIST_ITEM (tmp_item));
-
+             
              tmp_list = selection;
              selection = selection->next;
 
              list->selection = g_list_remove_link (list->selection, tmp_list);
+             gtk_widget_unref (GTK_WIDGET (tmp_item));
 
              g_list_free (tmp_list);
            }
@@ -941,6 +972,7 @@ gtk_real_list_select_child (GtkList   *list,
        {
          gtk_list_item_select (GTK_LIST_ITEM (child));
          list->selection = g_list_prepend (list->selection, child);
+         gtk_widget_ref (child);
          gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
        }
       break;
@@ -950,12 +982,14 @@ gtk_real_list_select_child (GtkList   *list,
        {
          gtk_list_item_select (GTK_LIST_ITEM (child));
          list->selection = g_list_prepend (list->selection, child);
+         gtk_widget_ref (child);
          gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
        }
       else if (child->state == GTK_STATE_SELECTED)
        {
          gtk_list_item_deselect (GTK_LIST_ITEM (child));
          list->selection = g_list_remove (list->selection, child);
+         gtk_widget_unref (child);
          gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
        }
       break;
@@ -983,6 +1017,7 @@ gtk_real_list_unselect_child (GtkList   *list,
        {
          gtk_list_item_deselect (GTK_LIST_ITEM (child));
          list->selection = g_list_remove (list->selection, child);
+         gtk_widget_unref (child);
          gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
        }
       break;