Difference between revisions of "GUI Guidelines"

From GnuCash
Jump to: navigation, search
(Mnemonics and Accelerators: glade files; highlighting)
(Mnemonics and Accelerators: Rewrite)
Line 1: Line 1:
 
This page collects rules for the GUI. You should mind them while [[CodingStandard|coding]] or [[Translation|translating]].
 
This page collects rules for the GUI. You should mind them while [[CodingStandard|coding]] or [[Translation|translating]].
 
= Mnemonics and Accelerators =
 
= Mnemonics and Accelerators =
*'''Accelerators''' are keyboard "hot-keys" like ctrl-c for copy
+
 
*'''Mnemonics''' are part of the menu label, the underscore, so they would be included in the msgid.
+
Gtk+ provides two means of creating "hot-keys" for keyboard operation of menu items and controls: [https://developer.gnome.org/gtk3/unstable/gtk3-Keyboard-Accelerators.html Accelerators] and special labels called '''mnemonics'''.
** In glade files they have <code><property name="use_underline">True</property></code>.
+
 
== Possible Problems==
+
== Accelerators ==
from [https://lists.gnucash.org/logs/2018/01/04.html IRC]:
+
Accelerators are normally assigned only to menu items, but they can be assigned to any control using a [https://developer.gnome.org/gtk3/unstable/GtkAccelLabel.html GtkAccelLabel]. ''"Can" does '''not''' mean "should"!'' Pressing the character together with the configured modifiers calls whatever function is linked to the control. Accelerators can be over-ridden by users using [https://developer.gnome.org/gtk3/unstable/gtk3-Accelerator-Maps.html an accelerator map]. Accelerators can be set in GtkBuilder/Glade files using the <code>accelerator</code> element.
* First off, mnemonics work differently for different widgets. e.g. on buttons they work like accelerators: <alt>F operates the button with that mnemonic--as long as there isn't an accelerator set to <alt>F because accelerators are handled first by gtkevent. Menuitem mnemonics work without a modifier key if one has the containing menu open.
+
 
* Mnemonics can be attached to any widget via gtk_label_new_with_mnemonic() and gtk_label_set_mnemonic_widget(), so it would be easy to go crazy and have them everywhere.
+
MacOS Note: In most cases MacOS prefers the &lt;command&gt; key to the &lt;control&gt; key as a modifier. Gtk provides a macro <code>GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR</code> that selects the correct modifier depending on OS. It should be used in most cases rather than <code>GDK_CONTROL_MASK</code>. As noted below under [[#Mnemonics|Mnemonics]] MacOS uses the &lt;alt&gt; modifier key to extend the keyboard, so it should be used only with another not-&lt;shift&gt; modifier key in accelerators. Note that on MacOS GDK_MOD2_MASK is the &lt;command&gt; key while on X11 it's &lt;numlock&gt; so either one must conditionally set accelerator modifiers (not possible in Glade), rely on an accelerator map to get a useable accelerator set, or restrict the modifiers to &lt;control&gt;&lt;alt&gt; and <code.GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR</code>. Unfortunately [https://glade.gnome.org/ Glade] does not support GdkModifierIntent and Gtk+ has supported it in GtkBuilder files only since 3.20 so it can be used only in accelerators defined in code.
* But we also need to be careful to ensure that they're turned off when focus is inside an edit because <alt> is used to ''extend the keyboard'' '''on Macs'''. For example to type ö I use <alt>u followed by o. We've had several bugs on Gramps where some mnemonic grabbed the <alt>u and prevented users from typing umlauts.
+
 
 +
 
 +
==== GtkShortcuts ====
 +
The <code>GtkShortcutsWindow</code> is a convenient way to display all of GnuCash's accelerators to the user. Unfortunately it wasn't introduced until Gtk+-3.20.0 and we want to support Gtk+-3.10 and later, so don't implement it.
 +
== Mnemonics ==
 +
 
 +
Mnemonics can be set on [https://developer.gnome.org/gtk3/unstable/GtkMenuItem.html#gtk-menu-item-new-with-mnemonic menu items] as well as [https://developer.gnome.org/gtk3/unstable/GtkButton.html#gtk-button-new-with-mnemonic buttons] or indeed any control by [https://developer.gnome.org/gtk3/unstable/GtkLabel.html#gtk-label-set-mnemonic-widget attaching] it to the [https://developer.gnome.org/gtk3/unstable/GtkLabel.html#gtk-label-new-with-mnemonic relevant label]. ''However'' one should be aware that menu-item mnemonics work quite differently: Mnemonics on controls operate like accelerators: Holding &lt;alt&gt; will reveal underlines on the mnemonic characters for the focused window or dialog and pressing an underlined character will operate the respective control. If the focused window has a menu bar associated with it the menu bar will be revealed if it's hidden and the mnemonics will be shown; pressing the mnemonic for a menu bar item will open that menu. At this point the &lt;alt&gt; can be released and the menu navigated by pressing the mnemonic keys alone. In addition to the linked functions, mnemonics can be set in GtkBuilder/Glade files with the <code>use_underline</code> and (on GtkLabels, not needed for GtkButtons) <code>mnemonic_widget</code> properties.
 +
 
 +
Mnemonics have two problems on Macs: First, they don't work on the menu. Keyboard menu navigation is accomplished by pressing &lt;ctrl&gt;F2 (don't forget to also press &lt;fn&gt; on keyboards that use one unless you've flipped the &lt;fn&gt; key behavior in Keyboard Preferences) to activate the menubar and then navigating with the cursor keys. Second, MacOS used the &lt;alt&gt; key to extend the keyboard; for example on a US keyboard one would type &lt;alt&gt;e e to get é or &lt;alt&gt;o to get ø. Setting a mnemonic will grab the event before the text control gets it and prevent that character from being typed.
 +
 
 +
Note that when one creates a mnemonic with an underscore the underscore becomes part of the label string that is a msgid for translation, so the same label with different mnemonics will result in multiple strings for translation. This is a good thing because it allows translators to select appropriate mnemonics for their languages.

Revision as of 20:26, 21 January 2018

This page collects rules for the GUI. You should mind them while coding or translating.

Mnemonics and Accelerators

Gtk+ provides two means of creating "hot-keys" for keyboard operation of menu items and controls: Accelerators and special labels called mnemonics.

Accelerators

Accelerators are normally assigned only to menu items, but they can be assigned to any control using a GtkAccelLabel. "Can" does not mean "should"! Pressing the character together with the configured modifiers calls whatever function is linked to the control. Accelerators can be over-ridden by users using an accelerator map. Accelerators can be set in GtkBuilder/Glade files using the accelerator element.

MacOS Note: In most cases MacOS prefers the <command> key to the <control> key as a modifier. Gtk provides a macro GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR that selects the correct modifier depending on OS. It should be used in most cases rather than GDK_CONTROL_MASK. As noted below under Mnemonics MacOS uses the <alt> modifier key to extend the keyboard, so it should be used only with another not-<shift> modifier key in accelerators. Note that on MacOS GDK_MOD2_MASK is the <command> key while on X11 it's <numlock> so either one must conditionally set accelerator modifiers (not possible in Glade), rely on an accelerator map to get a useable accelerator set, or restrict the modifiers to <control><alt> and <code.GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR</code>. Unfortunately Glade does not support GdkModifierIntent and Gtk+ has supported it in GtkBuilder files only since 3.20 so it can be used only in accelerators defined in code.


GtkShortcuts

The GtkShortcutsWindow is a convenient way to display all of GnuCash's accelerators to the user. Unfortunately it wasn't introduced until Gtk+-3.20.0 and we want to support Gtk+-3.10 and later, so don't implement it.

Mnemonics

Mnemonics can be set on menu items as well as buttons or indeed any control by attaching it to the relevant label. However one should be aware that menu-item mnemonics work quite differently: Mnemonics on controls operate like accelerators: Holding <alt> will reveal underlines on the mnemonic characters for the focused window or dialog and pressing an underlined character will operate the respective control. If the focused window has a menu bar associated with it the menu bar will be revealed if it's hidden and the mnemonics will be shown; pressing the mnemonic for a menu bar item will open that menu. At this point the <alt> can be released and the menu navigated by pressing the mnemonic keys alone. In addition to the linked functions, mnemonics can be set in GtkBuilder/Glade files with the use_underline and (on GtkLabels, not needed for GtkButtons) mnemonic_widget properties.

Mnemonics have two problems on Macs: First, they don't work on the menu. Keyboard menu navigation is accomplished by pressing <ctrl>F2 (don't forget to also press <fn> on keyboards that use one unless you've flipped the <fn> key behavior in Keyboard Preferences) to activate the menubar and then navigating with the cursor keys. Second, MacOS used the <alt> key to extend the keyboard; for example on a US keyboard one would type <alt>e e to get é or <alt>o to get ø. Setting a mnemonic will grab the event before the text control gets it and prevent that character from being typed.

Note that when one creates a mnemonic with an underscore the underscore becomes part of the label string that is a msgid for translation, so the same label with different mnemonics will result in multiple strings for translation. This is a good thing because it allows translators to select appropriate mnemonics for their languages.