From b8f4ea365c098880bfa5ccffb3a5a33daf13b1b4 Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Fri, 21 Dec 2018 13:02:25 -0700 Subject: [PATCH] Add tooltips with keyboard shortcuts --- src/Granite/Accels.vala | 136 +++++++++++++++++++++++ src/{Widgets => Granite}/ModeSwitch.vala | 4 +- src/meson.build | 3 +- src/window.vala | 9 +- 4 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 src/Granite/Accels.vala rename src/{Widgets => Granite}/ModeSwitch.vala (100%) diff --git a/src/Granite/Accels.vala b/src/Granite/Accels.vala new file mode 100644 index 0000000..33eb62a --- /dev/null +++ b/src/Granite/Accels.vala @@ -0,0 +1,136 @@ +// From https://github.com/elementary/granite/blob/621f2669f6c8940fe32ac9817ddca92e97d27ae0/lib/Widgets/Utils.vala#L79-L192 + +/* + * Copyright (C) 2012-2017 Granite Developers + * + * This program or library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +namespace Granite { + +/** + * Converts a {@link Gtk.accelerator_parse} style accel string to a human-readable string. + * + * @param accel an accelerator label like “a” or “Right” + * + * @return a human-readable string like "Ctrl + A" or "⌘ + →" + */ +public static string accel_to_string (string accel) { + uint accel_key; + Gdk.ModifierType accel_mods; + Gtk.accelerator_parse (accel, out accel_key, out accel_mods); + + string[] arr = {}; + if (Gdk.ModifierType.SUPER_MASK in accel_mods) { + arr += "⌘"; + } + + if (Gdk.ModifierType.SHIFT_MASK in accel_mods) { + arr += _("Shift"); + } + + if (Gdk.ModifierType.CONTROL_MASK in accel_mods) { + arr += _("Ctrl"); + } + + if (Gdk.ModifierType.MOD1_MASK in accel_mods) { + arr += _("Alt"); + } + + switch (accel_key) { + case Gdk.Key.Up: + arr += "↑"; + break; + case Gdk.Key.Down: + arr += "↓"; + break; + case Gdk.Key.Left: + arr += "←"; + break; + case Gdk.Key.Right: + arr += "→"; + break; + case Gdk.Key.minus: + case Gdk.Key.KP_Subtract: + ///TRANSLATORS: This is a non-symbol representation of the "-" key + arr += _("Minus"); + break; + case Gdk.Key.KP_Add: + case Gdk.Key.plus: + ///TRANSLATORS: This is a non-symbol representation of the "+" key + arr += _("Plus"); + break; + case Gdk.Key.KP_Enter: + case Gdk.Key.Return: + arr += _("Enter"); + break; + default: + arr += Gtk.accelerator_get_label (accel_key, 0); + break; + } + + return string.joinv (" + ", arr); +} + +/** + * Takes a description and an array of accels and returns {@link Pango} markup for use in a {@link Gtk.Tooltip}. This method uses {@link Granite.accel_to_string}. + * + * Example: + * + * Description + * Shortcut 1, Shortcut 2 + * + * @param a string array of accelerator labels like {"a", "Right"} + * + * @param description a standard tooltip text string + * + * @return {@link Pango} markup with the description label on one line and a list of human-readable accels on a new line + */ +public static string markup_accel_tooltip (string[]? accels, string? description = null) { + string[] parts = {}; + if (description != null && description != "") { + parts += description; + } + + if (accels != null && accels.length > 0) { + string[] unique_accels = {}; + + for (int i = 0; i < accels.length; i++) { + if (accels[i] == "") { + continue; + } + + var accel_string = accel_to_string (accels[i]); + if (!(accel_string in unique_accels)) { + unique_accels += accel_string; + } + } + + if (unique_accels.length > 0) { + ///TRANSLATORS: This is a delimiter that separates two keyboard shortcut labels like "⌘ + →, Control + A" + var accel_label = string.joinv (_(", "), unique_accels); + + var accel_markup = """%s""".printf (accel_label); + + parts += accel_markup; + } + } + + return string.joinv ("\n", parts); +} + +} + diff --git a/src/Widgets/ModeSwitch.vala b/src/Granite/ModeSwitch.vala similarity index 100% rename from src/Widgets/ModeSwitch.vala rename to src/Granite/ModeSwitch.vala index 98d99f2..bb1c720 100644 --- a/src/Widgets/ModeSwitch.vala +++ b/src/Granite/ModeSwitch.vala @@ -1,3 +1,5 @@ +// From https://github.com/elementary/granite/blob/2066b377226cf327cb2d5399b6b40a2d36d47b11/lib/Widgets/ModeSwitch.vala + /* * Copyright (c) 2018 elementary, Inc. (https://elementary.io) * @@ -17,8 +19,6 @@ * Boston, MA 02110-1301 USA */ -// From https://github.com/elementary/granite/blob/2066b377226cf327cb2d5399b6b40a2d36d47b11/lib/Widgets/ModeSwitch.vala - /** * ModeSwitch is a selection control for choosing between two options that can be described with an icon. * diff --git a/src/meson.build b/src/meson.build index 146b85c..54fb599 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,7 +1,8 @@ executable('writeas-gtk', 'application.vala', 'window.vala', - 'Widgets/ModeSwitch.vala', + 'Granite/Accels.vala', + 'Granite/ModeSwitch.vala', c_args: ['-include', 'config.h'], link_args: '-lm', diff --git a/src/window.vala b/src/window.vala index 69635f9..3f7c66f 100644 --- a/src/window.vala +++ b/src/window.vala @@ -137,7 +137,10 @@ public class WriteAs.MainWindow : Gtk.ApplicationWindow { var publish_button = new Gtk.Button.from_icon_name("document-send", Gtk.IconSize.SMALL_TOOLBAR); - publish_button.tooltip_text = _("Publish to Write.as on the web"); + publish_button.tooltip_markup = Granite.markup_accel_tooltip ( + {"Return"}, + _("Publish to Write.as on the web") + ); publish_button.clicked.connect(() => { canvas.buffer.text += "\n\n" + publish(); @@ -148,6 +151,10 @@ public class WriteAs.MainWindow : Gtk.ApplicationWindow { darkmode_switch = new Granite.ModeSwitch.from_icon_name ("display-brightness-symbolic", "weather-clear-night-symbolic"); darkmode_switch.primary_icon_tooltip_text = ("Light theme"); darkmode_switch.secondary_icon_tooltip_text = ("Dark theme"); + darkmode_switch.tooltip_markup = Granite.markup_accel_tooltip ( + {"T"}, + _("Toggle light/dark theme") + ); darkmode_switch.valign = Gtk.Align.CENTER; var settings = Gtk.Settings.get_default(); darkmode_switch.notify["active"].connect(() => {