* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
+#include <config.h>
+#include "gtkalias.h"
#include "gtkbutton.h"
#include "gtkdialog.h"
#include "gtkhbbox.h"
+#include "gtklabel.h"
#include "gtkhseparator.h"
#include "gtkmarshalers.h"
#include "gtkvbox.h"
-#include "gtksignal.h"
#include "gdkkeysyms.h"
#include "gtkmain.h"
#include "gtkintl.h"
#include "gtkbindings.h"
+#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_DIALOG, GtkDialogPrivate))
+
+typedef struct {
+ guint ignore_separator : 1;
+} GtkDialogPrivate;
+
+typedef struct _ResponseData ResponseData;
+
+struct _ResponseData
+{
+ gint response_id;
+};
+
static void gtk_dialog_class_init (GtkDialogClass *klass);
static void gtk_dialog_init (GtkDialog *dialog);
static void gtk_dialog_close (GtkDialog *dialog);
+static ResponseData* get_response_data (GtkWidget *widget,
+ gboolean create);
+
enum {
PROP_0,
PROP_HAS_SEPARATOR
static gpointer parent_class;
static guint dialog_signals[LAST_SIGNAL];
-GtkType
+GType
gtk_dialog_get_type (void)
{
- static GtkType dialog_type = 0;
+ static GType dialog_type = 0;
if (!dialog_type)
{
- static const GtkTypeInfo dialog_info =
+ static const GTypeInfo dialog_info =
{
- "GtkDialog",
- sizeof (GtkDialog),
sizeof (GtkDialogClass),
- (GtkClassInitFunc) gtk_dialog_class_init,
- (GtkObjectInitFunc) gtk_dialog_init,
- /* reserved_1 */ NULL,
- /* reserved_2 */ NULL,
- (GtkClassInitFunc) NULL,
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) gtk_dialog_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GtkDialog),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gtk_dialog_init,
};
- dialog_type = gtk_type_unique (GTK_TYPE_WINDOW, &dialog_info);
+ dialog_type = g_type_register_static (GTK_TYPE_WINDOW, "GtkDialog",
+ &dialog_info, 0);
}
return dialog_type;
gtk_dialog_class_init (GtkDialogClass *class)
{
GObjectClass *gobject_class;
- GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
GtkBindingSet *binding_set;
gobject_class = G_OBJECT_CLASS (class);
- object_class = GTK_OBJECT_CLASS (class);
widget_class = GTK_WIDGET_CLASS (class);
parent_class = g_type_class_peek_parent (class);
class->close = gtk_dialog_close;
+ g_type_class_add_private (gobject_class, sizeof (GtkDialogPrivate));
+
g_object_class_install_property (gobject_class,
PROP_HAS_SEPARATOR,
g_param_spec_boolean ("has_separator",
- _("Has separator"),
- _("The dialog has a separator bar above its buttons"),
+ P_("Has separator"),
+ P_("The dialog has a separator bar above its buttons"),
TRUE,
G_PARAM_READWRITE));
dialog_signals[RESPONSE] =
- gtk_signal_new ("response",
- GTK_RUN_LAST,
- GTK_CLASS_TYPE (object_class),
- GTK_SIGNAL_OFFSET (GtkDialogClass, response),
- _gtk_marshal_NONE__INT,
- GTK_TYPE_NONE, 1,
- GTK_TYPE_INT);
+ g_signal_new ("response",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkDialogClass, response),
+ NULL, NULL,
+ _gtk_marshal_NONE__INT,
+ G_TYPE_NONE, 1,
+ G_TYPE_INT);
dialog_signals[CLOSE] =
- gtk_signal_new ("close",
- GTK_RUN_LAST | GTK_RUN_ACTION,
- GTK_CLASS_TYPE (object_class),
- GTK_SIGNAL_OFFSET (GtkDialogClass, close),
- _gtk_marshal_NONE__NONE,
- GTK_TYPE_NONE, 0);
+ g_signal_new ("close",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkDialogClass, close),
+ NULL, NULL,
+ _gtk_marshal_NONE__NONE,
+ G_TYPE_NONE, 0);
gtk_widget_class_install_style_property (widget_class,
g_param_spec_int ("content_area_border",
- _("Content area border"),
- _("Width of border around the main dialog area"),
+ P_("Content area border"),
+ P_("Width of border around the main dialog area"),
0,
G_MAXINT,
2,
G_PARAM_READABLE));
gtk_widget_class_install_style_property (widget_class,
g_param_spec_int ("button_spacing",
- _("Button spacing"),
- _("Spacing between buttons"),
+ P_("Button spacing"),
+ P_("Spacing between buttons"),
0,
G_MAXINT,
10,
gtk_widget_class_install_style_property (widget_class,
g_param_spec_int ("action_area_border",
- _("Action area border"),
- _("Width of border around the button area at the bottom of the dialog"),
+ P_("Action area border"),
+ P_("Width of border around the button area at the bottom of the dialog"),
0,
G_MAXINT,
5,
static void
gtk_dialog_init (GtkDialog *dialog)
{
+ GtkDialogPrivate *priv;
+
+ priv = GET_PRIVATE (dialog);
+ priv->ignore_separator = FALSE;
+
/* To avoid breaking old code that prevents destroy on delete event
* by connecting a handler, we have to have the FIRST signal
* connection on the dialog.
*/
- gtk_signal_connect (GTK_OBJECT (dialog),
- "delete_event",
- GTK_SIGNAL_FUNC (gtk_dialog_delete_event_handler),
- NULL);
+ g_signal_connect (dialog,
+ "delete_event",
+ G_CALLBACK (gtk_dialog_delete_event_handler),
+ NULL);
dialog->vbox = gtk_vbox_new (FALSE, 0);
* widget in the tab chain, but if this results in the focus
* ending up on one of the response widgets _other_ than the
* default response, we focus the default response instead.
+ *
+ * Additionally, skip selectable labels when looking for the
+ * right initial focus widget.
*/
static void
gtk_dialog_map (GtkWidget *widget)
{
GList *children, *tmp_list;
- g_signal_emit_by_name (window, "move_focus", GTK_DIR_TAB_FORWARD);
+ do
+ {
+ g_signal_emit_by_name (window, "move_focus", GTK_DIR_TAB_FORWARD);
+ }
+ while (GTK_IS_LABEL (window->focus_widget));
tmp_list = children = gtk_container_get_children (GTK_CONTAINER (dialog->action_area));
{
GtkWidget *child = tmp_list->data;
- if (child == window->focus_widget && child != window->default_widget && window->default_widget)
+ if (window->focus_widget == NULL ||
+ (child == window->focus_widget &&
+ child != window->default_widget &&
+ window->default_widget))
{
gtk_widget_grab_focus (window->default_widget);
break;
update_spacings (GTK_DIALOG (widget));
}
+static GtkWidget *
+dialog_find_button (GtkDialog *dialog,
+ gint response_id)
+{
+ GList *children, *tmp_list;
+ GtkWidget *child = NULL;
+
+ children = gtk_container_get_children (GTK_CONTAINER (dialog->action_area));
+
+ for (tmp_list = children; tmp_list; tmp_list = tmp_list->next)
+ {
+ ResponseData *rd = get_response_data (tmp_list->data, FALSE);
+
+ if (rd && rd->response_id == response_id)
+ {
+ child = tmp_list->data;
+ break;
+ }
+ }
+
+ g_list_free (children);
+
+ return child;
+}
+
static void
gtk_dialog_close (GtkDialog *dialog)
{
/* Synthesize delete_event to close dialog. */
- GdkEventAny event;
- GtkWidget *widget;
+ GtkWidget *widget = GTK_WIDGET (dialog);
+ GdkEvent *event;
- widget = GTK_WIDGET (dialog);
-
- event.type = GDK_DELETE;
- event.window = widget->window;
- event.send_event = TRUE;
-
- g_object_ref (G_OBJECT (event.window));
+ if (!dialog_find_button (dialog, GTK_RESPONSE_CANCEL))
+ return;
+
+ event = gdk_event_new (GDK_DELETE);
- gtk_main_do_event ((GdkEvent*)&event);
+ event->any.window = g_object_ref (widget->window);
+ event->any.send_event = TRUE;
- g_object_unref (G_OBJECT (event.window));
+ gtk_main_do_event (event);
+ gdk_event_free (event);
}
GtkWidget*
gtk_dialog_new (void)
{
- return GTK_WIDGET (gtk_type_new (GTK_TYPE_DIALOG));
+ return g_object_new (GTK_TYPE_DIALOG, NULL);
}
static GtkWidget*
{
GtkDialog *dialog;
- dialog = GTK_DIALOG (g_object_new (GTK_TYPE_DIALOG, NULL));
+ dialog = g_object_new (GTK_TYPE_DIALOG, NULL);
if (title)
gtk_window_set_title (GTK_WINDOW (dialog), title);
*
* Here's a simple example:
* <informalexample><programlisting>
- * <!>GtkWidget *dialog = gtk_dialog_new_with_buttons ("My dialog",
- * <!> main_app_window,
- * <!> GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- * <!> GTK_STOCK_OK,
- * <!> GTK_RESPONSE_ACCEPT,
- * <!> GTK_STOCK_CANCEL,
- * <!> GTK_RESPONSE_REJECT,
- * <!> NULL);
+ * GtkWidget *dialog = gtk_dialog_new_with_buttons ("My dialog",
+ * main_app_window,
+ * GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ * GTK_STOCK_OK,
+ * GTK_RESPONSE_ACCEPT,
+ * GTK_STOCK_CANCEL,
+ * GTK_RESPONSE_REJECT,
+ * NULL);
* </programlisting></informalexample>
*
* Return value: a new #GtkDialog
return GTK_WIDGET (dialog);
}
-typedef struct _ResponseData ResponseData;
-
-struct _ResponseData
-{
- gint response_id;
-};
-
static ResponseData*
-get_response_data (GtkWidget *widget)
+get_response_data (GtkWidget *widget,
+ gboolean create)
{
- ResponseData *ad = gtk_object_get_data (GTK_OBJECT (widget),
- "gtk-dialog-response-data");
+ ResponseData *ad = g_object_get_data (G_OBJECT (widget),
+ "gtk-dialog-response-data");
- if (ad == NULL)
+ if (ad == NULL && create)
{
ad = g_new (ResponseData, 1);
- gtk_object_set_data_full (GTK_OBJECT (widget),
- "gtk-dialog-response-data",
- ad,
- g_free);
+ g_object_set_data_full (G_OBJECT (widget),
+ "gtk-dialog-response-data",
+ ad,
+ g_free);
}
return ad;
response_id = GTK_RESPONSE_NONE;
- ad = get_response_data (widget);
+ ad = get_response_data (widget, TRUE);
g_assert (ad != NULL);
gtk_dialog_response (dialog, response_id);
}
+
/**
* gtk_dialog_add_action_widget:
* @dialog: a #GtkDialog
* <literal>action_area</literal> field of the #GtkDialog struct.
**/
void
-gtk_dialog_add_action_widget (GtkDialog *dialog,
- GtkWidget *child,
- gint response_id)
+gtk_dialog_add_action_widget (GtkDialog *dialog,
+ GtkWidget *child,
+ gint response_id)
{
ResponseData *ad;
gint signal_id = 0;
g_return_if_fail (GTK_IS_DIALOG (dialog));
g_return_if_fail (GTK_IS_WIDGET (child));
- ad = get_response_data (child);
+ ad = get_response_data (child, TRUE);
ad->response_id = response_id;
if (GTK_IS_BUTTON (child))
- {
- signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON);
- }
+ signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON);
else
signal_id = GTK_WIDGET_GET_CLASS (child)->activate_signal != 0;
if (signal_id)
{
- const gchar* name = gtk_signal_name (signal_id);
-
- gtk_signal_connect_while_alive (GTK_OBJECT (child),
- name,
- GTK_SIGNAL_FUNC (action_widget_activated),
- dialog,
- GTK_OBJECT (dialog));
+ GClosure *closure;
+
+ closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated),
+ G_OBJECT (dialog));
+ g_signal_connect_closure_by_id (child,
+ signal_id,
+ 0,
+ closure,
+ FALSE);
}
else
g_warning ("Only 'activatable' widgets can be packed into the action area of a GtkDialog");
}
static void
-gtk_dialog_add_buttons_valist(GtkDialog *dialog,
- const gchar *first_button_text,
- va_list args)
+gtk_dialog_add_buttons_valist (GtkDialog *dialog,
+ const gchar *first_button_text,
+ va_list args)
{
const gchar* text;
gint response_id;
"gtk-dialog-response-data");
if (rd && rd->response_id == response_id)
- {
- gtk_widget_grab_default (widget);
-
- if (!GTK_WINDOW (dialog)->focus_widget)
- gtk_widget_grab_focus (widget);
- }
+ gtk_widget_grab_default (widget);
tmp_list = g_list_next (tmp_list);
}
gtk_dialog_set_has_separator (GtkDialog *dialog,
gboolean setting)
{
+ GtkDialogPrivate *priv;
+
g_return_if_fail (GTK_IS_DIALOG (dialog));
+ priv = GET_PRIVATE (dialog);
+
/* this might fail if we get called before _init() somehow */
g_assert (dialog->vbox != NULL);
+
+ if (priv->ignore_separator)
+ {
+ g_warning ("Ignoring the separator setting");
+ return;
+ }
if (setting && dialog->separator == NULL)
{
{
g_return_if_fail (GTK_IS_DIALOG (dialog));
- gtk_signal_emit (GTK_OBJECT (dialog),
- dialog_signals[RESPONSE],
- response_id);
+ g_signal_emit (dialog,
+ dialog_signals[RESPONSE],
+ 0,
+ response_id);
}
typedef struct
* @dialog: a #GtkDialog
*
* Blocks in a recursive main loop until the @dialog either emits the
- * response signal, or is destroyed. If the dialog is destroyed,
- * gtk_dialog_run() returns #GTK_RESPONSE_NONE. Otherwise, it returns
- * the response ID from the "response" signal emission. Before
- * entering the recursive main loop, gtk_dialog_run() calls
+ * response signal, or is destroyed. If the dialog is destroyed during the call
+ * to gtk_dialog_run(), gtk_dialog_returns #GTK_RESPONSE_NONE.
+ * Otherwise, it returns the response ID from the "response" signal emission.
+ * Before entering the recursive main loop, gtk_dialog_run() calls
* gtk_widget_show() on the dialog for you. Note that you still
* need to show any children of the dialog yourself.
*
*
* Typical usage of this function might be:
* <informalexample><programlisting>
- * <!> gint result = gtk_dialog_run (GTK_DIALOG (dialog));
- * <!> switch (result)
- * <!> {
- * <!> case GTK_RESPONSE_ACCEPT:
- * <!> do_application_specific_something (<!-- -->);
- * <!> break;
- * <!> default:
- * <!> do_nothing_since_dialog_was_cancelled (<!-- -->);
- * <!> break;
- * <!> }
- * <!> gtk_widget_destroy (dialog);
+ * gint result = gtk_dialog_run (GTK_DIALOG (dialog));
+ * switch (result)
+ * {
+ * case GTK_RESPONSE_ACCEPT:
+ * do_application_specific_something (<!-- -->);
+ * break;
+ * default:
+ * do_nothing_since_dialog_was_cancelled (<!-- -->);
+ * break;
+ * }
+ * gtk_widget_destroy (dialog);
* </programlisting></informalexample>
*
+ * Note that even though the recursive main loop gives the effect of a
+ * modal dialog (it prevents the user from interacting with other
+ * windows while the dialog is run), callbacks such as timeouts,
+ * IO channel watches, DND drops, etc, <emphasis>will</emphasis> be
+ * triggered during a gtk_dialog_run() call.
+ *
* Return value: response ID
**/
gint
{
RunInfo ri = { NULL, GTK_RESPONSE_NONE, NULL };
gboolean was_modal;
- guint response_handler;
- guint unmap_handler;
- guint destroy_handler;
- guint delete_handler;
+ gulong response_handler;
+ gulong unmap_handler;
+ gulong destroy_handler;
+ gulong delete_handler;
g_return_val_if_fail (GTK_IS_DIALOG (dialog), -1);
- gtk_object_ref (GTK_OBJECT (dialog));
+ g_object_ref (dialog);
- if (!GTK_WIDGET_VISIBLE (dialog))
- gtk_widget_show (GTK_WIDGET (dialog));
-
was_modal = GTK_WINDOW (dialog)->modal;
if (!was_modal)
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+ if (!GTK_WIDGET_VISIBLE (dialog))
+ gtk_widget_show (GTK_WIDGET (dialog));
+
response_handler =
- gtk_signal_connect (GTK_OBJECT (dialog),
- "response",
- GTK_SIGNAL_FUNC (run_response_handler),
- &ri);
+ g_signal_connect (dialog,
+ "response",
+ G_CALLBACK (run_response_handler),
+ &ri);
unmap_handler =
- gtk_signal_connect (GTK_OBJECT (dialog),
- "unmap",
- GTK_SIGNAL_FUNC (run_unmap_handler),
- &ri);
+ g_signal_connect (dialog,
+ "unmap",
+ G_CALLBACK (run_unmap_handler),
+ &ri);
delete_handler =
- gtk_signal_connect (GTK_OBJECT (dialog),
- "delete_event",
- GTK_SIGNAL_FUNC (run_delete_handler),
- &ri);
+ g_signal_connect (dialog,
+ "delete_event",
+ G_CALLBACK (run_delete_handler),
+ &ri);
destroy_handler =
- gtk_signal_connect (GTK_OBJECT (dialog),
- "destroy",
- GTK_SIGNAL_FUNC (run_destroy_handler),
- &ri);
+ g_signal_connect (dialog,
+ "destroy",
+ G_CALLBACK (run_destroy_handler),
+ &ri);
- ri.loop = g_main_new (FALSE);
+ ri.loop = g_main_loop_new (NULL, FALSE);
GDK_THREADS_LEAVE ();
g_main_loop_run (ri.loop);
if (!was_modal)
gtk_window_set_modal (GTK_WINDOW(dialog), FALSE);
- gtk_signal_disconnect (GTK_OBJECT (dialog), response_handler);
- gtk_signal_disconnect (GTK_OBJECT (dialog), unmap_handler);
- gtk_signal_disconnect (GTK_OBJECT (dialog), delete_handler);
- gtk_signal_disconnect (GTK_OBJECT (dialog), destroy_handler);
+ g_signal_handler_disconnect (dialog, response_handler);
+ g_signal_handler_disconnect (dialog, unmap_handler);
+ g_signal_handler_disconnect (dialog, delete_handler);
+ g_signal_handler_disconnect (dialog, destroy_handler);
}
- gtk_object_unref (GTK_OBJECT (dialog));
+ g_object_unref (dialog);
return ri.response_id;
}
+
+void
+_gtk_dialog_set_ignore_separator (GtkDialog *dialog,
+ gboolean ignore_separator)
+{
+ GtkDialogPrivate *priv;
+
+ priv = GET_PRIVATE (dialog);
+ priv->ignore_separator = ignore_separator;
+}
+
+gint
+_gtk_dialog_get_response_for_widget (GtkDialog *dialog,
+ GtkWidget *widget)
+{
+ ResponseData *rd;
+
+ rd = get_response_data (widget, FALSE);
+ if (!rd)
+ return GTK_RESPONSE_NONE;
+ else
+ return rd->response_id;
+}
+
+/**
+ * gtk_alternative_dialog_button_order:
+ * @screen: a #GdkScreen, or %NULL to use the default screen
+ *
+ * Returns %TRUE if dialogs are expected to use an alternative
+ * button order on the screen @screen. See
+ * gtk_dialog_set_alternative_button_order() for more details
+ * about alternative button order.
+ *
+ * If you need to use this function, you should probably connect
+ * to the ::notify:gtk-alternative-button-order signal on the
+ * #GtkSettings object associated to @screen, in order to be
+ * notified if the button order setting changes.
+ *
+ * Returns: Whether the alternative button order should be used
+ *
+ * Since: 2.6
+ */
+gboolean
+gtk_alternative_dialog_button_order (GdkScreen *screen)
+{
+ GtkSettings *settings;
+ gboolean result;
+
+ if (screen)
+ settings = gtk_settings_get_for_screen (screen);
+ else
+ settings = gtk_settings_get_default ();
+
+ g_object_get (settings,
+ "gtk-alternative-button-order", &result, NULL);
+
+ return result;
+}
+
+static void
+gtk_dialog_set_alternative_button_order_valist (GtkDialog *dialog,
+ gint first_response_id,
+ va_list args)
+{
+ GtkWidget *child;
+ gint response_id;
+ gint position;
+
+ response_id = first_response_id;
+ position = 0;
+ while (response_id != -1)
+ {
+ /* reorder child with response_id to position */
+ child = dialog_find_button (dialog, response_id);
+ gtk_box_reorder_child (GTK_BOX (dialog->action_area), child, position);
+
+ response_id = va_arg (args, gint);
+ position++;
+ }
+}
+
+/**
+ * gtk_dialog_set_alternative_button_order:
+ * @dialog: a #GtkDialog
+ * @first_response_id: a response id used by one @dialog's buttons
+ * @Varargs: a list of more response ids of @dialog's buttons, terminated by -1
+ *
+ * Sets an alternative button order. If the gtk-alternative-button-order
+ * setting is set to %TRUE, the dialog buttons are reordered according to
+ * the order of the response ids passed to this function.
+ *
+ * By default, GTK+ dialogs use the button order advocated by the Gnome
+ * <ulink url="http://developer.gnome.org/projects/gup/hig/2.0/">Human
+ * Interface Guidelines</ulink> with the affirmative button at the far
+ * right, and the cancel button left of it. But the builtin GTK+ dialogs
+ * and #GtkMessageDialog<!-- -->s do provide an alternative button order,
+ * which is more suitable on some platforms, e.g. Windows.
+ *
+ * Use this function after adding all the buttons to your dialog, as the
+ * following example shows:
+ * <informalexample><programlisting>
+ * cancel_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ * GTK_STOCK_CANCEL,
+ * GTK_RESPONSE_CANCEL);
+ *
+ * ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ * GTK_STOCK_OK,
+ * GTK_RESPONSE_OK);
+ *
+ * gtk_widget_grab_default (ok_button);
+ *
+ * help_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ * GTK_STOCK_HELP,
+ * GTK_RESPONSE_HELP);
+ *
+ * gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ * GTK_RESPONSE_OK,
+ * GTK_RESPONSE_CANCEL,
+ * GTK_RESPONSE_HELP,
+ * -1);
+ * </programlisting></informalexample>
+ *
+ * Since: 2.6
+ */
+void
+gtk_dialog_set_alternative_button_order (GtkDialog *dialog,
+ gint first_response_id,
+ ...)
+{
+ GdkScreen *screen;
+ va_list args;
+
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (dialog));
+ if (!gtk_alternative_dialog_button_order (screen))
+ return;
+
+ va_start (args, first_response_id);
+
+ gtk_dialog_set_alternative_button_order_valist (dialog,
+ first_response_id,
+ args);
+ va_end (args);
+}
+/**
+ * gtk_dialog_set_alternative_button_order_from_array:
+ * @dialog: a #GtkDialog
+ * @n_params: the number of response ids in @new_order
+ * @new_order: an array of response ids of @dialog's buttons
+ *
+ * Sets an alternative button order. If the gtk-alternative-button-order
+ * setting is set to %TRUE, the dialog buttons are reordered according to
+ * the order of the response ids in @new_order.
+ *
+ * See gtk_dialog_set_alternative_button_order() for more information.
+ *
+ * This function is for use by language bindings.
+ *
+ * Since: 2.6
+ */
+void
+gtk_dialog_set_alternative_button_order_from_array (GtkDialog *dialog,
+ gint n_params,
+ gint *new_order)
+{
+ GdkScreen *screen;
+ GtkWidget *child;
+ gint position;
+
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+ g_return_if_fail (new_order != NULL);
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (dialog));
+ if (!gtk_alternative_dialog_button_order (screen))
+ return;
+
+ for (position = 0; position < n_params; position++)
+ {
+ /* reorder child with response_id to position */
+ child = dialog_find_button (dialog, new_order[position]);
+ gtk_box_reorder_child (GTK_BOX (dialog->action_area), child, position);
+ }
+}
+