summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2018-04-13 15:31:44 +0100
committerCaolán McNamara <caolanm@redhat.com>2018-04-14 01:52:44 +0200
commit9c8a6a4396ebbe8ecb15591cc291c388c82c8ed6 (patch)
tree0dba376d730f88542efb12dd4f13bc83360d463e
parent22d2dbeaa6667e4c66978fb3bad11f835f569ef0 (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.hxx5
-rw-r--r--vcl/source/window/mnemonic.cxx13
-rw-r--r--vcl/unx/gtk3/gtk3gtkinst.cxx184
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