static void
anjuta_tabber_get_preferred_width (GtkWidget* widget, 
                                    gint* minimum,
                                    gint* preferred)
{
	g_return_if_fail (ANJUTA_IS_TABBER (widget));

	AnjutaTabber* tabber = ANJUTA_TABBER (widget);
	GtkStyleContext* context;
	GList* child;
	gint focus_width;
	gint focus_pad;
	gint tab_curvature;
	gint tab_overlap;

	*minimum = 0;
	*preferred = 0;
	
	gtk_widget_style_get (GTK_WIDGET (tabber->priv->notebook),
	                      "focus-line-width", &focus_width,
	                      "focus-padding", &focus_pad,
	                      "tab-curvature", &tab_curvature,
	                      "tab-overlap", &tab_overlap,
	                      NULL);

	context = gtk_widget_get_style_context (widget);

	for (child = tabber->priv->children; child != NULL; child = g_list_next (child))
	{
		GtkStateFlags state;
		GtkBorder tab_padding;
		gint xpadding;
		gint child_min;
		gint child_preferred;
		gint extra_space = 2 * (tab_curvature - tab_overlap);

		/* Get the padding of the tab */
		gtk_style_context_save (context);
		anjuta_tabber_setup_style_context (tabber, context, child, &state, NULL);
		gtk_style_context_get_padding (context, state, &tab_padding);
		gtk_style_context_restore (context);

		xpadding =  2 * (focus_width + focus_pad) + tab_padding.left + tab_padding.right;
		
		if (child->prev == NULL)
			extra_space += tab_overlap;
		if (child->next == NULL)
			extra_space += tab_overlap;
		
		gtk_widget_get_preferred_width (GTK_WIDGET (child->data), &child_min, &child_preferred);
		if (minimum)
		{
			*minimum += child_min + xpadding + extra_space;
		}
		if (preferred)
		{
			*preferred += child_preferred + xpadding + extra_space;
		}
	}
}
static gboolean
anjuta_tabber_draw (GtkWidget* widget, cairo_t* cr)
{
	AnjutaTabber* tabber;
	GList* current_tab;
	GList* child;

	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);

	/* Draw the current tab last since it overlaps the others */
	for (child = tabber->priv->children; child != current_tab; child = g_list_next (child))
	{
		anjuta_tabber_draw_tab (tabber, cr, child);
	}
	for (child = g_list_last (tabber->priv->children); child != current_tab; child = g_list_previous (child))
	{
		anjuta_tabber_draw_tab (tabber, cr, child);
	}
	anjuta_tabber_draw_tab (tabber, cr, current_tab);

	return GTK_WIDGET_CLASS (anjuta_tabber_parent_class)->draw (widget, cr);
}
Exemple #3
0
static void
anjuta_tabber_get_preferred_height (GtkWidget* widget, 
                                    gint* minimum,
                                    gint* preferred)
{
	g_return_if_fail (ANJUTA_IS_TABBER (widget));

	AnjutaTabber* tabber = ANJUTA_TABBER (widget);
	GList* child;
	gint focus_width;
	
	gtk_widget_style_get (GTK_WIDGET (tabber),
	                      "focus-line-width", &focus_width,
	                      NULL);

	
	for (child = tabber->priv->children; child != NULL; child = g_list_next (child))
	{
		gint child_min;
		gint child_preferred;		

		gtk_widget_get_preferred_height (GTK_WIDGET (child->data), &child_min, &child_preferred);
		if (minimum)
		{
			*minimum = MAX(*minimum, child_min + 
			               2 * (focus_width + tabber->priv->tab_vborder));
		}
		if (preferred)
		{
			*preferred = MAX(*preferred, child_preferred + 
			                 2 * (focus_width + tabber->priv->tab_vborder));
		}
	}
}
Exemple #4
0
static void
anjuta_tabber_get_preferred_width (GtkWidget* widget, 
                                    gint* minimum,
                                    gint* preferred)
{
	g_return_if_fail (ANJUTA_IS_TABBER (widget));

	AnjutaTabber* tabber = ANJUTA_TABBER (widget);
	GList* child;
	gint xthickness;
	gint focus_width;
	gint tab_curvature;
	gint tab_overlap;
	gint padding;
	
	GtkStyle* style = gtk_widget_get_style (widget);

	xthickness = style->xthickness;

	*minimum = 0;
	*preferred = 0;
	
	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;
	
	for (child = tabber->priv->children; child != NULL; child = g_list_next (child))
	{
		gint child_min;
		gint child_preferred;
		gint extra_space = 2 * (tab_curvature - tab_overlap);
		
		if (child == g_list_first (tabber->priv->children))
			extra_space += tab_overlap;
		if (child == g_list_last (tabber->priv->children))
			extra_space += tab_overlap;
		
		gtk_widget_get_preferred_width (GTK_WIDGET (child->data), &child_min, &child_preferred);
		if (minimum)
		{
			*minimum += child_min + 2 * padding + extra_space;
		}
		if (preferred)
		{
			*preferred += child_preferred + 2 * padding + extra_space;
		}
	}
}
static void
anjuta_tabber_forall (GtkContainer* container, 
                      gboolean include_internals,
                      GtkCallback callback,
                      gpointer callback_data)
{
	g_return_if_fail (ANJUTA_IS_TABBER (container));
	AnjutaTabber* tabber = ANJUTA_TABBER (container);
	GList* child;
	for (child = tabber->priv->children; child != NULL; child = g_list_next (child))
	{
		(* callback) (GTK_WIDGET(child->data), callback_data);
    }
}
static void
anjuta_tabber_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
	g_return_if_fail (ANJUTA_IS_TABBER (object));

	switch (prop_id)
	{
	case PROP_NOTEBOOK:
		g_value_set_object (value, object);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
static void
anjuta_tabber_get_preferred_height (GtkWidget* widget, 
                                    gint* minimum,
                                    gint* preferred)
{
	g_return_if_fail (ANJUTA_IS_TABBER (widget));

	AnjutaTabber* tabber = ANJUTA_TABBER (widget);
	GtkStyleContext* context;
	GList* child;
	gint focus_width;
	gint focus_pad;
	
	gtk_widget_style_get (GTK_WIDGET (tabber),
	                      "focus-line-width", &focus_width,
	                      "focus-padding", &focus_pad,
	                      NULL);

	context = gtk_widget_get_style_context (widget);

	for (child = tabber->priv->children; child != NULL; child = g_list_next (child))
	{
		GtkStateFlags state;
		GtkBorder tab_padding;
		gint ypadding;
		gint child_min;
		gint child_preferred;

		/* Get the padding of the tab */
		gtk_style_context_save (context);
		anjuta_tabber_setup_style_context (tabber, context, child, &state, NULL);
		gtk_style_context_get_padding (context, state, &tab_padding);
		gtk_style_context_restore (context);

		ypadding =  2 * (focus_width + focus_pad) + tab_padding.top + tab_padding.bottom;

		gtk_widget_get_preferred_height (GTK_WIDGET (child->data), &child_min, &child_preferred);
		if (minimum)
		{
			*minimum = MAX(*minimum, child_min + ypadding);
		}
		if (preferred)
		{
			*preferred = MAX(*preferred, child_preferred + ypadding);
		}
	}
}
static void
anjuta_tabber_add (GtkContainer* container, GtkWidget* widget)
{
	g_return_if_fail (ANJUTA_IS_TABBER (container));
	g_return_if_fail (GTK_IS_WIDGET (widget));
	
	AnjutaTabber* tabber = ANJUTA_TABBER (container);
	gboolean visible = gtk_widget_get_visible (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
anjuta_tabber_remove (GtkContainer* container, GtkWidget* widget)
{
	g_return_if_fail (ANJUTA_IS_TABBER (container));
	g_return_if_fail (GTK_IS_WIDGET (widget));

	AnjutaTabber* tabber = ANJUTA_TABBER (container);
	gboolean visible = gtk_widget_get_visible (widget);
	
	gtk_widget_unparent (widget);
	tabber->priv->children = g_list_remove (tabber->priv->children, widget);

	if (tabber->priv->active_page > 0)
		tabber->priv->active_page--;
	
	if (visible)
		gtk_widget_queue_resize (GTK_WIDGET (tabber));
}
static void
anjuta_tabber_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{	
	g_return_if_fail (ANJUTA_IS_TABBER (object));

	AnjutaTabber* tabber = ANJUTA_TABBER (object);

	switch (prop_id)
	{
	case PROP_NOTEBOOK:
		tabber->priv->notebook = g_value_get_object (value);
		anjuta_tabber_connect_notebook (tabber);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
static void
anjuta_tabber_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
{
	g_return_if_fail (ANJUTA_IS_TABBER (widget));
	AnjutaTabber* tabber = ANJUTA_TABBER (widget);

	GtkStyleContext* context;
	GList* child;
	gint focus_width;
	gint focus_pad;
	gint tab_curvature;
	gint tab_overlap;
	gint n_children = g_list_length (tabber->priv->children);
	gint x;
	gint focus_space;
	gint tab_space;

	context = gtk_widget_get_style_context (widget);

	gtk_widget_style_get (GTK_WIDGET (tabber),
	                      "focus-line-width", &focus_width,
	                      "focus-padding", &focus_pad,
	                      "tab-curvature", &tab_curvature,
	                      "tab-overlap", &tab_overlap,
	                      NULL);

	focus_space = focus_width + focus_pad;
	tab_space = 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;
			break;
		case GTK_TEXT_DIR_LTR:
		default:
			x = allocation->x;
	}

	if (gtk_widget_get_realized (widget))
	{
		gdk_window_move_resize (tabber->priv->event_window,
		                        allocation->x, allocation->y,
		                        allocation->width, allocation->height);
		if (gtk_widget_get_mapped (widget))
			gdk_window_show_unraised (tabber->priv->event_window);
	}

	if (n_children > 0)
	{
		gint total_space;
		gint total_width;
		gboolean use_natural = FALSE;
		gint child_equal;
		gint extra_space = 0;
		gint real_width = allocation->width;

		/* Calculate the total space that is used for padding/overlap */
		total_space = 2 * tab_curvature
			+ 2 * tab_space * (n_children - 1)
			+  2 * focus_space * n_children;

		for (child = tabber->priv->children; child != NULL; child = g_list_next (child))
		{
			GtkStateFlags state;
			GtkBorder tab_padding;

			/* Get the padding of the tab */
			gtk_style_context_save (context);
			anjuta_tabber_setup_style_context (tabber, context, child, &state, NULL);
			gtk_style_context_get_padding (context, state, &tab_padding);
			gtk_style_context_restore (context);

			total_space += tab_padding.left + tab_padding.right;
		}

		/* Check if we have enough space for all widgets natural size */
		child_equal = (real_width - total_space) / n_children;

		if (child_equal < 0)
			return;

		/* Calculate the total width of the tabs */
		total_width = total_space;
		for (child = tabber->priv->children; child != NULL; child = g_list_next (child))
		{
			GtkWidget* child_widget = GTK_WIDGET (child->data);
			gint natural;

			gtk_widget_get_preferred_width (child_widget, NULL,
			                                &natural);

			total_width += natural;

			if (natural < child_equal)
				extra_space += child_equal - natural;
		}

		use_natural = (total_width <= 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);
			GtkStateFlags state;
			GtkBorder tab_padding, active_padding;
			GtkAllocation child_alloc;
			gint natural;
			gint minimal;
			gint begin_tab = tab_space;
			gint end_tab = tab_space;

			/* Get the padding of the tab */
			gtk_style_context_save (context);
			anjuta_tabber_setup_style_context (tabber, context, child, &state, NULL);
			gtk_style_context_get_padding (context, state, &tab_padding);
			gtk_style_context_get_padding (context, state | GTK_STATE_ACTIVE, &active_padding);
			gtk_style_context_restore (context);

			if (child->prev == NULL)
				begin_tab = tab_curvature;
			if (child->next == NULL)
				end_tab = tab_curvature;
			
			gtk_widget_get_preferred_width (child_widget, &minimal,
				                            &natural);

			if (use_natural)
			{
				child_alloc.width = natural;
			}
	 		else
			{
				if (natural < child_equal)
					child_alloc.width = natural;
				else
					child_alloc.width = child_equal;
			}
			/* The active pad is by definition at least the same height
			 * as the inactive one. Therefore we always use the padding of the
			 * active tab to calculate the height and y position of the child.
			 */
			child_alloc.height = allocation->height - 2 * focus_space
				- active_padding.top - active_padding.bottom;
			child_alloc.y = allocation->y + focus_space + active_padding.top;

			switch (gtk_widget_get_direction (widget))
			{
				case GTK_TEXT_DIR_RTL:
					child_alloc.x = x - focus_space - tab_padding.right
						- begin_tab - child_alloc.width;
					x = child_alloc.x - focus_space - tab_padding.left - end_tab;
					break;
				case GTK_TEXT_DIR_LTR:
				default:
					child_alloc.x = x + focus_space + tab_padding.left + begin_tab;
					x = child_alloc.x + child_alloc.width + focus_space
						+ tab_padding.right + end_tab;
			}

			gtk_widget_size_allocate (child_widget, &child_alloc);
		}
	}
}
Exemple #12
0
static void
anjuta_tabber_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
{
	g_return_if_fail (ANJUTA_IS_TABBER (widget));
	AnjutaTabber* tabber = ANJUTA_TABBER (widget);

	GList* child;
	gint focus_width;
	gint tab_curvature;
	gint tab_overlap;
	gint n_children = g_list_length (tabber->priv->children);
	gint x;
	gint padding;
	gint tab_space;
	
	gtk_widget_style_get (GTK_WIDGET (tabber),
	                      "focus-line-width", &focus_width,
	                      "tab-curvature", &tab_curvature,
	                      "tab-overlap", &tab_overlap,
	                      NULL);

	padding = focus_width + tabber->priv->tab_hborder;
	tab_space = 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;
			break;
		case GTK_TEXT_DIR_LTR:
		default:
			x = allocation->x;
	}

	if (gtk_widget_get_realized (widget))
	{
		gdk_window_move_resize (tabber->priv->event_window,
		                        allocation->x, allocation->y,
		                        allocation->width, allocation->height);
		if (gtk_widget_get_mapped (widget))
			gdk_window_show_unraised (tabber->priv->event_window);
	}

	if (n_children > 0)
	{
		gint total_width = 2 * tab_overlap;
		gboolean use_natural = FALSE;
		gint child_equal;
		gint extra_space = 0;
		gint real_width = allocation->width;

		/* Check if we have enough space for all widgets natural size */
		child_equal = real_width / n_children - 
			 n_children * 2 * (padding + tab_space) - 2 * tab_overlap;

		if (child_equal < 0)
			return;
		
		for (child = tabber->priv->children; child != NULL; child = g_list_next (child))
		{
			GtkWidget* child_widget = GTK_WIDGET (child->data);
			gint natural;
			gtk_widget_get_preferred_width (child_widget, NULL,
			                                &natural);

			total_width += natural + 2 * (padding + tab_space);
			if (natural < child_equal)
				extra_space += child_equal - natural;
		}
		use_natural = (total_width <= 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);
			GtkAllocation child_alloc;
			gint natural;
			gint minimal;
			gint begin_tab = tab_space;
			gint end_tab = tab_space;

			if (child == g_list_first (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);

			if (use_natural)
			{
				child_alloc.width = natural;
			}
			else
			{
				if (natural < child_equal)
					child_alloc.width = natural;
				else
					child_alloc.width = child_equal;
			}
			child_alloc.height = allocation->height
				- 2 * (focus_width + tabber->priv->tab_vborder);
			switch (gtk_widget_get_direction (widget))
			{
				case GTK_TEXT_DIR_RTL:
					child_alloc.x = x - padding - begin_tab - child_alloc.width;
					x = child_alloc.x - padding - end_tab;
					break;
				case GTK_TEXT_DIR_LTR:
				default:
					child_alloc.x = x + padding + begin_tab;
					x = child_alloc.x + child_alloc.width + padding + end_tab;
			}
			child_alloc.y = allocation->y +
				tabber->priv->tab_vborder + focus_width;

			gtk_widget_size_allocate (GTK_WIDGET (child->data), &child_alloc);
		}
	}
}