]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtknotebook.c
Add GtkScrollable interface
[~andy/gtk] / gtk / gtknotebook.c
index 207aff5cefc6d6952b6a9e43061335574b4f9a70..2827645f9661bc99da8d0bde5453491a7b051710 100644 (file)
 #include "gtkdnd.h"
 #include "gtkbuildable.h"
 
+
+/**
+ * SECTION:gtknotebook
+ * @Short_description: A tabbed notebook container
+ * @Title: GtkNotebook
+ * @See_also: #GtkContainer
+ *
+ * The #GtkNotebook widget is a #GtkContainer whose children are pages that
+ * can be switched between using tab labels along one edge.
+ *
+ * There are many configuration options for GtkNotebook. Among other
+ * things, you can choose on which edge the tabs appear
+ * (see gtk_notebook_set_tab_pos()), whether, if there are too many
+ * tabs to fit the notebook should be made bigger or scrolling
+ * arrows added (see gtk_notebook_set_scrollable()), and whether there
+ * will be a popup menu allowing the users to switch pages.
+ * (see gtk_notebook_popup_enable(), gtk_notebook_popup_disable())
+ *
+ * <refsect2 id="GtkNotebook-BUILDER-UI">
+ * <title>GtkNotebook as GtkBuildable</title>
+ * <para>
+ * The GtkNotebook implementation of the #GtkBuildable interface
+ * supports placing children into tabs by specifying "tab" as the
+ * "type" attribute of a &lt;child&gt; element. Note that the content
+ * of the tab must be created before the tab can be filled.
+ * A tab child can be specified without specifying a &lt;child&gt;
+ * type attribute.
+ *
+ * To add a child widget in the notebooks action area, specify
+ * "action-start" or "action-end" as the "type" attribute of the &lt;child&gt;
+ * element.
+ * </para>
+ * <example>
+ * <title>A UI definition fragment with GtkNotebook</title>
+ * <programlisting><![CDATA[
+ * <object class="GtkNotebook">
+ *   <child>
+ *     <object class="GtkLabel" id="notebook-content">
+ *       <property name="label">Content</property>
+ *     </object>
+ *   </child>
+ *   <child type="tab">
+ *     <object class="GtkLabel" id="notebook-tab">
+ *       <property name="label">Tab</property>
+ *     </object>
+ *   </child>
+ * </object>
+ * ]]></programlisting>
+ * </example>
+ * </refsect2>
+ */
+
+
 #define SCROLL_DELAY_FACTOR   5
 #define SCROLL_THRESHOLD      12
 #define DND_THRESHOLD_MULTIPLIER 4
@@ -262,8 +315,7 @@ static void     gtk_notebook_query_tab_label_packing (GtkNotebook  *notebook,
                                                       gboolean     *fill,
                                                       GtkPackType  *pack_type);
 
-/*** GtkObject Methods ***/
-static void gtk_notebook_destroy             (GtkObject        *object);
+/*** GObject Methods ***/
 static void gtk_notebook_set_property       (GObject         *object,
                                              guint            prop_id,
                                              const GValue    *value,
@@ -274,6 +326,7 @@ static void gtk_notebook_get_property            (GObject         *object,
                                              GParamSpec      *pspec);
 
 /*** GtkWidget Methods ***/
+static void gtk_notebook_destroy             (GtkWidget        *widget);
 static void gtk_notebook_map                 (GtkWidget        *widget);
 static void gtk_notebook_unmap               (GtkWidget        *widget);
 static void gtk_notebook_realize             (GtkWidget        *widget);
@@ -533,19 +586,51 @@ gtk_object_handled_accumulator (GSignalInvocationHint *ihint,
   return continue_emission;
 }
 
+static void
+gtk_notebook_compute_expand (GtkWidget *widget,
+                             gboolean  *hexpand_p,
+                             gboolean  *vexpand_p)
+{
+  GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+  GtkNotebookPrivate *priv = notebook->priv;
+  gboolean hexpand;
+  gboolean vexpand;
+  GList *list;
+  GtkNotebookPage *page;
+
+  hexpand = FALSE;
+  vexpand = FALSE;
+
+  for (list = priv->children; list; list = list->next)
+    {
+      page = list->data;
+
+      hexpand = hexpand ||
+        gtk_widget_compute_expand (page->child, GTK_ORIENTATION_HORIZONTAL);
+
+      vexpand = vexpand ||
+        gtk_widget_compute_expand (page->child, GTK_ORIENTATION_VERTICAL);
+
+      if (hexpand & vexpand)
+        break;
+    }
+
+  *hexpand_p = hexpand;
+  *vexpand_p = vexpand;
+}
+
 static void
 gtk_notebook_class_init (GtkNotebookClass *class)
 {
   GObjectClass   *gobject_class = G_OBJECT_CLASS (class);
-  GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
   GtkBindingSet *binding_set;
   
   gobject_class->set_property = gtk_notebook_set_property;
   gobject_class->get_property = gtk_notebook_get_property;
-  object_class->destroy = gtk_notebook_destroy;
 
+  widget_class->destroy = gtk_notebook_destroy;
   widget_class->map = gtk_notebook_map;
   widget_class->unmap = gtk_notebook_unmap;
   widget_class->realize = gtk_notebook_realize;
@@ -571,6 +656,7 @@ gtk_notebook_class_init (GtkNotebookClass *class)
   widget_class->drag_drop = gtk_notebook_drag_drop;
   widget_class->drag_data_get = gtk_notebook_drag_data_get;
   widget_class->drag_data_received = gtk_notebook_drag_data_received;
+  widget_class->compute_expand = gtk_notebook_compute_expand;
 
   container_class->add = gtk_notebook_add;
   container_class->remove = gtk_notebook_remove;
@@ -686,6 +772,13 @@ gtk_notebook_class_init (GtkNotebookClass *class)
                                                                    P_("Whether the child's tab should fill the allocated area"),
                                                                    TRUE,
                                                                    GTK_PARAM_READWRITE));
+
+  /**
+   * GtkNotebook:tab-pack:
+   *
+   *  Deprecated: 2.20: The tab packing functionality of children should not
+   *  be used anymore and support will be removed in the future.
+   */
   gtk_container_class_install_child_property (container_class,
                                              CHILD_PROP_TAB_PACK,
                                              g_param_spec_enum ("tab-pack", 
@@ -820,6 +913,14 @@ gtk_notebook_class_init (GtkNotebookClass *class)
                                                              0,
                                                              GTK_PARAM_READABLE));
 
+  /**
+   * GtkNotebook::switch-page:
+   * @notebook: the object which received the signal.
+   * @page: the new current page
+   * @page_num: the index of the page
+   *
+   * Emitted when the user or a function changes the current page.
+   */
   notebook_signals[SWITCH_PAGE] =
     g_signal_new (I_("switch-page"),
                  G_TYPE_FROM_CLASS (gobject_class),
@@ -891,11 +992,12 @@ gtk_notebook_class_init (GtkNotebookClass *class)
     g_signal_new (I_("page-reordered"),
                   G_TYPE_FROM_CLASS (gobject_class),
                   G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                 _gtk_marshal_VOID__OBJECT_UINT,
+                  G_STRUCT_OFFSET (GtkNotebookClass, page_reordered),
+                  NULL, NULL,
+                  _gtk_marshal_VOID__OBJECT_UINT,
                   G_TYPE_NONE, 2,
-                 GTK_TYPE_WIDGET,
-                 G_TYPE_UINT);
+                  GTK_TYPE_WIDGET,
+                  G_TYPE_UINT);
   /**
    * GtkNotebook::page-removed:
    * @notebook: the #GtkNotebook
@@ -911,11 +1013,12 @@ gtk_notebook_class_init (GtkNotebookClass *class)
     g_signal_new (I_("page-removed"),
                   G_TYPE_FROM_CLASS (gobject_class),
                   G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                 _gtk_marshal_VOID__OBJECT_UINT,
+                  G_STRUCT_OFFSET (GtkNotebookClass, page_removed),
+                  NULL, NULL,
+                  _gtk_marshal_VOID__OBJECT_UINT,
                   G_TYPE_NONE, 2,
-                 GTK_TYPE_WIDGET,
-                 G_TYPE_UINT);
+                  GTK_TYPE_WIDGET,
+                  G_TYPE_UINT);
   /**
    * GtkNotebook::page-added:
    * @notebook: the #GtkNotebook
@@ -931,11 +1034,12 @@ gtk_notebook_class_init (GtkNotebookClass *class)
     g_signal_new (I_("page-added"),
                   G_TYPE_FROM_CLASS (gobject_class),
                   G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                 _gtk_marshal_VOID__OBJECT_UINT,
+                  G_STRUCT_OFFSET (GtkNotebookClass, page_added),
+                  NULL, NULL,
+                  _gtk_marshal_VOID__OBJECT_UINT,
                   G_TYPE_NONE, 2,
-                 GTK_TYPE_WIDGET,
-                 G_TYPE_UINT);
+                  GTK_TYPE_WIDGET,
+                  G_TYPE_UINT);
 
   /**
    * GtkNotebook::create-window:
@@ -1453,36 +1557,11 @@ gtk_notebook_new (void)
   return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
 }
 
-/* Private GtkObject Methods :
- * 
- * gtk_notebook_destroy
- * gtk_notebook_set_arg
- * gtk_notebook_get_arg
+/* Private GObject Methods :
+ *
+ * gtk_notebook_set_property
+ * gtk_notebook_get_property
  */
-static void
-gtk_notebook_destroy (GtkObject *object)
-{
-  GtkNotebook *notebook = GTK_NOTEBOOK (object);
-  GtkNotebookPrivate *priv = notebook->priv;
-
-  if (priv->menu)
-    gtk_notebook_popup_disable (notebook);
-
-  if (priv->source_targets)
-    {
-      gtk_target_list_unref (priv->source_targets);
-      priv->source_targets = NULL;
-    }
-
-  if (priv->switch_tab_timer)
-    {
-      g_source_remove (priv->switch_tab_timer);
-      priv->switch_tab_timer = 0;
-    }
-
-  GTK_OBJECT_CLASS (gtk_notebook_parent_class)->destroy (object);
-}
-
 static void
 gtk_notebook_set_property (GObject         *object,
                           guint            prop_id,
@@ -1564,7 +1643,8 @@ gtk_notebook_get_property (GObject         *object,
 }
 
 /* Private GtkWidget Methods :
- * 
+ *
+ * gtk_notebook_destroy
  * gtk_notebook_map
  * gtk_notebook_unmap
  * gtk_notebook_realize
@@ -1588,6 +1668,30 @@ gtk_notebook_get_property (GObject         *object,
  * gtk_notebook_drag_data_get
  * gtk_notebook_drag_data_received
  */
+static void
+gtk_notebook_destroy (GtkWidget *widget)
+{
+  GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+  GtkNotebookPrivate *priv = notebook->priv;
+
+  if (priv->menu)
+    gtk_notebook_popup_disable (notebook);
+
+  if (priv->source_targets)
+    {
+      gtk_target_list_unref (priv->source_targets);
+      priv->source_targets = NULL;
+    }
+
+  if (priv->switch_tab_timer)
+    {
+      g_source_remove (priv->switch_tab_timer);
+      priv->switch_tab_timer = 0;
+    }
+
+  GTK_WIDGET_CLASS (gtk_notebook_parent_class)->destroy (widget);
+}
+
 static gboolean
 gtk_notebook_get_event_window_position (GtkNotebook  *notebook,
                                        GdkRectangle *rectangle)
@@ -1703,7 +1807,7 @@ gtk_notebook_map (GtkWidget *widget)
     {
       if (priv->action_widget[i] &&
           gtk_widget_get_visible (priv->action_widget[i]) &&
-          GTK_WIDGET_CHILD_VISIBLE (priv->action_widget[i]) &&
+          gtk_widget_get_child_visible (priv->action_widget[i]) &&
           !gtk_widget_get_mapped (priv->action_widget[i]))
         gtk_widget_map (priv->action_widget[i]);
     }
@@ -4528,10 +4632,9 @@ gtk_notebook_real_remove (GtkNotebook *notebook,
   GList * next_list;
   gint need_resize = FALSE;
   GtkWidget *tab_label;
-
   gboolean destroying;
 
-  destroying = GTK_OBJECT_FLAGS (notebook) & GTK_IN_DESTRUCTION;
+  destroying = gtk_widget_in_destruction (GTK_WIDGET (notebook));
 
   next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
   if (!next_list)
@@ -5354,9 +5457,14 @@ gtk_notebook_calculate_shown_tabs (GtkNotebook *notebook,
     }
   else /* !show_arrows */
     {
+      GtkOrientation tab_expand_orientation;
       gint c = 0;
       *n = 0;
 
+      if (priv->tab_pos == GTK_POS_TOP || priv->tab_pos == GTK_POS_BOTTOM)
+        tab_expand_orientation = GTK_ORIENTATION_HORIZONTAL;
+      else
+        tab_expand_orientation = GTK_ORIENTATION_VERTICAL;
       *remaining_space = max - min - tab_overlap - tab_space;
       children = priv->children;
       priv->first_tab = gtk_notebook_search_page (notebook, NULL,
@@ -5372,7 +5480,8 @@ gtk_notebook_calculate_shown_tabs (GtkNotebook *notebook,
 
          c++;
 
-         if (page->expand)
+         if (page->expand ||
+              (gtk_widget_compute_expand (page->tab_label, tab_expand_orientation)))
            (*n)++;
        }
 
@@ -5432,6 +5541,7 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
   guint border_width;
   gboolean gap_left, packing_changed;
   GtkAllocation child_allocation = { 0, };
+  GtkOrientation tab_expand_orientation;
 
   widget = GTK_WIDGET (notebook);
   container = GTK_CONTAINER (notebook);
@@ -5481,6 +5591,11 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
   bottom_y = top_y + priv->cur_page->allocation.height;
   gap_left = packing_changed = FALSE;
 
+  if (priv->tab_pos == GTK_POS_TOP || priv->tab_pos == GTK_POS_BOTTOM)
+    tab_expand_orientation = GTK_ORIENTATION_HORIZONTAL;
+  else
+    tab_expand_orientation = GTK_ORIENTATION_VERTICAL;
+
   while (*children && *children != last_child)
     {
       page = (*children)->data;
@@ -5507,7 +5622,7 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
        continue;
 
       tab_extra_space = 0;
-      if (*expanded_tabs && (showarrow || page->expand || priv->homogeneous))
+      if (*expanded_tabs && (showarrow || page->expand || gtk_widget_compute_expand (page->tab_label, tab_expand_orientation) || priv->homogeneous))
        {
          tab_extra_space = *remaining_space / *expanded_tabs;
          *remaining_space -= tab_extra_space;
@@ -7548,7 +7663,8 @@ gtk_notebook_reorder_child (GtkNotebook *notebook,
 /**
  * gtk_notebook_set_group_name:
  * @notebook: a #GtkNotebook
- * @name: (allow-none): the name of the notebook group, or %NULL to unset it
+ * @group_name: (allow-none): the name of the notebook group,
+ *     or %NULL to unset it
  *
  * Sets a group name for @notebook.
  *