#54720 -button children should optionally move
- From: Owen Taylor <otaylor redhat com>
- To: gtk-devel-list gnome org
- Cc: sandmann daimi au dk
- Subject: #54720 -button children should optionally move
- Date: 22 Aug 2001 12:48:03 -0400
I took a look at this patch and ended up rewriting it quite a bit.
* I simplified a lot of the logic in GtkButton and GtkToggleButton to centralize
all the state maintanence in one place for each widget.
* I removed the movement for the child of check/radio buttons with
draw_indicator == TRUE. This just looked very weird to me, and windows
does not do this.
* Instead of adding a ->depressed() virtual function, I added a function
_gtk_button_set_depressed() that sets a depressed flag. This resulted
in more consistent code since the state of the widget was maintained via
gtk_widget_set_state() rather than a callback.
Remaining possible questions about this patch:
* Should we have separate child_displacement_x/child_displacement_y
properties? Does it ever make sense for them to be separate
* Should we increase the amount of space requested for the button
based on the amount of displacement? Currently, things don't
work very will if the displacement is more than 1.
* Should _gtk_button_set_depressed() be exported? If someone wanted
to write a like-toggle-button widget right now, they wouldn't
be able to. On the other hand, making it public is inviting
confusion and abuse.
Regards,
Owen
? gtkcontainer.c.bench
Index: gtkbutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkbutton.c,v
retrieving revision 1.65
diff -u -r1.65 gtkbutton.c
--- gtkbutton.c 2001/07/18 23:39:21 1.65
+++ gtkbutton.c 2001/08/22 16:35:40
@@ -97,9 +97,8 @@
GtkWidget *widget);
static void gtk_real_button_pressed (GtkButton *button);
static void gtk_real_button_released (GtkButton *button);
-static void gtk_real_button_enter (GtkButton *button);
-static void gtk_real_button_leave (GtkButton *button);
static void gtk_real_button_activate (GtkButton *button);
+static void gtk_button_update_state (GtkButton *button);
static GtkType gtk_button_child_type (GtkContainer *container);
static void gtk_button_finish_activate (GtkButton *button,
@@ -169,8 +168,8 @@
klass->pressed = gtk_real_button_pressed;
klass->released = gtk_real_button_released;
klass->clicked = NULL;
- klass->enter = gtk_real_button_enter;
- klass->leave = gtk_real_button_leave;
+ klass->enter = gtk_button_update_state;
+ klass->leave = gtk_button_update_state;
klass->activate = gtk_real_button_activate;
g_object_class_install_property (G_OBJECT_CLASS(object_class),
@@ -247,6 +246,22 @@
_("Extra space to add for CAN_DEFAULT buttons that is always drawn outside the border"),
GTK_TYPE_BORDER,
G_PARAM_READABLE));
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_int ("child_displacement_x",
+ _("Child X Displacement"),
+ _("How far in the x direction to move the child when the button is depressed"),
+ G_MININT,
+ G_MAXINT,
+ 0,
+ G_PARAM_READABLE));
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_int ("child_displacement_y",
+ _("Child Y Displacement"),
+ _("How far in the y direction to move the child when the button is depressed"),
+ G_MININT,
+ G_MAXINT,
+ 0,
+ G_PARAM_READABLE));
}
static void
@@ -259,6 +274,7 @@
button->in_button = FALSE;
button->button_down = FALSE;
button->relief = GTK_RELIEF_NORMAL;
+ button->depressed = FALSE;
}
static GtkType
@@ -656,6 +672,19 @@
child_allocation.height = MAX (1, child_allocation.height - default_border.top - default_border.bottom);
}
+ if (button->depressed)
+ {
+ gint child_displacement_x;
+ gint child_displacement_y;
+
+ gtk_widget_style_get (widget,
+ "child_displacement_x", &child_displacement_x,
+ "child_displacement_y", &child_displacement_y,
+ NULL);
+ child_allocation.x += child_displacement_x;
+ child_allocation.y += child_displacement_y;
+ }
+
gtk_widget_size_allocate (GTK_BIN (button)->child, &child_allocation);
}
}
@@ -740,12 +769,9 @@
width -= 2;
height -= 2;
}
-
- if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
- shadow_type = GTK_SHADOW_IN;
- else
- shadow_type = GTK_SHADOW_OUT;
+ shadow_type = button->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+
if ((button->relief != GTK_RELIEF_NONE) ||
((GTK_WIDGET_STATE(widget) != GTK_STATE_NORMAL) &&
(GTK_WIDGET_STATE(widget) != GTK_STATE_INSENSITIVE)))
@@ -937,88 +963,30 @@
static void
gtk_real_button_pressed (GtkButton *button)
{
- GtkStateType new_state;
-
- g_return_if_fail (GTK_IS_BUTTON (button));
-
if (button->activate_timeout)
return;
button->button_down = TRUE;
-
- new_state = (button->in_button ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
-
- if (GTK_WIDGET_STATE (button) != new_state)
- {
- gtk_widget_set_state (GTK_WIDGET (button), new_state);
- gtk_widget_queue_draw (GTK_WIDGET (button));
- }
+ gtk_button_update_state (button);
}
static void
gtk_real_button_released (GtkButton *button)
{
- GtkStateType new_state;
-
- g_return_if_fail (GTK_IS_BUTTON (button));
-
if (button->button_down)
{
button->button_down = FALSE;
if (button->activate_timeout)
return;
-
+
if (button->in_button)
gtk_button_clicked (button);
-
- new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
- if (GTK_WIDGET_STATE (button) != new_state)
- {
- gtk_widget_set_state (GTK_WIDGET (button), new_state);
- /* We _draw () instead of queue_draw so that if the operation
- * blocks, the label doesn't vanish.
- */
- gtk_widget_draw (GTK_WIDGET (button), NULL);
- }
+ gtk_button_update_state (button);
}
}
-static void
-gtk_real_button_enter (GtkButton *button)
-{
- GtkStateType new_state;
-
- g_return_if_fail (GTK_IS_BUTTON (button));
-
- new_state = (button->button_down ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
-
- if (button->activate_timeout)
- return;
-
- if (GTK_WIDGET_STATE (button) != new_state)
- {
- gtk_widget_set_state (GTK_WIDGET (button), new_state);
- gtk_widget_queue_draw (GTK_WIDGET (button));
- }
-}
-
-static void
-gtk_real_button_leave (GtkButton *button)
-{
- g_return_if_fail (GTK_IS_BUTTON (button));
-
- if (button->activate_timeout)
- return;
-
- if (GTK_WIDGET_STATE (button) != GTK_STATE_NORMAL)
- {
- gtk_widget_set_state (GTK_WIDGET (button), GTK_STATE_NORMAL);
- gtk_widget_queue_draw (GTK_WIDGET (button));
- }
-}
-
static gboolean
button_activate_timeout (gpointer data)
{
@@ -1049,7 +1017,7 @@
button_activate_timeout,
button);
button->button_down = TRUE;
- gtk_widget_set_state (widget, GTK_STATE_ACTIVE);
+ gtk_button_update_state (button);
}
}
}
@@ -1067,10 +1035,49 @@
gtk_grab_remove (widget);
button->button_down = FALSE;
- gtk_widget_set_state (GTK_WIDGET (button),
- button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
+ gtk_button_update_state (button);
if (do_it)
gtk_button_clicked (button);
}
+/**
+ * _gtk_button_set_depressed:
+ * @button: a #GtkButton
+ * @depressed: %TRUE if the button should be drawn with a recessed shadow.
+ *
+ * Sets whether the button is currently drawn as down or not. This is
+ * purely a visual setting, and is meant only for use by derived widgets
+ * such as #GtkToggleButton.
+ **/
+void
+_gtk_button_set_depressed (GtkButton *button,
+ gboolean depressed)
+{
+ GtkWidget *widget = GTK_WIDGET (button);
+
+ depressed = depressed != FALSE;
+
+ if (depressed != button->depressed)
+ {
+ button->depressed = depressed;
+ gtk_widget_queue_resize (widget);
+ }
+}
+
+static void
+gtk_button_update_state (GtkButton *button)
+{
+ gboolean depressed;
+ GtkStateType new_state;
+
+ depressed = button->in_button && button->button_down;
+
+ if (!button->button_down && button->in_button)
+ new_state = GTK_STATE_PRELIGHT;
+ else
+ new_state = depressed ? GTK_STATE_ACTIVE: GTK_STATE_NORMAL;
+
+ _gtk_button_set_depressed (button, depressed);
+ gtk_widget_set_state (GTK_WIDGET (button), new_state);
+}
Index: gtkbutton.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkbutton.h,v
retrieving revision 1.17
diff -u -r1.17 gtkbutton.h
--- gtkbutton.h 2001/03/23 23:39:23 1.17
+++ gtkbutton.h 2001/08/22 16:35:40
@@ -61,6 +61,7 @@
guint in_button : 1;
guint button_down : 1;
guint relief : 2;
+ guint depressed : 1;
};
struct _GtkButtonClass
@@ -76,7 +77,7 @@
};
-GtkType gtk_button_get_type (void) G_GNUC_CONST;
+GtkType gtk_button_get_type (void) G_GNUC_CONST;
GtkWidget* gtk_button_new (void);
GtkWidget* gtk_button_new_with_label (const gchar *label);
GtkWidget* gtk_button_new_from_stock (const gchar *stock_id);
@@ -89,7 +90,8 @@
void gtk_button_set_relief (GtkButton *button,
GtkReliefStyle newstyle);
GtkReliefStyle gtk_button_get_relief (GtkButton *button);
-
+void _gtk_button_set_depressed (GtkButton *button,
+ gboolean depressed);
#ifdef __cplusplus
}
Index: gtktogglebutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktogglebutton.c,v
retrieving revision 1.39
diff -u -r1.39 gtktogglebutton.c
--- gtktogglebutton.c 2001/07/18 23:39:23 1.39
+++ gtktogglebutton.c 2001/08/22 16:35:40
@@ -58,8 +58,6 @@
static void gtk_toggle_button_pressed (GtkButton *button);
static void gtk_toggle_button_released (GtkButton *button);
static void gtk_toggle_button_clicked (GtkButton *button);
-static void gtk_toggle_button_enter (GtkButton *button);
-static void gtk_toggle_button_leave (GtkButton *button);
static void gtk_toggle_button_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -68,11 +66,11 @@
guint prop_id,
GValue *value,
GParamSpec *pspec);
-static void gtk_toggle_button_leave (GtkButton *button);
static void gtk_toggle_button_realize (GtkWidget *widget);
static void gtk_toggle_button_unrealize (GtkWidget *widget);
static void gtk_toggle_button_map (GtkWidget *widget);
static void gtk_toggle_button_unmap (GtkWidget *widget);
+static void gtk_toggle_button_update_state (GtkButton *button);
static guint toggle_button_signals[LAST_SIGNAL] = { 0 };
static GtkContainerClass *parent_class = NULL;
@@ -133,8 +131,8 @@
button_class->pressed = gtk_toggle_button_pressed;
button_class->released = gtk_toggle_button_released;
button_class->clicked = gtk_toggle_button_clicked;
- button_class->enter = gtk_toggle_button_enter;
- button_class->leave = gtk_toggle_button_leave;
+ button_class->enter = gtk_toggle_button_update_state;
+ button_class->leave = gtk_toggle_button_update_state;
class->toggled = NULL;
@@ -406,6 +404,8 @@
if (setting != toggle_button->inconsistent)
{
toggle_button->inconsistent = setting;
+
+ gtk_toggle_button_update_state (GTK_BUTTON (toggle_button));
gtk_widget_queue_draw (GTK_WIDGET (toggle_button));
g_object_notify (G_OBJECT (toggle_button), "inconsistent");
@@ -490,11 +490,8 @@
state_type = GTK_STATE_NORMAL;
shadow_type = GTK_SHADOW_ETCHED_IN;
}
- else if ((GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE) ||
- toggle_button->active)
- shadow_type = GTK_SHADOW_IN;
else
- shadow_type = GTK_SHADOW_OUT;
+ shadow_type = button->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
if (button->relief != GTK_RELIEF_NONE ||
(GTK_WIDGET_STATE(widget) != GTK_STATE_NORMAL &&
@@ -557,117 +554,39 @@
static void
gtk_toggle_button_pressed (GtkButton *button)
{
- GtkToggleButton *toggle_button;
- GtkStateType new_state;
-
- g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
-
- toggle_button = GTK_TOGGLE_BUTTON (button);
-
button->button_down = TRUE;
-
- if (toggle_button->active)
- new_state = (button->in_button ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE);
- else
- new_state = (button->in_button ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
- if (GTK_WIDGET_STATE (button) != new_state)
- gtk_widget_set_state (GTK_WIDGET (button), new_state);
+ gtk_toggle_button_update_state (button);
}
static void
gtk_toggle_button_released (GtkButton *button)
{
- GtkToggleButton *toggle_button;
- GtkStateType new_state;
-
- g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
-
if (button->button_down)
{
- toggle_button = GTK_TOGGLE_BUTTON (button);
-
button->button_down = FALSE;
if (button->in_button)
- {
- gtk_button_clicked (button);
- }
- else
- {
- if (toggle_button->active)
- new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
- else
- new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
+ gtk_button_clicked (button);
- if (GTK_WIDGET_STATE (button) != new_state)
- gtk_widget_set_state (GTK_WIDGET (button), new_state);
- }
+ gtk_toggle_button_update_state (button);
}
}
static void
gtk_toggle_button_clicked (GtkButton *button)
{
- GtkToggleButton *toggle_button;
- GtkStateType new_state;
-
- g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
-
- toggle_button = GTK_TOGGLE_BUTTON (button);
+ GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (button);
toggle_button->active = !toggle_button->active;
gtk_toggle_button_toggled (toggle_button);
-
- if (toggle_button->active)
- new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
- else
- new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
- if (GTK_WIDGET_STATE (button) != new_state)
- gtk_widget_set_state (GTK_WIDGET (button), new_state);
- else
- gtk_widget_queue_draw (GTK_WIDGET (button));
+ gtk_toggle_button_update_state (button);
g_object_notify (G_OBJECT (toggle_button), "active");
}
static void
-gtk_toggle_button_enter (GtkButton *button)
-{
- GtkToggleButton *toggle_button;
- GtkStateType new_state;
-
- g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
-
- toggle_button = GTK_TOGGLE_BUTTON (button);
-
- if (toggle_button->active)
- new_state = (button->button_down ? GTK_STATE_NORMAL : GTK_STATE_PRELIGHT);
- else
- new_state = (button->button_down ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
-
- if (GTK_WIDGET_STATE (button) != new_state)
- gtk_widget_set_state (GTK_WIDGET (button), new_state);
-}
-
-static void
-gtk_toggle_button_leave (GtkButton *button)
-{
- GtkToggleButton *toggle_button;
- GtkStateType new_state;
-
- g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
-
- toggle_button = GTK_TOGGLE_BUTTON (button);
-
- new_state = (toggle_button->active ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
-
- if (GTK_WIDGET_STATE (button) != new_state)
- gtk_widget_set_state (GTK_WIDGET (button), new_state);
-}
-
-static void
gtk_toggle_button_realize (GtkWidget *widget)
{
GtkToggleButton *toggle_button;
@@ -763,4 +682,27 @@
gdk_window_hide (GTK_TOGGLE_BUTTON (widget)->event_window);
GTK_WIDGET_CLASS (parent_class)->unmap (widget);
+}
+
+static void
+gtk_toggle_button_update_state (GtkButton *button)
+{
+ GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (button);
+ gboolean depressed;
+ GtkStateType new_state;
+
+ if (toggle_button->inconsistent)
+ depressed = FALSE;
+ else if (button->in_button && button->button_down)
+ depressed = !toggle_button->active;
+ else
+ depressed = toggle_button->active;
+
+ if (!button->button_down && button->in_button)
+ new_state = GTK_STATE_PRELIGHT;
+ else
+ new_state = depressed ? GTK_STATE_ACTIVE: GTK_STATE_NORMAL;
+
+ _gtk_button_set_depressed (button, depressed);
+ gtk_widget_set_state (GTK_WIDGET (toggle_button), new_state);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]