Compare commits

...

11 Commits

Author SHA1 Message Date
Timm Bäder
745182860a GtkStack: Interpolate between size changes 2015-05-25 15:51:30 +02:00
Timm Bäder
fac1b3e5f9 GtkStack: Remove some useless function calls
We will call gtk_widget_queue_resize anyway later when finishing the
(maybe non-running) transition, which will also cause the stack to be
repainted.
2015-05-25 15:44:38 +02:00
Timm Bäder
df9b49e1ac GtkStack: Keep the last_visible_child around during transitions
We need it later.
2015-05-25 15:44:37 +02:00
Timm Bäder
dd6cb3a2cf GtkStack: Misc indentation fixes 2015-05-25 13:00:34 +02:00
Timm Bäder
911d482c4e GtkStack: Remove useless cast 2015-05-25 13:00:34 +02:00
Timm Bäder
e4156c6313 GtkStack: Remove useless function calls
These both just use the default values anyway.
2015-05-25 13:00:34 +02:00
Timm Bäder
99f8bcf1ef GtkStack: Save last visible widget size
When interpolating the stack size, we compute the current size by using
the prefered/minimum current size and the last size. We can't use the
last_visible_surface_allocation because that is not available until the
first _draw call and it doesn't include the child's margins.
2015-05-25 13:00:34 +02:00
Timm Bäder
8ffe9f441a GtkStack: Remove gtk_widget_set_opacity call
The corresponding call with 0.999 opacity is gone, so we don't need to
reset the opacity anymore.
2015-05-25 13:00:34 +02:00
Timm Bäder
375efee6bf Revert "popover: Expand buttons over entire width"
This reverts commit e23fa3e61da773dc407f48ec02787b3318975aff.
2015-05-25 13:00:34 +02:00
Timm Bäder
1ea75bf8fb popover: Expand buttons over entire width 2015-05-25 13:00:34 +02:00
Timm Bäder
deb476266c gtkpopover: Update the menu's alignment
... when the popover position changes.
2015-05-25 13:00:34 +02:00
5 changed files with 130 additions and 57 deletions

View File

@@ -277,7 +277,7 @@ gtk_menu_section_box_insert_func (GtkMenuTrackerItem *item,
gchar *name;
widget = g_object_new (GTK_TYPE_MODEL_BUTTON,
"menu-name", gtk_menu_tracker_item_get_label (item),
"menu-name", gtk_menu_tracker_item_get_label (item),
NULL);
g_object_bind_property (item, "label", widget, "text", G_BINDING_SYNC_CREATE);
g_object_bind_property (item, "icon", widget, "icon", G_BINDING_SYNC_CREATE);
@@ -369,10 +369,39 @@ gtk_menu_section_box_class_init (GtkMenuSectionBoxClass *class)
G_OBJECT_CLASS (class)->dispose = gtk_menu_section_box_dispose;
}
static void
update_popover_position_cb (GObject *source,
GParamSpec *spec,
gpointer *user_data)
{
GtkPopover *popover = GTK_POPOVER (source);
GtkMenuSectionBox *box = GTK_MENU_SECTION_BOX (user_data);
GtkPositionType new_pos = gtk_popover_get_position (popover);
GList *children = gtk_container_get_children (GTK_CONTAINER (gtk_widget_get_parent (GTK_WIDGET (box))));
GList *l;
for (l = children;
l != NULL;
l = l->next)
{
GtkWidget *w = l->data;
if (new_pos == GTK_POS_BOTTOM)
gtk_widget_set_valign (w, GTK_ALIGN_START);
else if (new_pos == GTK_POS_TOP)
gtk_widget_set_valign (w, GTK_ALIGN_END);
else
gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
}
}
void
gtk_menu_section_box_new_toplevel (GtkStack *stack,
GMenuModel *model,
const gchar *action_namespace)
const gchar *action_namespace,
GtkPopover *popover)
{
GtkMenuSectionBox *box;
@@ -384,6 +413,9 @@ gtk_menu_section_box_new_toplevel (GtkStack *stack,
gtk_menu_section_box_insert_func,
gtk_menu_section_box_remove_func, box);
g_signal_connect (G_OBJECT (popover), "notify::position", G_CALLBACK (update_popover_position_cb), box);
gtk_widget_show (GTK_WIDGET (box));
}
@@ -485,7 +517,6 @@ gtk_menu_section_box_new_section (GtkMenuTrackerItem *item,
NULL);
gtk_widget_show (box->separator);
}
box->tracker = gtk_menu_tracker_new_for_item_link (item, G_MENU_LINK_SECTION, FALSE, FALSE,
gtk_menu_section_box_insert_func,
gtk_menu_section_box_remove_func,

View File

@@ -23,6 +23,7 @@
#include <gtk/gtkmenutrackeritem.h>
#include <gtk/gtkstack.h>
#include <gtk/gtkbox.h>
#include <gtk/gtkpopover.h>
G_BEGIN_DECLS
@@ -43,7 +44,8 @@ typedef struct _GtkMenuSectionBox GtkMenuSectionBox;
GType gtk_menu_section_box_get_type (void) G_GNUC_CONST;
void gtk_menu_section_box_new_toplevel (GtkStack *stack,
GMenuModel *model,
const gchar *action_namespace);
const gchar *action_namespace,
GtkPopover *popover);
G_END_DECLS

View File

@@ -415,7 +415,7 @@ gtk_model_button_get_full_border (GtkModelButton *button,
border_width = gtk_container_get_border_width (GTK_CONTAINER (button));
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &indicator_size, NULL);
indicator_spacing = indicator_size / 8;
indicator_spacing = indicator_size / 2;
border->left = border_width;
border->right = border_width;
@@ -425,7 +425,7 @@ gtk_model_button_get_full_border (GtkModelButton *button,
if (button->iconic)
*indicator = 0;
else
*indicator = indicator_size + 2 * indicator_spacing;
*indicator = indicator_size + indicator_spacing;
}
static gboolean
@@ -634,7 +634,7 @@ indicator_is_left (GtkWidget *widget)
return ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL && !button->inverted) ||
(gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR && button->inverted));
}
static void
@@ -660,7 +660,7 @@ gtk_model_button_size_allocate (GtkWidget *widget,
{
GtkBorder border;
gint indicator;
gtk_model_button_get_full_border (button, &border, &indicator);
if (button->centered)
@@ -777,7 +777,7 @@ gtk_model_button_draw (GtkWidget *widget,
if (gtk_widget_has_visible_focus (widget))
{
GtkBorder border;
gtk_style_context_get_border (context, gtk_style_context_get_state (context), &border);
gtk_render_focus (context, cr,
@@ -861,7 +861,7 @@ gtk_model_button_class_init (GtkModelButtonClass *class)
*
* Since: 3.16
*/
properties[PROP_ICON] =
properties[PROP_ICON] =
g_param_spec_object ("icon",
P_("Icon"),
P_("The icon"),

View File

@@ -2330,7 +2330,10 @@ gtk_popover_bind_model (GtkPopover *popover,
gtk_widget_show (stack);
gtk_container_add (GTK_CONTAINER (popover), stack);
gtk_menu_section_box_new_toplevel (GTK_STACK (stack), model, action_namespace);
gtk_menu_section_box_new_toplevel (GTK_STACK (stack),
model,
action_namespace,
popover);
gtk_stack_set_visible_child_name (GTK_STACK (stack), "main");
g_signal_connect (popover, "unmap", G_CALLBACK (back_to_main), NULL);

View File

@@ -137,6 +137,9 @@ typedef struct {
gint64 start_time;
gint64 end_time;
gint last_visible_widget_width;
gint last_visible_widget_height;
GtkStackTransitionType active_transition_type;
} GtkStackPrivate;
@@ -201,8 +204,6 @@ G_DEFINE_TYPE_WITH_PRIVATE (GtkStack, gtk_stack, GTK_TYPE_CONTAINER)
static void
gtk_stack_init (GtkStack *stack)
{
gtk_widget_set_has_window ((GtkWidget*) stack, TRUE);
gtk_widget_set_redraw_on_allocate ((GtkWidget*) stack, TRUE);
}
static void
@@ -846,6 +847,9 @@ gtk_stack_set_transition_position (GtkStack *stack,
priv->transition_pos = pos;
gtk_widget_queue_draw (GTK_WIDGET (stack));
if (!priv->vhomogeneous || !priv->hhomogeneous)
gtk_widget_queue_resize (GTK_WIDGET (stack));
if (priv->bin_window != NULL &&
is_window_moving_transition (priv->active_transition_type))
{
@@ -857,15 +861,6 @@ gtk_stack_set_transition_position (GtkStack *stack,
done = pos >= 1.0;
if (done || priv->last_visible_surface != NULL)
{
if (priv->last_visible_child)
{
gtk_widget_set_child_visible (priv->last_visible_child->widget, FALSE);
priv->last_visible_child = NULL;
}
}
if (done)
{
if (priv->last_visible_surface != NULL)
@@ -874,6 +869,12 @@ gtk_stack_set_transition_position (GtkStack *stack,
priv->last_visible_surface = NULL;
}
if (priv->last_visible_child != NULL)
{
gtk_widget_set_child_visible (priv->last_visible_child->widget, FALSE);
priv->last_visible_child = NULL;
}
gtk_widget_queue_resize (GTK_WIDGET (stack));
}
@@ -897,12 +898,11 @@ gtk_stack_transition_cb (GtkWidget *widget,
t = (now - priv->start_time) / (double) (priv->end_time - priv->start_time);
/* Finish animation early if not mapped anymore */
if (!gtk_widget_get_mapped (GTK_WIDGET (stack)))
if (!gtk_widget_get_mapped (widget))
t = 1.0;
if (gtk_stack_set_transition_position (stack, t))
{
gtk_widget_set_opacity (GTK_WIDGET (stack), 1.0);
priv->tick_id = 0;
g_object_notify_by_pspec (G_OBJECT (stack), stack_props[PROP_TRANSITION_RUNNING]);
@@ -1060,9 +1060,20 @@ set_visible_child (GtkStack *stack,
if (priv->visible_child && priv->visible_child->widget)
{
if (gtk_widget_is_visible (widget))
priv->last_visible_child = priv->visible_child;
{
int fake;
priv->last_visible_child = priv->visible_child;
gtk_widget_get_preferred_width (priv->last_visible_child->widget,
&fake,
&priv->last_visible_widget_width);
gtk_widget_get_preferred_height (priv->last_visible_child->widget,
&fake,
&priv->last_visible_widget_height);
}
else
gtk_widget_set_child_visible (priv->visible_child->widget, FALSE);
{
gtk_widget_set_child_visible (priv->visible_child->widget, FALSE);
}
}
priv->visible_child = child_info;
@@ -1102,9 +1113,6 @@ set_visible_child (GtkStack *stack,
transition_type = get_simple_transition_type (i_first, transition_type);
}
gtk_widget_queue_resize (GTK_WIDGET (stack));
gtk_widget_queue_draw (GTK_WIDGET (stack));
g_object_notify_by_pspec (G_OBJECT (stack), stack_props[PROP_VISIBLE_CHILD]);
g_object_notify_by_pspec (G_OBJECT (stack),
stack_props[PROP_VISIBLE_CHILD_NAME]);
@@ -1195,7 +1203,7 @@ gtk_stack_add_named (GtkStack *stack,
static void
gtk_stack_add (GtkContainer *container,
GtkWidget *child)
GtkWidget *child)
{
GtkStack *stack = GTK_STACK (container);
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
@@ -1410,7 +1418,7 @@ gtk_stack_set_hhomogeneous (GtkStack *stack,
if (priv->hhomogeneous == hhomogeneous)
return;
priv->hhomogeneous = hhomogeneous;
if (gtk_widget_get_visible (GTK_WIDGET(stack)))
@@ -1464,7 +1472,7 @@ gtk_stack_set_vhomogeneous (GtkStack *stack,
if (priv->vhomogeneous == vhomogeneous)
return;
priv->vhomogeneous = vhomogeneous;
if (gtk_widget_get_visible (GTK_WIDGET(stack)))
@@ -1974,6 +1982,13 @@ gtk_stack_draw_slide (GtkWidget *widget,
x += priv->last_visible_surface_allocation.x;
y += priv->last_visible_surface_allocation.y;
if (gtk_widget_get_valign (priv->last_visible_child->widget) == GTK_ALIGN_END &&
priv->last_visible_widget_height > allocation.height)
y -= priv->last_visible_widget_height - allocation.height;
else if (gtk_widget_get_valign (priv->last_visible_child->widget) == GTK_ALIGN_CENTER)
y -= (priv->last_visible_widget_height - allocation.height) / 2;
cairo_save (cr);
cairo_set_source_surface (cr, priv->last_visible_surface, x, y);
cairo_paint (cr);
@@ -1982,8 +1997,8 @@ gtk_stack_draw_slide (GtkWidget *widget,
if (gtk_cairo_should_draw_window (cr, priv->bin_window))
gtk_container_propagate_draw (GTK_CONTAINER (stack),
priv->visible_child->widget,
cr);
priv->visible_child->widget,
cr);
}
static gboolean
@@ -1997,7 +2012,7 @@ gtk_stack_draw (GtkWidget *widget,
if (gtk_cairo_should_draw_window (cr, priv->view_window))
{
GtkStyleContext *context;
context = gtk_widget_get_style_context (widget);
gtk_render_background (context,
cr,
@@ -2077,15 +2092,32 @@ gtk_stack_size_allocate (GtkWidget *widget,
gtk_widget_set_allocation (widget, allocation);
child_allocation = *allocation;
child_allocation.x = 0;
child_allocation.y = 0;
child_allocation.width = allocation->width;
child_allocation.height = allocation->height;
if (priv->last_visible_child)
gtk_widget_size_allocate (priv->last_visible_child->widget, &child_allocation);
if (priv->visible_child)
gtk_widget_size_allocate (priv->visible_child->widget, &child_allocation);
{
int min, nat;
gtk_widget_get_preferred_height_for_width (priv->visible_child->widget,
allocation->width,
&min, &nat);
GtkAlign valign = gtk_widget_get_valign (priv->visible_child->widget);
child_allocation.height = MAX (nat, allocation->height);
if (valign == GTK_ALIGN_END &&
child_allocation.height > allocation->height)
child_allocation.y -= nat - allocation->height;
else if (valign == GTK_ALIGN_CENTER &&
child_allocation.height > allocation->height)
child_allocation.y -= (nat - allocation->height) / 2;
gtk_widget_size_allocate (priv->visible_child->widget, &child_allocation);
}
if (gtk_widget_get_realized (widget))
{
@@ -2098,6 +2130,9 @@ gtk_stack_size_allocate (GtkWidget *widget,
}
}
#define LERP(a, b, t) ((a) + (((b) - (a)) * (1.0 - (t))))
static void
gtk_stack_get_preferred_height (GtkWidget *widget,
gint *minimum_height,
@@ -2119,9 +2154,9 @@ gtk_stack_get_preferred_height (GtkWidget *widget,
child = child_info->widget;
if (!priv->vhomogeneous &&
(priv->visible_child != child_info &&
priv->last_visible_child != child_info))
priv->visible_child != child_info)
continue;
if (gtk_widget_get_visible (child))
{
gtk_widget_get_preferred_height (child, &child_min, &child_nat);
@@ -2131,10 +2166,11 @@ gtk_stack_get_preferred_height (GtkWidget *widget,
}
}
if (priv->last_visible_surface != NULL)
if (priv->last_visible_child != NULL && !priv->vhomogeneous)
{
*minimum_height = MAX (*minimum_height, priv->last_visible_surface_allocation.height);
*natural_height = MAX (*natural_height, priv->last_visible_surface_allocation.height);
gdouble t = ease_out_cubic (priv->transition_pos);
*minimum_height = LERP (*minimum_height, priv->last_visible_widget_height, t);
*natural_height = LERP (*natural_height, priv->last_visible_widget_height, t);
}
}
@@ -2160,9 +2196,9 @@ gtk_stack_get_preferred_height_for_width (GtkWidget *widget,
child = child_info->widget;
if (!priv->vhomogeneous &&
(priv->visible_child != child_info &&
priv->last_visible_child != child_info))
priv->visible_child != child_info)
continue;
if (gtk_widget_get_visible (child))
{
gtk_widget_get_preferred_height_for_width (child, width, &child_min, &child_nat);
@@ -2172,10 +2208,11 @@ gtk_stack_get_preferred_height_for_width (GtkWidget *widget,
}
}
if (priv->last_visible_surface != NULL)
if (priv->last_visible_child != NULL && !priv->vhomogeneous)
{
*minimum_height = MAX (*minimum_height, priv->last_visible_surface_allocation.height);
*natural_height = MAX (*natural_height, priv->last_visible_surface_allocation.height);
gdouble t = ease_out_cubic (priv->transition_pos);
*minimum_height = LERP (*minimum_height, priv->last_visible_widget_height, t);
*natural_height = LERP (*natural_height, priv->last_visible_widget_height, t);
}
}
@@ -2200,8 +2237,7 @@ gtk_stack_get_preferred_width (GtkWidget *widget,
child = child_info->widget;
if (!priv->hhomogeneous &&
(priv->visible_child != child_info &&
priv->last_visible_child != child_info))
priv->visible_child != child_info)
continue;
if (gtk_widget_get_visible (child))
{
@@ -2212,10 +2248,11 @@ gtk_stack_get_preferred_width (GtkWidget *widget,
}
}
if (priv->last_visible_surface != NULL)
if (priv->last_visible_child != NULL && !priv->hhomogeneous)
{
*minimum_width = MAX (*minimum_width, priv->last_visible_surface_allocation.width);
*natural_width = MAX (*natural_width, priv->last_visible_surface_allocation.width);
gdouble t = ease_out_cubic (priv->transition_pos);
*minimum_width = LERP (*minimum_width, priv->last_visible_widget_width, t);
*natural_width = LERP (*natural_width, priv->last_visible_widget_width, t);
}
}
@@ -2241,8 +2278,7 @@ gtk_stack_get_preferred_width_for_height (GtkWidget *widget,
child = child_info->widget;
if (!priv->hhomogeneous &&
(priv->visible_child != child_info &&
priv->last_visible_child != child_info))
priv->visible_child != child_info)
continue;
if (gtk_widget_get_visible (child))
{
@@ -2253,9 +2289,10 @@ gtk_stack_get_preferred_width_for_height (GtkWidget *widget,
}
}
if (priv->last_visible_surface != NULL)
if (priv->last_visible_child != NULL && !priv->hhomogeneous)
{
*minimum_width = MAX (*minimum_width, priv->last_visible_surface_allocation.width);
*natural_width = MAX (*natural_width, priv->last_visible_surface_allocation.width);
gdouble t = ease_out_cubic (priv->transition_pos);
*minimum_width = LERP (*minimum_width, priv->last_visible_widget_width, t);
*natural_width = LERP (*natural_width, priv->last_visible_widget_width, t);
}
}