Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / framework / source / uielement / langselectionstatusbarcontroller.cxx
blobe620af612092265d75873fc2f885c2c9cb8ae098
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 css::i18n;
55 using namespace css::document;
56 using namespace framework;
58 namespace {
60 class LangSelectionStatusbarController:
61 public svt::StatusbarController
63 public:
64 explicit LangSelectionStatusbarController( const css::uno::Reference< css::uno::XComponentContext >& xContext );
65 LangSelectionStatusbarController(const LangSelectionStatusbarController&) = delete;
66 LangSelectionStatusbarController& operator=(const LangSelectionStatusbarController&) = delete;
68 // XInitialization
69 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
71 // XStatusListener
72 virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override;
74 // XStatusbarController
75 virtual void SAL_CALL command( const css::awt::Point& aPos,
76 ::sal_Int32 nCommand,
77 sal_Bool bMouseEvent,
78 const css::uno::Any& aData ) override;
79 virtual void SAL_CALL click( const css::awt::Point& aPos ) override;
81 private:
82 virtual ~LangSelectionStatusbarController() override {}
84 bool m_bShowMenu; // if the menu is to be displayed or not (depending on the selected object/text)
85 SvtScriptType m_nScriptType; // the flags for the different script types available in the selection, LATIN = 0x0001, ASIAN = 0x0002, COMPLEX = 0x0004
86 OUString m_aCurLang; // the language of the current selection, "*" if there are more than one languages
87 OUString m_aKeyboardLang; // the keyboard language
88 OUString m_aGuessedTextLang; // the 'guessed' language for the selection, "" if none could be guessed
89 LanguageGuessingHelper m_aLangGuessHelper;
91 /// @throws css::uno::RuntimeException
92 void LangMenu( const css::awt::Point& aPos );
95 LangSelectionStatusbarController::LangSelectionStatusbarController( const uno::Reference< uno::XComponentContext >& xContext ) :
96 svt::StatusbarController( xContext, uno::Reference< frame::XFrame >(), OUString(), 0 ),
97 m_bShowMenu( true ),
98 m_nScriptType( SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX ),
99 m_aLangGuessHelper( xContext )
103 void SAL_CALL LangSelectionStatusbarController::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
105 SolarMutexGuard aSolarMutexGuard;
107 svt::StatusbarController::initialize( aArguments );
109 if ( m_xStatusbarItem.is() )
111 m_xStatusbarItem->setText( FwkResId(STR_LANGSTATUS_MULTIPLE_LANGUAGES) );
112 m_xStatusbarItem->setQuickHelpText(FwkResId(STR_LANGSTATUS_HINT));
116 void LangSelectionStatusbarController::LangMenu(
117 const css::awt::Point& aPos )
119 if (!m_bShowMenu)
120 return;
122 const Reference<XServiceInfo> xService(m_xFrame->getController()->getModel(), UNO_QUERY);
123 bool bCalc = xService.is() && xService->supportsService("com.sun.star.sheet.SpreadsheetDocument");
124 bool bWriter = xService.is() && xService->supportsService("com.sun.star.text.GenericTextDocument");
125 //add context menu
126 Reference< awt::XPopupMenu > xPopupMenu( awt::PopupMenu::create( m_xContext ) );
127 //sub menu that contains all items except the last two items: Separator + Set Language for Paragraph
128 Reference< awt::XPopupMenu > subPopupMenu( awt::PopupMenu::create( m_xContext ) );
130 // get languages to be displayed in the menu
131 std::set< OUString > aLangItems;
132 FillLangItems( aLangItems, m_xFrame, m_aLangGuessHelper,
133 m_nScriptType, m_aCurLang, m_aKeyboardLang, m_aGuessedTextLang );
135 // add first few entries to main menu
136 sal_Int16 nItemId = static_cast< sal_Int16 >(MID_LANG_SEL_1);
137 static const OUStringLiteral sAsterisk(u"*"); // multiple languages in current selection
138 const OUString sNone( SvtLanguageTable::GetLanguageString( LANGUAGE_NONE ));
139 std::map< sal_Int16, OUString > aLangMap;
140 for (auto const& langItem : aLangItems)
142 if ( langItem != sNone &&
143 langItem != sAsterisk &&
144 !langItem.isEmpty()) // 'no language found' from language guessing
146 SAL_WARN_IF( MID_LANG_SEL_1 > nItemId || nItemId > MID_LANG_SEL_9,
147 "fwk.uielement", "nItemId outside of expected range!" );
148 xPopupMenu->insertItem( nItemId, langItem, 0, nItemId );
149 if ( langItem == m_aCurLang )
151 //make a sign for the current language
152 xPopupMenu->checkItem( nItemId, true );
154 aLangMap[ nItemId ] = langItem;
155 ++nItemId;
159 if (bWriter)
161 xPopupMenu->insertItem( MID_LANG_SEL_NONE, FwkResId(STR_LANGSTATUS_NONE), 0, MID_LANG_SEL_NONE );
162 if ( sNone == m_aCurLang )
163 xPopupMenu->checkItem( MID_LANG_SEL_NONE, true );
164 xPopupMenu->insertItem( MID_LANG_SEL_RESET, FwkResId(STR_RESET_TO_DEFAULT_LANGUAGE), 0, MID_LANG_SEL_RESET );
165 xPopupMenu->insertItem( MID_LANG_SEL_MORE, FwkResId(STR_LANGSTATUS_MORE), 0, MID_LANG_SEL_MORE );
167 // add entries to submenu ('set language for paragraph')
168 nItemId = static_cast< sal_Int16 >(MID_LANG_PARA_1);
169 for (auto const& langItem : aLangItems)
171 if( langItem != sNone &&
172 langItem != sAsterisk &&
173 !langItem.isEmpty()) // 'no language found' from language guessing
175 SAL_WARN_IF( MID_LANG_PARA_1 > nItemId || nItemId > MID_LANG_PARA_9,
176 "fwk.uielement", "nItemId outside of expected range!" );
177 subPopupMenu->insertItem( nItemId, langItem, 0, nItemId );
178 aLangMap[nItemId] = langItem;
179 ++nItemId;
182 subPopupMenu->insertItem( MID_LANG_PARA_NONE, FwkResId(STR_LANGSTATUS_NONE), 0, MID_LANG_PARA_NONE );
183 subPopupMenu->insertItem( MID_LANG_PARA_RESET, FwkResId(STR_RESET_TO_DEFAULT_LANGUAGE), 0, MID_LANG_PARA_RESET );
184 subPopupMenu->insertItem( MID_LANG_PARA_MORE, FwkResId(STR_LANGSTATUS_MORE), 0, MID_LANG_PARA_MORE );
186 // add last two entries to main menu
187 xPopupMenu->insertSeparator( MID_LANG_PARA_SEPARATOR );
188 xPopupMenu->insertItem( MID_LANG_PARA_STRING, FwkResId(STR_SET_LANGUAGE_FOR_PARAGRAPH), 0, MID_LANG_PARA_STRING );
189 xPopupMenu->setPopupMenu( MID_LANG_PARA_STRING, subPopupMenu );
191 else
193 xPopupMenu->insertItem( MID_LANG_DEF_NONE, FwkResId(STR_LANGSTATUS_NONE), 0, MID_LANG_DEF_NONE );
194 if ( sNone == m_aCurLang )
195 xPopupMenu->checkItem( MID_LANG_DEF_NONE, true );
196 xPopupMenu->insertItem( MID_LANG_DEF_RESET, FwkResId(STR_RESET_TO_DEFAULT_LANGUAGE), 0, MID_LANG_DEF_RESET );
197 xPopupMenu->insertItem( MID_LANG_DEF_MORE, FwkResId(STR_LANGSTATUS_MORE), 0, MID_LANG_DEF_MORE );
200 // now display the popup menu and execute every command ...
202 Reference< awt::XWindowPeer > xParent( m_xParentWindow, UNO_QUERY );
203 css::awt::Rectangle aRect( aPos.X, aPos.Y, 0, 0 );
204 sal_Int16 nId = xPopupMenu->execute( xParent, aRect, css::awt::PopupMenuDirection::EXECUTE_UP+16 );
205 //click "More..."
206 if ( !(nId && m_xFrame.is()) )
207 return;
209 OUStringBuffer aBuff;
210 //set selected language as current language for selection
211 const OUString aSelectedLang = aLangMap[nId];
213 if (MID_LANG_SEL_1 <= nId && nId <= MID_LANG_SEL_9)
215 if (bWriter)
216 aBuff.append( ".uno:LanguageStatus?Language:string=Current_" );
217 else
218 aBuff.append( ".uno:LanguageStatus?Language:string=Default_" );
220 aBuff.append( aSelectedLang );
222 else if (nId == MID_LANG_SEL_NONE)
224 //set None as current language for selection
225 aBuff.append( ".uno:LanguageStatus?Language:string=Current_LANGUAGE_NONE" );
227 else if (nId == MID_LANG_SEL_RESET)
229 // reset language attributes for selection
230 aBuff.append( ".uno:LanguageStatus?Language:string=Current_RESET_LANGUAGES" );
232 else if (nId == MID_LANG_SEL_MORE)
234 //open the dialog "format/character" for current selection
235 aBuff.append( ".uno:FontDialog?Page:string=font" );
237 else if (nId == MID_LANG_DEF_NONE)
239 aBuff.append( ".uno:LanguageStatus?Language:string=Default_LANGUAGE_NONE" );
241 else if (nId == MID_LANG_DEF_RESET)
243 aBuff.append( ".uno:LanguageStatus?Language:string=Default_RESET_LANGUAGES" );
245 else if (nId == MID_LANG_DEF_MORE)
247 if (bCalc)
248 aBuff.append( ".uno:FormatCellDialog" );
249 else
250 aBuff.append( ".uno:LanguageStatus?Language:string=*" );
252 else if (MID_LANG_PARA_1 <= nId && nId <= MID_LANG_PARA_9)
254 aBuff.append( ".uno:LanguageStatus?Language:string=Paragraph_" + aSelectedLang );
256 else if (nId == MID_LANG_PARA_NONE)
258 //set None as language for current paragraph
259 aBuff.append( ".uno:LanguageStatus?Language:string=Paragraph_LANGUAGE_NONE" );
261 else if (nId == MID_LANG_PARA_RESET)
263 // reset language attributes for paragraph
264 aBuff.append( ".uno:LanguageStatus?Language:string=Paragraph_RESET_LANGUAGES" );
266 else if (nId == MID_LANG_PARA_MORE)
268 //open the dialog "format/character" for current paragraph
269 aBuff.append( ".uno:FontDialogForParagraph" );
272 const Sequence< beans::PropertyValue > aDummyArgs;
273 execute( aBuff.makeStringAndClear(), aDummyArgs );
276 void SAL_CALL LangSelectionStatusbarController::command(
277 const css::awt::Point& aPos,
278 ::sal_Int32 nCommand,
279 sal_Bool /*bMouseEvent*/,
280 const css::uno::Any& /*aData*/ )
282 if ( nCommand & ::awt::Command::CONTEXTMENU )
284 LangMenu( aPos );
288 void SAL_CALL LangSelectionStatusbarController::click(
289 const css::awt::Point& aPos )
291 LangMenu( aPos );
294 // XStatusListener
295 void SAL_CALL LangSelectionStatusbarController::statusChanged( const FeatureStateEvent& Event )
297 // This function will be called when observed data changes,
298 // for example the selection or keyboard language.
299 // - It displays the language in use in the status bar
300 // - and it stores the relevant data for creating the menu
301 // at some later point in the member variables
302 // m_nScriptType, m_aCurLang, m_aKeyboardLang, m_aGuessedText
304 SolarMutexGuard aSolarMutexGuard;
306 if ( m_bDisposed )
307 return;
309 m_bShowMenu = true;
310 m_nScriptType = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX; //set the default value
312 if ( !m_xStatusbarItem.is() )
313 return;
315 OUString aStrValue;
316 Sequence< OUString > aSeq;
318 if ( Event.State >>= aStrValue )
320 m_xStatusbarItem->setText( aStrValue );
321 m_xStatusbarItem->setQuickHelpText(FwkResId(STR_LANGSTATUS_HINT));
322 m_aCurLang = aStrValue;
324 else if ( Event.State >>= aSeq )
326 if ( aSeq.getLength() == 4 )
328 OUString aStatusText = aSeq[0];
329 if (aStatusText == "*")
331 aStatusText = FwkResId(STR_LANGSTATUS_MULTIPLE_LANGUAGES);
333 m_xStatusbarItem->setText( aStatusText );
334 m_xStatusbarItem->setQuickHelpText(FwkResId(STR_LANGSTATUS_HINT));
336 // Retrieve all other values from the sequence and
337 // store it members!
338 m_aCurLang = aSeq[0];
339 m_nScriptType = static_cast< SvtScriptType >( aSeq[1].toInt32() );
340 m_aKeyboardLang = aSeq[2];
341 m_aGuessedTextLang = aSeq[3];
344 else if ( !Event.State.hasValue() )
346 m_xStatusbarItem->setText( OUString() );
347 m_xStatusbarItem->setQuickHelpText(u"");
348 m_bShowMenu = false; // no language -> no menu
354 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
355 com_sun_star_comp_framework_LangSelectionStatusbarController_get_implementation(
356 css::uno::XComponentContext *context,
357 css::uno::Sequence<css::uno::Any> const &)
359 return cppu::acquire(new LangSelectionStatusbarController(context));
362 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */