Merge branch 'switch-rtl' into 'main'

switch: Respect text direction

Closes #1489

See merge request GNOME/gtk!6396
This commit is contained in:
Matthias Clasen 2023-09-15 21:59:15 +00:00
commit 86e0d5c13e

View File

@ -47,13 +47,13 @@
*
* ```
* switch
* label
* label
* image
* image
* slider
* ```
*
* `GtkSwitch` has four css nodes, the main node with the name switch and
* subnodes for the slider and the on and off labels. Neither of them is
* subnodes for the slider and the on and off images. Neither of them is
* using any style classes.
*
* # Accessibility
@ -140,6 +140,16 @@ G_DEFINE_TYPE_WITH_CODE (GtkSwitch, gtk_switch, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIONABLE,
gtk_switch_actionable_iface_init))
static gboolean
is_right_side (GtkWidget *widget,
gboolean active)
{
if (_gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
return active;
else
return !active;
}
static void
gtk_switch_end_toggle_animation (GtkSwitch *self)
{
@ -156,16 +166,18 @@ gtk_switch_on_frame_clock_update (GtkWidget *widget,
gpointer user_data)
{
GtkSwitch *self = GTK_SWITCH (widget);
double progress;
gtk_progress_tracker_advance_frame (&self->tracker,
gdk_frame_clock_get_frame_time (clock));
if (gtk_progress_tracker_get_state (&self->tracker) != GTK_PROGRESS_STATE_AFTER)
{
if (self->is_active)
self->handle_pos = 1.0 - gtk_progress_tracker_get_ease_out_cubic (&self->tracker, FALSE);
progress = gtk_progress_tracker_get_ease_out_cubic (&self->tracker, FALSE);
if (is_right_side (widget, self->is_active))
self->handle_pos = 1.0 - progress;
else
self->handle_pos = gtk_progress_tracker_get_ease_out_cubic (&self->tracker, FALSE);
self->handle_pos = progress;
}
else
{
@ -251,7 +263,7 @@ gtk_switch_pan_gesture_pan (GtkGesturePan *gesture,
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
if (self->is_active)
if (is_right_side (widget, self->is_active))
offset += width / 2;
offset /= width / 2;
@ -268,6 +280,7 @@ gtk_switch_pan_gesture_drag_end (GtkGestureDrag *gesture,
double y,
GtkSwitch *self)
{
GtkWidget *widget = GTK_WIDGET (self);
GdkEventSequence *sequence;
gboolean active;
@ -278,16 +291,19 @@ gtk_switch_pan_gesture_drag_end (GtkGestureDrag *gesture,
/* if half the handle passed the middle of the switch, then we
* consider it to be on
*/
active = self->handle_pos >= 0.5;
if (_gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
active = self->handle_pos >= 0.5;
else
active = self->handle_pos <= 0.5;
}
else if (!gtk_gesture_handles_sequence (self->click_gesture, sequence))
active = self->is_active;
else
return;
self->handle_pos = active ? 1.0 : 0.0;
self->handle_pos = is_right_side (widget, active) ? 1.0 : 0.0;
gtk_switch_set_active (self, active);
gtk_widget_queue_allocate (GTK_WIDGET (self));
gtk_widget_queue_allocate (widget);
}
static void
@ -354,6 +370,8 @@ gtk_switch_allocate (GtkWidget *widget,
/* Center ON icon in left half */
gtk_widget_measure (self->on_image, GTK_ORIENTATION_HORIZONTAL, -1, &min, NULL, NULL, NULL);
child_alloc.x = ((width / 2) - min) / 2;
if (is_right_side (widget, FALSE))
child_alloc.x += width / 2;
child_alloc.width = min;
gtk_widget_measure (self->on_image, GTK_ORIENTATION_VERTICAL, min, &min, NULL, NULL, NULL);
child_alloc.y = (height - min) / 2;
@ -362,7 +380,9 @@ gtk_switch_allocate (GtkWidget *widget,
/* Center OFF icon in right half */
gtk_widget_measure (self->off_image, GTK_ORIENTATION_HORIZONTAL, -1, &min, NULL, NULL, NULL);
child_alloc.x = (width / 2) + ((width / 2) - min) / 2;
child_alloc.x = ((width / 2) - min) / 2;
if (is_right_side (widget, TRUE))
child_alloc.x += width / 2;
child_alloc.width = min;
gtk_widget_measure (self->off_image, GTK_ORIENTATION_VERTICAL, min, &min, NULL, NULL, NULL);
child_alloc.y = (height - min) / 2;
@ -370,6 +390,18 @@ gtk_switch_allocate (GtkWidget *widget,
gtk_widget_size_allocate (self->off_image, &child_alloc, -1);
}
static void
gtk_switch_direction_changed (GtkWidget *widget,
GtkTextDirection previous_dir)
{
GtkSwitch *self = GTK_SWITCH (widget);
self->handle_pos = 1.0 - self->handle_pos;
gtk_widget_queue_allocate (widget);
GTK_WIDGET_CLASS (gtk_switch_parent_class)->direction_changed (widget, previous_dir);
}
static void
gtk_switch_set_action_name (GtkActionable *actionable,
const char *action_name)
@ -552,6 +584,8 @@ gtk_switch_class_init (GtkSwitchClass *klass)
g_object_class_install_properties (gobject_class, LAST_PROP, switch_props);
widget_class->direction_changed = gtk_switch_direction_changed;
klass->activate = gtk_switch_activate;
klass->state_set = state_set;
@ -676,6 +710,10 @@ gtk_switch_init (GtkSwitch *self)
gtk_accessible_update_state (GTK_ACCESSIBLE (self),
GTK_ACCESSIBLE_STATE_CHECKED, FALSE,
-1);
if (is_right_side (GTK_WIDGET (self), FALSE))
self->handle_pos = 1.0;
else
self->handle_pos = 0.0;
}
/**
@ -714,7 +752,7 @@ gtk_switch_set_active (GtkSwitch *self,
self->is_active = is_active;
if (self->is_active)
if (is_right_side (GTK_WIDGET (self), self->is_active))
self->handle_pos = 1.0;
else
self->handle_pos = 0.0;