tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / framework / source / uielement / langselectionstatusbarcontroller.cxx
blob03ceaa3d47d834fa351010b84f779221dad63fa7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <classes/fwkresid.hxx>
21 #include <services.h>
22 #include <strings.hrc>
23 #include <vcl/svapp.hxx>
25 #include <cppuhelper/supportsservice.hxx>
26 #include <com/sun/star/awt/PopupMenu.hpp>
27 #include <com/sun/star/awt/PopupMenuDirection.hpp>
28 #include <svtools/langtab.hxx>
29 #include <svtools/statusbarcontroller.hxx>
30 #include <sal/types.h>
31 #include <sal/log.hxx>
32 #include <com/sun/star/document/XDocumentLanguages.hpp>
33 #include <com/sun/star/lang/XServiceInfo.hpp>
34 #include <com/sun/star/i18n/ScriptType.hpp>
35 #include <com/sun/star/ui/XStatusbarItem.hpp>
37 #include <com/sun/star/frame/XFrame.hpp>
39 #include <com/sun/star/awt/Command.hpp>
40 #include <svl/languageoptions.hxx>
42 #include <helper/mischelper.hxx>
44 #include <rtl/ustrbuf.hxx>
46 #include <map>
47 #include <set>
49 using namespace ::cppu;
50 using namespace ::com::sun::star;
51 using namespace css::uno;
52 using namespace css::lang;
53 using namespace css::frame;
54 using namespace framework;
56 namespace {
58 class LangSelectionStatusbarController:
59 public svt::StatusbarController
61 public:
62 explicit LangSelectionStatusbarController( const css::uno::Reference< css::uno::XComponentContext >& xContext );
63 LangSelectionStatusbarController(const LangSelectionStatusbarController&) = delete;
64 LangSelectionStatusbarController& operator=(const LangSelectionStatusbarController&) = delete;
66 // XInitialization
67 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
69 // XStatusListener
70 virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override;
72 // XStatusbarController
73 virtual void SAL_CALL command( const css::awt::Point& aPos,
74 ::sal_Int32 nCommand,
75 sal_Bool bMouseEvent,
76 const css::uno::Any& aData ) override;
77 virtual void SAL_CALL click( const css::awt::Point& aPos ) override;
79 private:
80 virtual ~LangSelectionStatusbarController() override {}
82 bool m_bShowMenu; // if the menu is to be displayed or not (depending on the selected object/text)
83 SvtScriptType m_nScriptType; // the flags for the different script types available in the selection, LATIN = 0x0001, ASIAN = 0x0002, COMPLEX = 0x0004
84 OUString m_aCurLang; // the language of the current selection, "*" if there are more than one languages
85 OUString m_aKeyboardLang; // the keyboard language
86 OUString m_aGuessedTextLang; // the 'guessed' language for the selection, "" if none could be guessed
87 LanguageGuessingHelper m_aLangGuessHelper;
89 /// @throws css::uno::RuntimeException
90 void LangMenu( const css::awt::Point& aPos );
93 LangSelectionStatusbarController::LangSelectionStatusbarController( const uno::Reference< uno::XComponentContext >& xContext ) :
94 svt::StatusbarController( xContext, uno::Reference< frame::XFrame >(), OUString(), 0 ),
95 m_bShowMenu( true ),
96 m_nScriptType( SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX ),
97 m_aLangGuessHelper( xContext )
101 void SAL_CALL LangSelectionStatusbarController::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
103 SolarMutexGuard aSolarMutexGuard;
105 svt::StatusbarController::initialize( aArguments );
107 if ( m_xStatusbarItem.is() )
109 m_xStatusbarItem->setText( FwkResId(STR_LANGSTATUS_MULTIPLE_LANGUAGES) );
110 m_xStatusbarItem->setQuickHelpText(FwkResId(STR_LANGSTATUS_HINT));
114 void LangSelectionStatusbarController::LangMenu(
115 const css::awt::Point& aPos )
117 if (!m_bShowMenu)
118 return;
120 const Reference<XServiceInfo> xService(m_xFrame->getController()->getModel(), UNO_QUERY);
121 bool bCalc = xService.is() && xService->supportsService(u"com.sun.star.sheet.SpreadsheetDocument"_ustr);
122 bool bWriter = xService.is() && xService->supportsService(u"com.sun.star.text.GenericTextDocument"_ustr);
123 //add context menu
124 Reference< awt::XPopupMenu > xPopupMenu( awt::PopupMenu::create( m_xContext ) );
125 //sub menu that contains all items except the last two items: Separator + Set Language for Paragraph
126 Reference< awt::XPopupMenu > subPopupMenu( awt::PopupMenu::create( m_xContext ) );
128 // get languages to be displayed in the menu
129 std::set< OUString > aLangItems;
130 FillLangItems( aLangItems, m_xFrame, m_aLangGuessHelper,
131 m_nScriptType, m_aCurLang, m_aKeyboardLang, m_aGuessedTextLang );
133 // add first few entries to main menu
134 sal_Int16 nItemId = static_cast< sal_Int16 >(MID_LANG_SEL_1);
135 static constexpr OUString sAsterisk(u"*"_ustr); // multiple languages in current selection
136 const OUString sNone( SvtLanguageTable::GetLanguageString( LANGUAGE_NONE ));
137 std::map< sal_Int16, OUString > aLangMap;
138 for (auto const& langItem : aLangItems)
140 if ( langItem != sNone &&
141 langItem != sAsterisk &&
142 !langItem.isEmpty()) // 'no language found' from language guessing
144 SAL_WARN_IF( MID_LANG_SEL_1 > nItemId || nItemId > MID_LANG_SEL_9,
145 "fwk.uielement", "nItemId outside of expected range!" );
146 xPopupMenu->insertItem( nItemId, langItem, 0, nItemId );
147 if ( langItem == m_aCurLang )
149 //make a sign for the current language
150 xPopupMenu->checkItem( nItemId, true );
152 aLangMap[ nItemId ] = langItem;
153 ++nItemId;
157 if (bWriter)
159 xPopupMenu->insertItem( MID_LANG_SEL_NONE, FwkResId(STR_LANGSTATUS_NONE), 0, MID_LANG_SEL_NONE );
160 if ( sNone == m_aCurLang )
161 xPopupMenu->checkItem( MID_LANG_SEL_NONE, true );
162 xPopupMenu->insertItem( MID_LANG_SEL_RESET, FwkResId(STR_RESET_TO_DEFAULT_LANGUAGE), 0, MID_LANG_SEL_RESET );
163 xPopupMenu->insertItem( MID_LANG_SEL_MORE, FwkResId(STR_LANGSTATUS_MORE), 0, MID_LANG_SEL_MORE );
165 // add entries to submenu ('set language for paragraph')
166 nItemId = static_cast< sal_Int16 >(MID_LANG_PARA_1);
167 for (auto const& langItem : aLangItems)
169 if( langItem != sNone &&
170 langItem != sAsterisk &&
171 !langItem.isEmpty()) // 'no language found' from language guessing
173 SAL_WARN_IF( MID_LANG_PARA_1 > nItemId || nItemId > MID_LANG_PARA_9,
174 "fwk.uielement", "nItemId outside of expected range!" );
175 subPopupMenu->insertItem( nItemId, langItem, 0, nItemId );
176 aLangMap[nItemId] = langItem;
177 ++nItemId;
180 subPopupMenu->insertItem( MID_LANG_PARA_NONE, FwkResId(STR_LANGSTATUS_NONE), 0, MID_LANG_PARA_NONE );
181 subPopupMenu->insertItem( MID_LANG_PARA_RESET, FwkResId(STR_RESET_TO_DEFAULT_LANGUAGE), 0, MID_LANG_PARA_RESET );
182 subPopupMenu->insertItem( MID_LANG_PARA_MORE, FwkResId(STR_LANGSTATUS_MORE), 0, MID_LANG_PARA_MORE );
184 // add last two entries to main menu
185 xPopupMenu->insertSeparator( MID_LANG_PARA_SEPARATOR );
186 xPopupMenu->insertItem( MID_LANG_PARA_STRING, FwkResId(STR_SET_LANGUAGE_FOR_PARAGRAPH), 0, MID_LANG_PARA_STRING );
187 xPopupMenu->setPopupMenu( MID_LANG_PARA_STRING, subPopupMenu );
189 else
191 if (bCalc)
192 xPopupMenu->insertItem( MID_LANG_SEL_NONE, FwkResId(STR_LANGSTATUS_NONE), 0, MID_LANG_SEL_NONE );
193 else
194 xPopupMenu->insertItem( MID_LANG_DEF_NONE, FwkResId(STR_LANGSTATUS_NONE), 0, MID_LANG_DEF_NONE );
195 if ( sNone == m_aCurLang )
196 xPopupMenu->checkItem( MID_LANG_DEF_NONE, true );
197 xPopupMenu->insertItem( MID_LANG_DEF_RESET, FwkResId(STR_RESET_TO_DEFAULT_LANGUAGE), 0, MID_LANG_DEF_RESET );
198 xPopupMenu->insertItem( MID_LANG_DEF_MORE, FwkResId(STR_LANGSTATUS_MORE), 0, MID_LANG_DEF_MORE );
201 // now display the popup menu and execute every command ...
203 Reference< awt::XWindowPeer > xParent( m_xParentWindow, UNO_QUERY );
204 css::awt::Rectangle aRect( aPos.X, aPos.Y, 0, 0 );
205 sal_Int16 nId = xPopupMenu->execute( xParent, aRect, css::awt::PopupMenuDirection::EXECUTE_UP+16 );
206 //click "More..."
207 if ( !(nId && m_xFrame.is()) )
208 return;
210 OUStringBuffer aBuff;
211 //set selected language as current language for selection
212 const OUString aSelectedLang = aLangMap[nId];
214 if (MID_LANG_SEL_1 <= nId && nId <= MID_LANG_SEL_9)
216 if (bWriter || bCalc)
217 aBuff.append( ".uno:LanguageStatus?Language:string=Current_" );
218 else
219 aBuff.append( ".uno:LanguageStatus?Language:string=Default_" );
221 aBuff.append( aSelectedLang );
223 else if (nId == MID_LANG_SEL_NONE)
225 //set None as current language for selection
226 aBuff.append( ".uno:LanguageStatus?Language:string=Current_LANGUAGE_NONE" );
228 else if (nId == MID_LANG_SEL_RESET)
230 // reset language attributes for selection
231 aBuff.append( ".uno:LanguageStatus?Language:string=Current_RESET_LANGUAGES" );
233 else if (nId == MID_LANG_SEL_MORE)
235 //open the dialog "format/character" for current selection
236 aBuff.append( ".uno:FontDialog?Page:string=font" );
238 else if (nId == MID_LANG_DEF_NONE)
240 aBuff.append( ".uno:LanguageStatus?Language:string=Default_LANGUAGE_NONE" );
242 else if (nId == MID_LANG_DEF_RESET)
244 aBuff.append( ".uno:LanguageStatus?Language:string=Default_RESET_LANGUAGES" );
246 else if (nId == MID_LANG_DEF_MORE)
248 aBuff.append( ".uno:LanguageStatus?Language:string=*" );
250 else if (MID_LANG_PARA_1 <= nId && nId <= MID_LANG_PARA_9)
252 aBuff.append( ".uno:LanguageStatus?Language:string=Paragraph_" + aSelectedLang );
254 else if (nId == MID_LANG_PARA_NONE)
256 //set None as language for current paragraph
257 aBuff.append( ".uno:LanguageStatus?Language:string=Paragraph_LANGUAGE_NONE" );
259 else if (nId == MID_LANG_PARA_RESET)
261 // reset language attributes for paragraph
262 aBuff.append( ".uno:LanguageStatus?Language:string=Paragraph_RESET_LANGUAGES" );
264 else if (nId == MID_LANG_PARA_MORE)
266 //open the dialog "format/character" for current paragraph
267 aBuff.append( ".uno:FontDialogForParagraph" );
270 const Sequence< beans::PropertyValue > aDummyArgs;
271 execute( aBuff.makeStringAndClear(), aDummyArgs );
274 void SAL_CALL LangSelectionStatusbarController::command(
275 const css::awt::Point& aPos,
276 ::sal_Int32 nCommand,
277 sal_Bool /*bMouseEvent*/,
278 const css::uno::Any& /*aData*/ )
280 if ( nCommand & ::awt::Command::CONTEXTMENU )
282 LangMenu( aPos );
286 void SAL_CALL LangSelectionStatusbarController::click(
287 const css::awt::Point& aPos )
289 LangMenu( aPos );
292 // XStatusListener
293 void SAL_CALL LangSelectionStatusbarController::statusChanged( const FeatureStateEvent& Event )
295 // This function will be called when observed data changes,
296 // for example the selection or keyboard language.
297 // - It displays the language in use in the status bar
298 // - and it stores the relevant data for creating the menu
299 // at some later point in the member variables
300 // m_nScriptType, m_aCurLang, m_aKeyboardLang, m_aGuessedText
302 SolarMutexGuard aSolarMutexGuard;
304 if ( m_bDisposed )
305 return;
307 m_bShowMenu = true;
308 m_nScriptType = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX; //set the default value
310 if ( !m_xStatusbarItem.is() )
311 return;
313 OUString aStrValue;
314 Sequence< OUString > aSeq;
316 if ( Event.State >>= aStrValue )
318 m_xStatusbarItem->setText( aStrValue );
319 m_xStatusbarItem->setQuickHelpText(FwkResId(STR_LANGSTATUS_HINT));
320 m_aCurLang = aStrValue;
322 else if ( Event.State >>= aSeq )
324 if ( aSeq.getLength() == 4 )
326 OUString aStatusText = aSeq[0];
327 if (aStatusText == "*")
329 aStatusText = FwkResId(STR_LANGSTATUS_MULTIPLE_LANGUAGES);
331 m_xStatusbarItem->setText( aStatusText );
332 m_xStatusbarItem->setQuickHelpText(FwkResId(STR_LANGSTATUS_HINT));
334 // Retrieve all other values from the sequence and
335 // store it members!
336 m_aCurLang = aSeq[0];
337 m_nScriptType = static_cast< SvtScriptType >( aSeq[1].toInt32() );
338 m_aKeyboardLang = aSeq[2];
339 m_aGuessedTextLang = aSeq[3];
342 else if ( !Event.State.hasValue() )
344 m_xStatusbarItem->setText( OUString() );
345 m_xStatusbarItem->setQuickHelpText(u""_ustr);
346 m_bShowMenu = false; // no language -> no menu
352 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
353 com_sun_star_comp_framework_LangSelectionStatusbarController_get_implementation(
354 css::uno::XComponentContext *context,
355 css::uno::Sequence<css::uno::Any> const &)
357 return cppu::acquire(new LangSelectionStatusbarController(context));
360 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */