1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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>
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
;
58 class LangSelectionStatusbarController
:
59 public svt::StatusbarController
62 explicit LangSelectionStatusbarController( const css::uno::Reference
< css::uno::XComponentContext
>& xContext
);
63 LangSelectionStatusbarController(const LangSelectionStatusbarController
&) = delete;
64 LangSelectionStatusbarController
& operator=(const LangSelectionStatusbarController
&) = delete;
67 virtual void SAL_CALL
initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
) override
;
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
,
76 const css::uno::Any
& aData
) override
;
77 virtual void SAL_CALL
click( const css::awt::Point
& aPos
) override
;
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 ),
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
)
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
);
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
;
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
;
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
);
192 xPopupMenu
->insertItem( MID_LANG_SEL_NONE
, FwkResId(STR_LANGSTATUS_NONE
), 0, MID_LANG_SEL_NONE
);
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 );
207 if ( !(nId
&& m_xFrame
.is()) )
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_" );
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
)
286 void SAL_CALL
LangSelectionStatusbarController::click(
287 const css::awt::Point
& aPos
)
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
;
308 m_nScriptType
= SvtScriptType::LATIN
| SvtScriptType::ASIAN
| SvtScriptType::COMPLEX
; //set the default value
310 if ( !m_xStatusbarItem
.is() )
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
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: */