[anjuta] libanjuta: Port AnjutaTabber to GtkStyleContext



commit 888b6a9df6b37cfadcf6b94bbe85c24746d9f35a
Author: Johannes Schmid <jhs gnome org>
Date:   Sun Mar 13 22:36:52 2011 +0100

    libanjuta: Port AnjutaTabber to GtkStyleContext

 libanjuta/anjuta-tabber.c |  236 ++++++++++++++++++++++++++++++---------------
 1 files changed, 159 insertions(+), 77 deletions(-)
---
diff --git a/libanjuta/anjuta-tabber.c b/libanjuta/anjuta-tabber.c
index 531e4a8..790f97b 100644
--- a/libanjuta/anjuta-tabber.c
+++ b/libanjuta/anjuta-tabber.c
@@ -156,29 +156,48 @@ anjuta_tabber_get_preferred_width (GtkWidget* widget,
 	GList* child;
 	gint xthickness;
 	gint focus_width;
+	gint tab_curvature;
+	gint tab_overlap;
+	gint padding;
+	gint tab;
+	
 	GtkStyle* style = gtk_widget_get_style (widget);
 
 	xthickness = style->xthickness;
 	
 	gtk_widget_style_get (GTK_WIDGET (tabber->priv->notebook),
 	                      "focus-line-width", &focus_width,
+	                      "tab-curvature", &tab_curvature,
+	                      "tab-overlap", &tab_overlap,
 	                      NULL);
+
+	padding = xthickness + focus_width + tabber->priv->tab_hborder;
+	tab = tab_curvature - tab_overlap;
 	
 	for (child = tabber->priv->children; child != NULL; child = g_list_next (child))
 	{
 		gint child_min;
-		gint child_preferred;		
-		GtkStyle *style;
-
+		gint child_preferred;
+		
 		gtk_widget_get_preferred_width (GTK_WIDGET (child->data), &child_min, &child_preferred);
-		style = gtk_widget_get_style (widget);
 		if (minimum)
 		{
-			*minimum += child_min + 2 * (xthickness + focus_width + tabber->priv->tab_hborder);
+			*minimum += child_min + 2 * padding + 2 * tab;
 		}
 		if (preferred)
 		{
-			*preferred += child_preferred + 2 * (xthickness + focus_width + tabber->priv->tab_hborder);
+			*preferred += child_preferred + 2 * padding + 2 *tab;
+		}
+	}
+	if (tabber->priv->children)
+	{
+		if (minimum)
+		{
+			*minimum += 2 * tab_overlap;
+		}
+				if (preferred)
+		{
+			*preferred += 2 * tab_overlap;
 		}
 	}
 }
@@ -207,10 +226,8 @@ anjuta_tabber_get_preferred_height (GtkWidget* widget,
 	{
 		gint child_min;
 		gint child_preferred;		
-		GtkStyle *style;
 
 		gtk_widget_get_preferred_height (GTK_WIDGET (child->data), &child_min, &child_preferred);
-		style = gtk_widget_get_style (widget);
 		if (minimum)
 		{
 			*minimum = MAX(*minimum, child_min + 
@@ -234,10 +251,13 @@ anjuta_tabber_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
 	GList* child;
 	gint focus_width;
 	gint tab_curvature;
+	gint tab_overlap;
 	gint n_children = g_list_length (tabber->priv->children);
 	gint xthickness;
 	gint ythickness;
 	gint x;
+	gint padding;
+	gint tab;
 	GtkStyle* style = gtk_widget_get_style (widget);
 
 	xthickness = style->xthickness;
@@ -246,18 +266,22 @@ anjuta_tabber_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
 	gtk_widget_style_get (GTK_WIDGET (tabber->priv->notebook),
 	                      "focus-line-width", &focus_width,
 	                      "tab-curvature", &tab_curvature,
+	                      "tab-overlap", &tab_overlap,
 	                      NULL);
+
+	padding = xthickness + focus_width + tabber->priv->tab_hborder;
+	tab = tab_curvature - tab_overlap;
 	
 	gtk_widget_set_allocation (widget, allocation);
 
 	switch (gtk_widget_get_direction (widget))
 	{
 		case GTK_TEXT_DIR_RTL:
-			x = allocation->x + allocation->width - tabber->priv->tab_hborder;
+			x = allocation->x + allocation->width;
 			break;
 		case GTK_TEXT_DIR_LTR:
 		default:
-			x = allocation->x; // + tabber->priv->tab_hborder;
+			x = allocation->x;
 	}
 
 	if (gtk_widget_get_realized (widget))
@@ -275,10 +299,11 @@ anjuta_tabber_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
 		gboolean use_natural = FALSE;
 		gint child_equal;
 		gint extra_space = 0;
+		gint real_width = allocation->width - 2 * tab_overlap;
 
 		/* Check if we have enough space for all widgets natural size */
-		child_equal = allocation->width / n_children - 
-			2 * (xthickness + focus_width + tabber->priv->tab_hborder);
+		child_equal = real_width / n_children - 
+			 n_children * 2 * (padding + tab);
 		for (child = tabber->priv->children; child != NULL; child = g_list_next (child))
 		{
 			GtkWidget* child_widget = GTK_WIDGET (child->data);
@@ -290,10 +315,8 @@ anjuta_tabber_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
 			if (natural < child_equal)
 				extra_space += child_equal - natural;
 		}
-		use_natural = (total_width +  
-		               2 * (xthickness + focus_width + tabber->priv->tab_hborder) <= allocation->width);
+		use_natural = (total_width + n_children * 2 * (padding + tab)) <= real_width;
 		child_equal += extra_space / n_children;
-		
 		for (child = tabber->priv->children; child != NULL; child = g_list_next (child))
 		{
 			GtkWidget* child_widget = GTK_WIDGET (child->data);
@@ -301,8 +324,15 @@ anjuta_tabber_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
 			GtkAllocation child_alloc;
 			gtk_widget_get_child_requisition (child_widget, &child_req);
 			gint natural;
-			gint minimal;			
-
+			gint minimal;
+			gint begin_tab = tab;
+			gint end_tab = tab;
+
+			if (child == tabber->priv->children)
+				begin_tab += tab_overlap;
+			if (child == g_list_last (tabber->priv->children))
+				end_tab += tab_overlap;
+			
 			gtk_widget_get_preferred_width (child_widget, &minimal,
 				                            &natural);
 
@@ -318,22 +348,18 @@ anjuta_tabber_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
 					child_alloc.width = child_equal;
 			}
 			child_alloc.height = child_req.height - tabber->priv->tab_vborder;
-
+			child_alloc.x = x + padding + begin_tab;
 			switch (gtk_widget_get_direction (widget))
 			{
 				case GTK_TEXT_DIR_RTL:
-					child_alloc.x = x - xthickness - focus_width;
-					child_alloc.width += xthickness + focus_width + tabber->priv->tab_hborder; 
-					x = child_alloc.x - child_alloc.width;
+					x = child_alloc.x - child_alloc.width - 2 * padding - end_tab;
 					break;
 				case GTK_TEXT_DIR_LTR:
 				default:
-					child_alloc.x = x + xthickness + focus_width;
-					child_alloc.width += xthickness + focus_width + tabber->priv->tab_hborder; 
-					x = child_alloc.x + child_alloc.width;
+					x = child_alloc.x + child_alloc.width + 2 * padding + end_tab;
 			}
-			child_alloc.y = allocation->y + allocation->height
-				- child_alloc.height - tabber->priv->tab_vborder - focus_width - ythickness;
+			child_alloc.y = allocation->y +
+				tabber->priv->tab_vborder + focus_width + ythickness;
 
 			gtk_widget_size_allocate (GTK_WIDGET (child->data), &child_alloc);
 		}
@@ -341,92 +367,145 @@ anjuta_tabber_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
 }
 
 static void
-anjuta_tabber_draw_tab (GtkWidget* widget,
-                        GtkWidget* tab,
-                        cairo_t* cr,
-                        GtkStateType state,
-                        gboolean first)
+anjuta_tabber_render_tab (GtkWidget* widget,
+                          GtkWidget* tab,
+                          cairo_t* cr,
+                          gboolean current,
+                          GtkRegionFlags region_flags)
 {
 	AnjutaTabber* tabber = ANJUTA_TABBER (widget);
 	GtkAllocation alloc;
 	GtkAllocation widget_alloc;
+
 	gint focus_width;
-	gint tab_curvature;
 	gint xthickness;
 	gint ythickness;
-	GtkStyle* style = gtk_widget_get_style (widget);
-
+	gint tab_curvature;
+	gint tab_overlap;
+	gint tab_begin;
+	gint tab_end;
+
+	gint xpadding;
+	gint ypadding;
+	GtkStyle* style = gtk_widget_get_style (GTK_WIDGET (tabber->priv->notebook));
+	GtkStyleContext* context = gtk_widget_get_style_context (GTK_WIDGET (tabber->priv->notebook));
+	GtkStateFlags state = current ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL;
+	
 	xthickness = style->xthickness;
 	ythickness = style->ythickness;
 	
 	gtk_widget_style_get (GTK_WIDGET (tabber->priv->notebook),
 	                      "focus-line-width", &focus_width,
 	                      "tab-curvature", &tab_curvature,
+	                      "tab-overlap", &tab_overlap,
 	                      NULL);
 
+	 /* Get border/padding for tab */
+	gtk_style_context_save (context);
+	gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB,
+	                              region_flags);
+	gtk_style_context_set_state (context, state);
 	
 	gtk_widget_get_allocation (widget, &widget_alloc);
 	gtk_widget_get_allocation (tab, &alloc);
 
-	style = gtk_widget_get_style (widget);
+	xpadding = xthickness + focus_width + tabber->priv->tab_hborder;
+	ypadding = ythickness + focus_width + tabber->priv->tab_vborder;
 
-	alloc.x -= widget_alloc.x 
-		+ xthickness + focus_width;// + tabber->priv->tab_hborder;
-	alloc.y -= widget_alloc.y + focus_width + ythickness;
-	alloc.width += xthickness + focus_width; //+ tabber->priv->tab_hborder;;
-	alloc.height = widget_alloc.height;
+	tab_begin = tab_curvature - tab_overlap;
+	tab_end = tab_curvature - tab_overlap;
 
-	if (state == GTK_STATE_NORMAL)
+	if (region_flags | GTK_REGION_FIRST)
+		tab_begin += tab_overlap;
+	if (region_flags | GTK_REGION_LAST)
+		tab_end += tab_overlap;
+	
+	alloc.x -= widget_alloc.x;
+	alloc.x -= tab_begin;
+	alloc.x -= xpadding;
+	alloc.y -= widget_alloc.y;
+	alloc.y -= ypadding;
+	alloc.width += 2 * (xpadding) + tab_begin + tab_end;
+	alloc.height += 2 * ypadding;
+	
+	gtk_render_extension (context,
+	                      cr,
+	                      alloc.x, 
+	                      alloc.y,
+	                      alloc.width, 
+	                      alloc.height,
+	                      GTK_POS_BOTTOM);
+
+	if (gtk_widget_has_focus (widget) &&
+	    current)
 	{
-		alloc.y -= tabber->priv->tab_vborder;
-		alloc.height += tabber->priv->tab_vborder;
-		if (!first)
-		{
-			switch (gtk_widget_get_direction (widget))
-			{
-				case GTK_TEXT_DIR_RTL:
-					alloc.x += tabber->priv->tab_hborder;
-				case GTK_TEXT_DIR_LTR:
-				default:
-					alloc.x -= tabber->priv->tab_hborder;
-			}
-			alloc.width += tabber->priv->tab_hborder;
-		}
-		alloc.width += tabber->priv->tab_hborder;
+		GtkAllocation allocation;
+		
+		gtk_widget_get_allocation (tab, &allocation);
+
+		gtk_render_focus (context, cr,
+		                  allocation.x - focus_width,
+		                  allocation.y - focus_width,
+		                  allocation.width + 2 * focus_width,
+		                  allocation.height + 2 * focus_width);
 	}
 	
-	gtk_paint_extension (style,
-	                     cr,
-	                     state, GTK_SHADOW_OUT,
-	                     widget, "tab",
-	                     alloc.x, 
-	                     alloc.y,
-	                     alloc.width, 
-	                     alloc.height,
-	                     GTK_POS_BOTTOM);
+	gtk_style_context_restore (context);
+}
+
+static GtkRegionFlags
+anjuta_tabber_get_region_flags (gint page_num, gboolean is_last)
+{
+	GtkRegionFlags flags = 0;
+	if ((page_num) % 2 == 0)
+		flags |= GTK_REGION_EVEN;
+	else
+		flags |= GTK_REGION_ODD;
+
+	if (page_num == 1)
+		flags |= GTK_REGION_FIRST;
+
+	if (is_last)
+		flags |= GTK_REGION_LAST;
+	
+	return flags;
+}
+
+static void
+anjuta_tabber_draw_tab (AnjutaTabber* tabber,
+                        cairo_t* cr,
+                        GList* child,
+                        gboolean current)
+{
+	GtkWidget* tab = GTK_WIDGET (child->data);
+	gint nth = g_list_index (tabber->priv->children,
+	                         child->data) + 1;
+	gboolean last = (child->next == NULL);
+	anjuta_tabber_render_tab (GTK_WIDGET (tabber), tab, cr, current,
+	                          anjuta_tabber_get_region_flags (nth, last));
 }
 
 static gboolean
 anjuta_tabber_draw (GtkWidget* widget, cairo_t* cr)
 {
-	g_return_val_if_fail (ANJUTA_IS_TABBER (widget), FALSE);
-
-	AnjutaTabber* tabber = ANJUTA_TABBER (widget);
+	AnjutaTabber* tabber;
+	GList* current_tab;
 	GList* child;
-	GtkWidget* current_tab = g_list_nth_data (tabber->priv->children, tabber->priv->active_page);
-	GtkWidget* first = NULL;
 
-	if (tabber->priv->children) 
-		first = tabber->priv->children->data;
+	g_return_val_if_fail (ANJUTA_IS_TABBER (widget), FALSE);
+
+	tabber = ANJUTA_TABBER (widget);
+	
+	if (!tabber->priv->children)
+		return TRUE;
 
+	current_tab = g_list_nth (tabber->priv->children, tabber->priv->active_page);
+	
 	for (child = tabber->priv->children; child != NULL; child = g_list_next (child))
 	{
-		GtkWidget* tab = GTK_WIDGET (child->data);
-		if (tab != current_tab)
-			anjuta_tabber_draw_tab (widget, tab, cr, GTK_STATE_ACTIVE, current_tab == first);
+		anjuta_tabber_draw_tab (tabber, cr, child, FALSE);
 	}
-	anjuta_tabber_draw_tab (widget, current_tab, cr, GTK_STATE_NORMAL, current_tab == first);
-	
+	anjuta_tabber_draw_tab (tabber, cr, current_tab, TRUE);
 	return GTK_WIDGET_CLASS (anjuta_tabber_parent_class)->draw (widget, cr);
 }
 
@@ -581,7 +660,10 @@ anjuta_tabber_add (GtkContainer* container, GtkWidget* widget)
 	tabber->priv->children = g_list_append (tabber->priv->children, widget);
 	gtk_widget_set_parent (widget, GTK_WIDGET (tabber));
 	if (visible)
+	{
+		gtk_container_resize_children (GTK_CONTAINER (tabber));
 		gtk_widget_queue_resize (widget);
+	}
 }
 
 static void



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]