Re: accelerated buttons



On Tue, Jul 11, 2000 at 12:20:03AM +0200, xander wrote:
> Are accelerated buttons available? E.g. like with GtkItemFactory
> "_OK" & "_Cancel" with gtk_label_parse_uline stuff.

Yes.

It's a bit of a pain in GTK+ to add that type of accelerator (they're
called "mnemonics" in Windows and Motif, to distinguish them from
"accelerators" not tied to a letter of the label, e.g. Ctrl+C for
"copy", although Qt calls 'em both "accelerators" as GTK+ does).

It appears to be:

	easier in Windows (you create the button with the normal calls;
	a single "&" before a letter or digit means "that letter is the
	digit or mnemonic");

	easier in Qt (you just create the button with the normal calls;
	the label uses Windows-style syntax for this, and "&&" is an
	escape meaning "insert an ampersand in the label here" - I don't
	know whether Windows does that);

	not quite as much easier in Motif (you have to set the
	XmNmnemonic resource for the widget to the mnemonic letter - the
	first occurrence of that letter in the label is underlined if it
	appears, otherwise it's still an Alt+<letter> mnemonic but
	there's no visual indication of its existence, but you don't
	have to monkey around with accelerator groups by hand).

The way I did it in Ethereal was to add some routines to create radio
and check buttons with labels including "_" for mnemonics (and, as an
experiment to make sure it worked with "regular" buttons, I added a
routine for that as well), which take a "GtkAccelGroup *" as an
argument, and added an accelerator group to the window in question.

I.e., after creating the window:

  GtkWidget *dialog_window;

	...

  dialog_window = gtk_window_new(GTK_WINDOW_DIALOG);

	...
  
I do:

  GtkAccelGroup *accel_group;

	...

  accel_group = gtk_accel_group_new();
  gtk_window_add_accel_group(GTK_WINDOW(top_level_window), accel_group);

and then create the buttons with the
"dlg_radio_button_new_with_label_with_mnemonic()",
"dlg_check_button_new_with_label_with_mnemonic()", and
"dlg_button_new_with_label_with_mnemonic()" routines (yes, the names
suck) that I cooked up:

typedef struct {
	GtkWidget *button;
	GtkAccelGroup *accel_group;
} fix_label_args_t;

static void
dlg_fix_label_callback(GtkWidget *label_widget, gpointer data)
{
  fix_label_args_t *args = data;
  gchar *label;
  guint accel_key;

  gtk_label_get(GTK_LABEL(label_widget), &label);
  accel_key = gtk_label_parse_uline(GTK_LABEL(label_widget), label);
  if (accel_key != GDK_VoidSymbol) {
    /* Yes, we have a mnemonic. */
    gtk_widget_add_accelerator(args->button, "clicked", args->accel_group,
				accel_key, 0, GTK_ACCEL_LOCKED);
    gtk_widget_add_accelerator(args->button, "clicked", args->accel_group,
				accel_key, GDK_MOD1_MASK, GTK_ACCEL_LOCKED);
  }
}

static void
dlg_fix_button_label(GtkWidget *button, GtkAccelGroup *accel_group)
{
  fix_label_args_t args;

  args.button = button;
  args.accel_group = accel_group;
  gtk_container_foreach(GTK_CONTAINER(button), dlg_fix_label_callback, &args);
}

GtkWidget *
dlg_radio_button_new_with_label_with_mnemonic(GSList *group,
		const gchar *label, GtkAccelGroup *accel_group)
{
  GtkWidget *radio_button;

  radio_button = gtk_radio_button_new_with_label (group, label);
  dlg_fix_button_label(radio_button, accel_group);
  return radio_button;
}

GtkWidget *
dlg_check_button_new_with_label_with_mnemonic(const gchar *label,
			GtkAccelGroup *accel_group)
{
  GtkWidget *check_button;
	         
  check_button = gtk_check_button_new_with_label (label);
  dlg_fix_button_label(check_button, accel_group);
  return check_button;
}

GtkWidget *
dlg_button_new_with_label_with_mnemonic(const gchar *label,
			GtkAccelGroup *accel_group)
{
  GtkWidget *button;
	         
  button = gtk_button_new_with_label (label);
  dlg_fix_button_label(button, accel_group);
  return button;
}





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]