diff --git a/gtk/Makefile.am b/gtk/Makefile.am index c2d4cb2197..1e375aff79 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -1101,7 +1101,8 @@ COMPOSITE_TEMPLATES = \ gtkdialog.ui \ gtkinfobar.ui \ gtklockbutton.ui \ - gtkmessagedialog.ui + gtkmessagedialog.ui \ + gtkscalebutton.ui # # rules to generate built sources diff --git a/gtk/gtk.gresource.xml b/gtk/gtk.gresource.xml index fc936e8112..856b450c53 100644 --- a/gtk/gtk.gresource.xml +++ b/gtk/gtk.gresource.xml @@ -17,5 +17,6 @@ gtkinfobar.ui gtklockbutton.ui gtkmessagedialog.ui + gtkscalebutton.ui diff --git a/gtk/gtkscalebutton.c b/gtk/gtkscalebutton.c index f10bb0308d..945e8ef596 100644 --- a/gtk/gtkscalebutton.c +++ b/gtk/gtkscalebutton.c @@ -167,15 +167,27 @@ static void cb_scale_grab_notify (GtkWidget *widget, static void gtk_scale_button_update_icon (GtkScaleButton *button); static void gtk_scale_button_scale_value_changed(GtkRange *range); -/* see below for scale definitions */ -static GtkWidget *gtk_scale_button_scale_new (GtkScaleButton *button); - G_DEFINE_TYPE_WITH_CODE (GtkScaleButton, gtk_scale_button, GTK_TYPE_BUTTON, G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL)) static guint signals[LAST_SIGNAL] = { 0, }; +/* + * ScaleButtonScale forward declarations + */ +#define GTK_TYPE_SCALE_BUTTON_SCALE (_gtk_scale_button_scale_get_type ()) +#define GTK_SCALE_BUTTON_SCALE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SCALE_BUTTON_SCALE, GtkScaleButtonScale)) +#define GTK_IS_SCALE_BUTTON_SCALE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SCALE_BUTTON_SCALE)) +GType _gtk_scale_button_scale_get_type (void); + +typedef struct _GtkScaleButtonScale +{ + GtkScale parent_instance; + GtkScaleButton *button; +} GtkScaleButtonScale; + + static void gtk_scale_button_class_init (GtkScaleButtonClass *klass) { @@ -345,6 +357,27 @@ gtk_scale_button_class_init (GtkScaleButtonClass *klass) gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "popdown", 0); + /* Bind class to template + */ + gtk_widget_class_set_template_from_resource (widget_class, + "/org/gtk/libgtk/gtkscalebutton.ui"); + + gtk_widget_class_bind_child_internal (widget_class, GtkScaleButtonPrivate, plus_button); + gtk_widget_class_bind_child_internal (widget_class, GtkScaleButtonPrivate, minus_button); + gtk_widget_class_bind_child (widget_class, GtkScaleButtonPrivate, dock); + gtk_widget_class_bind_child (widget_class, GtkScaleButtonPrivate, box); + gtk_widget_class_bind_child (widget_class, GtkScaleButtonPrivate, scale); + gtk_widget_class_bind_child (widget_class, GtkScaleButtonPrivate, image); + gtk_widget_class_bind_child (widget_class, GtkScaleButtonPrivate, adjustment); + + gtk_widget_class_bind_callback (widget_class, cb_dock_button_press); + gtk_widget_class_bind_callback (widget_class, cb_dock_key_release); + gtk_widget_class_bind_callback (widget_class, cb_dock_grab_notify); + gtk_widget_class_bind_callback (widget_class, cb_dock_grab_broken_event); + gtk_widget_class_bind_callback (widget_class, cb_button_press); + gtk_widget_class_bind_callback (widget_class, cb_button_release); + gtk_widget_class_bind_callback (widget_class, cb_scale_grab_notify); + gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_SCALE_BUTTON_ACCESSIBLE); } @@ -352,7 +385,6 @@ static void gtk_scale_button_init (GtkScaleButton *button) { GtkScaleButtonPrivate *priv; - GtkWidget *frame; button->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (button, GTK_TYPE_SCALE_BUTTON, @@ -363,60 +395,16 @@ gtk_scale_button_init (GtkScaleButton *button) priv->click_timeout = CLICK_TIMEOUT; priv->orientation = GTK_ORIENTATION_VERTICAL; - gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); - gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE); + g_type_ensure (GTK_TYPE_SCALE_BUTTON_SCALE); + gtk_widget_init_template (GTK_WIDGET (button)); - /* image */ - priv->image = gtk_image_new (); - gtk_container_add (GTK_CONTAINER (button), priv->image); - gtk_widget_show_all (priv->image); + /* Assign GtkScaleButtonScale pointer back to 'button', + * since there's no property for that we can't do it in the template + */ + GTK_SCALE_BUTTON_SCALE (priv->scale)->button = button; - /* window */ - priv->dock = gtk_window_new (GTK_WINDOW_POPUP); - gtk_widget_set_name (priv->dock, "gtk-scalebutton-popup-window"); - g_signal_connect (priv->dock, "button-press-event", - G_CALLBACK (cb_dock_button_press), button); - g_signal_connect (priv->dock, "key-release-event", - G_CALLBACK (cb_dock_key_release), button); - g_signal_connect (priv->dock, "grab-notify", - G_CALLBACK (cb_dock_grab_notify), button); - g_signal_connect (priv->dock, "grab-broken-event", - G_CALLBACK (cb_dock_grab_broken_event), button); - gtk_window_set_decorated (GTK_WINDOW (priv->dock), FALSE); - - /* frame */ - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); - gtk_container_add (GTK_CONTAINER (priv->dock), frame); - - /* box for scale and +/- buttons */ - priv->box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - gtk_container_add (GTK_CONTAINER (frame), priv->box); - - /* + */ - priv->plus_button = gtk_button_new_with_label ("+"); - gtk_button_set_relief (GTK_BUTTON (priv->plus_button), GTK_RELIEF_NONE); - g_signal_connect (priv->plus_button, "button-press-event", - G_CALLBACK (cb_button_press), button); - g_signal_connect (priv->plus_button, "button-release-event", - G_CALLBACK (cb_button_release), button); - gtk_box_pack_start (GTK_BOX (priv->box), priv->plus_button, FALSE, FALSE, 0); - - /* - */ - priv->minus_button = gtk_button_new_with_label ("-"); - gtk_button_set_relief (GTK_BUTTON (priv->minus_button), GTK_RELIEF_NONE); - g_signal_connect (priv->minus_button, "button-press-event", - G_CALLBACK (cb_button_press), button); - g_signal_connect (priv->minus_button, "button-release-event", - G_CALLBACK (cb_button_release), button); - gtk_box_pack_end (GTK_BOX (priv->box), priv->minus_button, FALSE, FALSE, 0); - - priv->adjustment = gtk_adjustment_new (0.0, 0.0, 100.0, 2, 20, 0); - g_object_ref_sink (priv->adjustment); - - /* the scale */ - priv->scale = gtk_scale_button_scale_new (button); - gtk_container_add (GTK_CONTAINER (priv->box), priv->scale); + /* Need a local reference to the adjustment */ + g_object_ref (priv->adjustment); gtk_widget_add_events (GTK_WIDGET (button), GDK_SCROLL_MASK); } @@ -1402,17 +1390,6 @@ cb_scale_grab_notify (GtkWidget *widget, /* * Scale stuff. */ - -#define GTK_TYPE_SCALE_BUTTON_SCALE (_gtk_scale_button_scale_get_type ()) -#define GTK_SCALE_BUTTON_SCALE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SCALE_BUTTON_SCALE, GtkScaleButtonScale)) -#define GTK_IS_SCALE_BUTTON_SCALE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SCALE_BUTTON_SCALE)) - -typedef struct _GtkScaleButtonScale -{ - GtkScale parent_instance; - GtkScaleButton *button; -} GtkScaleButtonScale; - typedef struct _GtkScaleButtonScaleClass { GtkScaleClass parent_class; @@ -1423,8 +1400,6 @@ static gboolean gtk_scale_button_scale_press (GtkWidget *widget, static gboolean gtk_scale_button_scale_release (GtkWidget *widget, GdkEventButton *event); -GType _gtk_scale_button_scale_get_type (void); - G_DEFINE_TYPE (GtkScaleButtonScale, _gtk_scale_button_scale, GTK_TYPE_SCALE) static void @@ -1443,42 +1418,19 @@ _gtk_scale_button_scale_init (GtkScaleButtonScale *scale) { } -static GtkWidget * -gtk_scale_button_scale_new (GtkScaleButton *button) -{ - GtkScaleButtonPrivate *priv = button->priv; - GtkScaleButtonScale *scale; - - scale = g_object_new (GTK_TYPE_SCALE_BUTTON_SCALE, - "orientation", priv->orientation, - "adjustment", priv->adjustment, - "draw-value", FALSE, - NULL); - - scale->button = button; - - g_signal_connect (scale, "grab-notify", - G_CALLBACK (cb_scale_grab_notify), button); - - if (priv->orientation == GTK_ORIENTATION_VERTICAL) - { - gtk_widget_set_size_request (GTK_WIDGET (scale), -1, SCALE_SIZE); - gtk_range_set_inverted (GTK_RANGE (scale), TRUE); - } - else - { - gtk_widget_set_size_request (GTK_WIDGET (scale), SCALE_SIZE, -1); - gtk_range_set_inverted (GTK_RANGE (scale), FALSE); - } - - return GTK_WIDGET (scale); -} - static gboolean gtk_scale_button_scale_press (GtkWidget *widget, GdkEventButton *event) { - GtkScaleButtonPrivate *priv = GTK_SCALE_BUTTON_SCALE (widget)->button->priv; + GtkScaleButtonPrivate *priv; + + /* Avoid a crash when using a GtkScaleButtonScale without a GtkScaleButton, + * this can happen while editing gtkscalebutton.ui in Glade + */ + if (!GTK_SCALE_BUTTON_SCALE (widget)->button) + return GTK_WIDGET_CLASS (_gtk_scale_button_scale_parent_class)->button_release_event (widget, event); + + priv = GTK_SCALE_BUTTON_SCALE (widget)->button->priv; /* the scale will grab input; if we have input grabbed, all goes * horribly wrong, so let's not do that. @@ -1495,6 +1447,12 @@ gtk_scale_button_scale_release (GtkWidget *widget, GtkScaleButton *button = GTK_SCALE_BUTTON_SCALE (widget)->button; gboolean res; + /* Avoid a crash when using a GtkScaleButtonScale without a GtkScaleButton, + * this can happen while editing gtkscalebutton.ui in Glade + */ + if (!button) + return GTK_WIDGET_CLASS (_gtk_scale_button_scale_parent_class)->button_release_event (widget, event); + if (button->priv->timeout) { /* if we did a quick click, leave the window open; else, hide it */ @@ -1604,6 +1562,12 @@ gtk_scale_button_scale_value_changed (GtkRange *range) GtkScaleButton *button = GTK_SCALE_BUTTON_SCALE (range)->button; gdouble value; + /* Avoid a crash when using a GtkScaleButtonScale without a GtkScaleButton, + * this can happen while editing gtkscalebutton.ui in Glade + */ + if (!button) + return; + value = gtk_range_get_value (range); gtk_scale_button_update_icon (button); diff --git a/gtk/gtkscalebutton.ui b/gtk/gtkscalebutton.ui new file mode 100644 index 0000000000..e12b008b30 --- /dev/null +++ b/gtk/gtkscalebutton.ui @@ -0,0 +1,101 @@ + + + + + + + 100 + 2 + 20 + + + gtk-scalebutton-popup-window + False + popup + False + + + + + + + True + False + 0 + out + + + True + False + vertical + + + + + True + True + True + none + + + + + False + False + 0 + + + + + 100 + True + True + vertical + adjustment + True + 1 + False + + + + False + True + 1 + + + + + - + True + True + True + none + + + + + False + False + 2 + + + + + + + + + + + diff --git a/gtk/tests/templates.c b/gtk/tests/templates.c index 9faebb9bd9..7cf7c63a8d 100644 --- a/gtk/tests/templates.c +++ b/gtk/tests/templates.c @@ -98,6 +98,17 @@ test_assistant_basic (void) gtk_widget_destroy (widget); } +static void +test_scale_button_basic (void) +{ + GtkWidget *widget; + + widget = gtk_scale_button_new (GTK_ICON_SIZE_MENU, + 0, 100, 10, NULL); + g_assert (GTK_IS_SCALE_BUTTON (widget)); + gtk_widget_destroy (widget); +} + int main (int argc, char **argv) { @@ -117,6 +128,7 @@ main (int argc, char **argv) g_test_add_func ("/Template/GtkInfoBar/Basic", test_info_bar_basic); g_test_add_func ("/Template/GtkLockButton/Basic", test_lock_button_basic); g_test_add_func ("/Template/GtkAssistant/Basic", test_assistant_basic); + g_test_add_func ("/Template/GtkScaleButton/Basic", test_scale_button_basic); return g_test_run(); }