diff options
author | Caolán McNamara <caolanm@redhat.com> | 2018-04-13 15:31:44 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2018-04-14 01:52:44 +0200 |
commit | 9c8a6a4396ebbe8ecb15591cc291c388c82c8ed6 (patch) | |
tree | 0dba376d730f88542efb12dd4f13bc83360d463e | |
parent | 22d2dbeaa6667e4c66978fb3bad11f835f569ef0 (diff) |
gtk3: generate missing mnemonics
Change-Id: Ib0e94b8484dabb7e859c53aeb0e4adf75727fcd6
Reviewed-on: https://gerrit.libreoffice.org/52839
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r-- | include/vcl/mnemonic.hxx | 5 | ||||
-rw-r--r-- | vcl/source/window/mnemonic.cxx | 13 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkinst.cxx | 184 |
3 files changed, 139 insertions, 63 deletions
diff --git a/include/vcl/mnemonic.hxx b/include/vcl/mnemonic.hxx index bf2591aff8f4..f7db3a3095fb 100644 --- a/include/vcl/mnemonic.hxx +++ b/include/vcl/mnemonic.hxx @@ -51,15 +51,16 @@ class VCL_DLLPUBLIC MnemonicGenerator { + sal_Unicode m_cMnemonic; // 0 == Mnemonic; >0 == count of characters sal_uInt8 maMnemonics[MAX_MNEMONICS]; css::uno::Reference< css::i18n::XCharacterClassification > mxCharClass; SAL_DLLPRIVATE static sal_uInt16 ImplGetMnemonicIndex( sal_Unicode c ); - SAL_DLLPRIVATE static sal_Unicode ImplFindMnemonic( const OUString& rKey ); + SAL_DLLPRIVATE sal_Unicode ImplFindMnemonic( const OUString& rKey ); public: - MnemonicGenerator(); + MnemonicGenerator(sal_Unicode cMnemonic = MNEMONIC_CHAR); void RegisterMnemonic( const OUString& rKey ); OUString CreateMnemonic( const OUString& rKey ); diff --git a/vcl/source/window/mnemonic.cxx b/vcl/source/window/mnemonic.cxx index fe26cd14c152..43db6dea1493 100644 --- a/vcl/source/window/mnemonic.cxx +++ b/vcl/source/window/mnemonic.cxx @@ -28,7 +28,8 @@ using namespace ::com::sun::star; -MnemonicGenerator::MnemonicGenerator() +MnemonicGenerator::MnemonicGenerator(sal_Unicode cMnemonic) + : m_cMnemonic(cMnemonic) { memset( maMnemonics, 1, sizeof( maMnemonics ) ); } @@ -59,10 +60,10 @@ sal_uInt16 MnemonicGenerator::ImplGetMnemonicIndex( sal_Unicode c ) sal_Unicode MnemonicGenerator::ImplFindMnemonic( const OUString& rKey ) { sal_Int32 nIndex = 0; - while ( (nIndex = rKey.indexOf( MNEMONIC_CHAR, nIndex )) != -1 ) + while ( (nIndex = rKey.indexOf( m_cMnemonic, nIndex )) != -1 ) { sal_Unicode cMnemonic = rKey[ nIndex+1 ]; - if ( cMnemonic != MNEMONIC_CHAR ) + if ( cMnemonic != m_cMnemonic ) return cMnemonic; nIndex += 2; } @@ -187,7 +188,7 @@ OUString MnemonicGenerator::CreateMnemonic( const OUString& _rKey ) if ( maMnemonics[nMnemonicIndex] ) { maMnemonics[nMnemonicIndex] = 0; - rKey = rKey.replaceAt( nIndex, 0, OUString(MNEMONIC_CHAR) ); + rKey = rKey.replaceAt( nIndex, 0, OUString(m_cMnemonic) ); bChanged = true; break; } @@ -239,7 +240,7 @@ OUString MnemonicGenerator::CreateMnemonic( const OUString& _rKey ) if ( nBestCount != 0xFFFF ) { maMnemonics[nBestMnemonicIndex] = 0; - rKey = rKey.replaceAt( nBestIndex, 0, OUString(MNEMONIC_CHAR) ); + rKey = rKey.replaceAt( nBestIndex, 0, OUString(m_cMnemonic) ); bChanged = true; } } @@ -260,7 +261,7 @@ OUString MnemonicGenerator::CreateMnemonic( const OUString& _rKey ) { maMnemonics[nMnemonicIndex] = 0; OUString aStr = OUStringBuffer(). - append('(').append(MNEMONIC_CHAR).append(sal_Unicode(rtl::toAsciiUpperCase(c))). + append('(').append(m_cMnemonic).append(sal_Unicode(rtl::toAsciiUpperCase(c))). append(')').makeStringAndClear(); nIndex = rKey.getLength(); if( nIndex >= 2 ) diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 957b58fcc083..9425d93fa63e 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -31,6 +31,7 @@ #include <rtl/bootstrap.hxx> #include <tools/fract.hxx> #include <tools/stream.hxx> +#include <vcl/mnemonic.hxx> #include <vcl/pngwrite.hxx> #include <vcl/weld.hxx> @@ -2343,6 +2344,31 @@ public: } }; +namespace +{ + OUString get_label(GtkLabel* pLabel) + { + const gchar* pStr = gtk_label_get_label(pLabel); + return OUString(pStr, pStr ? strlen(pStr) : 0, RTL_TEXTENCODING_UTF8); + } + + void set_label(GtkLabel* pLabel, const OUString& rText) + { + gtk_label_set_label(pLabel, MapToGtkAccelerator(rText).getStr()); + } + + OUString get_label(GtkButton* pButton) + { + const gchar* pStr = gtk_button_get_label(pButton); + return OUString(pStr, pStr ? strlen(pStr) : 0, RTL_TEXTENCODING_UTF8); + } + + void set_label(GtkButton* pButton, const OUString& rText) + { + gtk_button_set_label(pButton, MapToGtkAccelerator(rText).getStr()); + } +} + class GtkInstanceButton : public GtkInstanceContainer, public virtual weld::Button { private: @@ -2367,13 +2393,12 @@ public: virtual void set_label(const OUString& rText) override { - gtk_button_set_label(m_pButton, MapToGtkAccelerator(rText).getStr()); + ::set_label(m_pButton, rText); } virtual OUString get_label() const override { - const gchar* pStr = gtk_button_get_label(m_pButton); - return OUString(pStr, pStr ? strlen(pStr) : 0, RTL_TEXTENCODING_UTF8); + return ::get_label(m_pButton); } virtual void clicked() override @@ -3101,13 +3126,12 @@ public: virtual void set_label(const OUString& rText) override { - gtk_label_set_label(m_pLabel, MapToGtkAccelerator(rText).getStr()); + ::set_label(m_pLabel, rText); } virtual OUString get_label() const override { - const char* pLabel = gtk_label_get_label(m_pLabel); - return OUString(pLabel, strlen(pLabel), RTL_TEXTENCODING_UTF8); + return ::get_label(m_pLabel); } }; @@ -3868,13 +3892,52 @@ namespace return false; } +} - void postprocess(gpointer data, gpointer user_data) +namespace +{ + +AtkObject* (*default_drawing_area_get_accessible)(GtkWidget *widget); + +AtkObject* drawing_area_get_accessibity(GtkWidget *pWidget) +{ + void* pData = g_object_get_data(G_OBJECT(pWidget), "g-lo-GtkInstanceDrawingArea"); + GtkInstanceDrawingArea* pDrawingArea = static_cast<GtkInstanceDrawingArea*>(pData); + AtkObject *pAtkObj = pDrawingArea ? pDrawingArea->GetAtkObject() : nullptr; + if (pAtkObj) + return pAtkObj; + return default_drawing_area_get_accessible(pWidget); +} + +void ensure_intercept_drawing_area_accessibility() +{ + static bool bDone; + if (!bDone) + { + gpointer pClass = g_type_class_ref(GTK_TYPE_DRAWING_AREA); + GtkWidgetClass* pWidgetClass = GTK_WIDGET_CLASS(pClass); + default_drawing_area_get_accessible = pWidgetClass->get_accessible; + pWidgetClass->get_accessible = drawing_area_get_accessibity; + g_type_class_unref(pClass); + bDone = true; + } +} + +} + +class GtkInstanceBuilder : public weld::Builder +{ +private: + OUString m_sHelpRoot; + OString m_aUtf8HelpRoot; + GtkBuilder* m_pBuilder; + GSList* m_pObjectList; + GtkWidget* m_pParentWidget; + std::vector<GtkButton*> m_aMnemonicButtons; + std::vector<GtkLabel*> m_aMnemonicLabels; + + void postprocess_widget(GtkWidget* pWidget) { - GObject* pObject = static_cast<GObject*>(data); - if (!GTK_IS_WIDGET(pObject)) - return; - OString* pHelpRoot = static_cast<OString*>(user_data); //fixup icons //wanted: better way to do this, e.g. make gtk use gio for //loading from a filename and provide gio protocol handler @@ -3882,9 +3945,9 @@ namespace // //unpack the images and keep them as dirs and just //add the paths to the gtk icon theme dir - if (GTK_IS_IMAGE(pObject)) + if (GTK_IS_IMAGE(pWidget)) { - GtkImage* pImage = GTK_IMAGE(pObject); + GtkImage* pImage = GTK_IMAGE(pWidget); const gchar* icon_name; gtk_image_get_icon_name(pImage, &icon_name, nullptr); GtkIconSize size; @@ -3909,61 +3972,41 @@ namespace } } //set helpids - GtkWidget* pWidget = GTK_WIDGET(pObject); const gchar* pStr = gtk_buildable_get_name(GTK_BUILDABLE(pWidget)); size_t nLen = pStr ? strlen(pStr) : 0; if (!nLen) return; - OString sHelpId = *pHelpRoot + OString(pStr, nLen); + OString sHelpId = m_aUtf8HelpRoot + OString(pStr, nLen); set_help_id(pWidget, sHelpId); //hook up for extended help const ImplSVData* pSVData = ImplGetSVData(); if (pSVData->maHelpData.mbBalloonHelp && !GTK_IS_DIALOG(pWidget)) { gtk_widget_set_has_tooltip(pWidget, true); - g_signal_connect(pObject, "query-tooltip", G_CALLBACK(signalTooltipQuery), nullptr); + g_signal_connect(pWidget, "query-tooltip", G_CALLBACK(signalTooltipQuery), nullptr); } - } -} -namespace -{ - -AtkObject* (*default_drawing_area_get_accessible)(GtkWidget *widget); - -AtkObject* drawing_area_get_accessibity(GtkWidget *pWidget) -{ - void* pData = g_object_get_data(G_OBJECT(pWidget), "g-lo-GtkInstanceDrawingArea"); - GtkInstanceDrawingArea* pDrawingArea = static_cast<GtkInstanceDrawingArea*>(pData); - AtkObject *pAtkObj = pDrawingArea ? pDrawingArea->GetAtkObject() : nullptr; - if (pAtkObj) - return pAtkObj; - return default_drawing_area_get_accessible(pWidget); -} + //missing mnemonics + if (GTK_IS_BUTTON(pWidget)) + { + if (gtk_button_get_use_underline(GTK_BUTTON(pWidget))) + m_aMnemonicButtons.push_back(GTK_BUTTON(pWidget)); + } + else if (GTK_IS_LABEL(pWidget)) + { + if (gtk_label_get_use_underline(GTK_LABEL(pWidget))) + m_aMnemonicLabels.push_back(GTK_LABEL(pWidget)); + } + } -void ensure_intercept_drawing_area_accessibility() -{ - static bool bDone; - if (!bDone) + static void postprocess(gpointer data, gpointer user_data) { - gpointer pClass = g_type_class_ref(GTK_TYPE_DRAWING_AREA); - GtkWidgetClass* pWidgetClass = GTK_WIDGET_CLASS(pClass); - default_drawing_area_get_accessible = pWidgetClass->get_accessible; - pWidgetClass->get_accessible = drawing_area_get_accessibity; - g_type_class_unref(pClass); - bDone = true; + GObject* pObject = static_cast<GObject*>(data); + if (!GTK_IS_WIDGET(pObject)) + return; + GtkInstanceBuilder* pThis = static_cast<GtkInstanceBuilder*>(user_data); + pThis->postprocess_widget(GTK_WIDGET(pObject)); } -} - -} - -class GtkInstanceBuilder : public weld::Builder -{ -private: - OUString m_sHelpRoot; - GtkBuilder* m_pBuilder; - GSList* m_pObjectList; - GtkWidget* m_pParentWidget; public: GtkInstanceBuilder(GtkWidget* pParent, const OUString& rUIRoot, const OUString& rUIFile) : weld::Builder(rUIFile) @@ -3981,10 +4024,41 @@ public: if (nIdx != -1) m_sHelpRoot = m_sHelpRoot.copy(0, nIdx); m_sHelpRoot = m_sHelpRoot + OUString('/'); + m_aUtf8HelpRoot = OUStringToOString(m_sHelpRoot, RTL_TEXTENCODING_UTF8); m_pObjectList = gtk_builder_get_objects(m_pBuilder); - OString aUtf8HelpRoot(OUStringToOString(m_sHelpRoot, RTL_TEXTENCODING_UTF8)); - g_slist_foreach(m_pObjectList, postprocess, &aUtf8HelpRoot); + g_slist_foreach(m_pObjectList, postprocess, this); + + GenerateMissingMnemonics(); + } + + void GenerateMissingMnemonics() + { + MnemonicGenerator aMnemonicGenerator('_'); + for (const auto a : m_aMnemonicButtons) + aMnemonicGenerator.RegisterMnemonic(get_label(a)); + for (const auto a : m_aMnemonicLabels) + aMnemonicGenerator.RegisterMnemonic(get_label(a)); + + for (const auto a : m_aMnemonicButtons) + { + OUString aLabel(get_label(a)); + OUString aNewLabel = aMnemonicGenerator.CreateMnemonic(aLabel); + if (aLabel == aNewLabel) + continue; + set_label(a, aNewLabel); + } + for (const auto a : m_aMnemonicLabels) + { + OUString aLabel(get_label(a)); + OUString aNewLabel = aMnemonicGenerator.CreateMnemonic(aLabel); + if (aLabel == aNewLabel) + continue; + set_label(a, aNewLabel); + } + + m_aMnemonicLabels.clear(); + m_aMnemonicButtons.clear(); } virtual ~GtkInstanceBuilder() override |