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 <classes/resource.hrc>
23 #include <osl/mutex.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/window.hxx>
26 #include <vcl/status.hxx>
27 #include <toolkit/helper/convert.hxx>
29 #include <boost/noncopyable.hpp>
30 #include <cppuhelper/supportsservice.hxx>
31 #include <toolkit/helper/vclunohelper.hxx>
32 #include <com/sun/star/awt/PopupMenu.hpp>
33 #include <com/sun/star/awt/PopupMenuDirection.hpp>
34 #include <svtools/langtab.hxx>
35 #include <svtools/statusbarcontroller.hxx>
36 #include <sal/types.h>
37 #include <com/sun/star/awt/MenuItemStyle.hpp>
38 #include <com/sun/star/document/XDocumentLanguages.hpp>
39 #include <i18nlangtag/mslangid.hxx>
40 #include <com/sun/star/i18n/ScriptType.hpp>
41 #include <com/sun/star/frame/XModule.hpp>
42 #include <com/sun/star/frame/XModel.hpp>
44 #include <com/sun/star/frame/XFrame.hpp>
45 #include <com/sun/star/frame/XDispatch.hpp>
46 #include <com/sun/star/frame/XDispatchProvider.hpp>
47 #include <comphelper/processfactory.hxx>
49 #include <tools/gen.hxx>
50 #include <com/sun/star/awt/Command.hpp>
51 #include <svl/languageoptions.hxx>
53 #include "helper/mischelper.hxx"
55 #include <rtl/ustrbuf.hxx>
56 #include <rtl/ref.hxx>
58 #include <macros/generic.hxx>
59 #include <macros/xinterface.hxx>
60 #include <macros/xtypeprovider.hxx>
61 #include <macros/xserviceinfo.hxx>
67 using namespace ::cppu
;
68 using namespace ::com::sun::star
;
69 using namespace css::uno
;
70 using namespace css::lang
;
71 using namespace css::frame
;
72 using namespace css::i18n
;
73 using namespace css::document
;
74 using namespace framework
;
78 class LangSelectionStatusbarController
:
79 public svt::StatusbarController
, private boost::noncopyable
82 explicit LangSelectionStatusbarController( const css::uno::Reference
< css::uno::XComponentContext
>& xContext
);
85 virtual void SAL_CALL
initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
) throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
88 virtual void SAL_CALL
statusChanged( const css::frame::FeatureStateEvent
& Event
) throw ( css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
90 // XStatusbarController
91 virtual void SAL_CALL
command( const css::awt::Point
& aPos
,
94 const css::uno::Any
& aData
) throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
95 virtual void SAL_CALL
click( const css::awt::Point
& aPos
) throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
98 virtual ~LangSelectionStatusbarController() {}
100 bool m_bShowMenu
; // if the menu is to be displayed or not (depending on the selected object/text)
101 SvtScriptType m_nScriptType
; // the flags for the different script types available in the selection, LATIN = 0x0001, ASIAN = 0x0002, COMPLEX = 0x0004
102 OUString m_aCurLang
; // the language of the current selection, "*" if there are more than one languages
103 OUString m_aKeyboardLang
; // the keyboard language
104 OUString m_aGuessedTextLang
; // the 'guessed' language for the selection, "" if none could be guessed
105 LanguageGuessingHelper m_aLangGuessHelper
;
107 void LangMenu( const css::awt::Point
& aPos
) throw (css::uno::RuntimeException
);
110 LangSelectionStatusbarController::LangSelectionStatusbarController( const uno::Reference
< uno::XComponentContext
>& xContext
) :
111 svt::StatusbarController( xContext
, uno::Reference
< frame::XFrame
>(), OUString(), 0 ),
113 m_nScriptType( SvtScriptType::LATIN
| SvtScriptType::ASIAN
| SvtScriptType::COMPLEX
),
114 m_aLangGuessHelper( xContext
)
118 void SAL_CALL
LangSelectionStatusbarController::initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
)
119 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
121 SolarMutexGuard aSolarMutexGuard
;
123 svt::StatusbarController::initialize( aArguments
);
125 if ( m_xStatusbarItem
.is() )
127 m_xStatusbarItem
->setText( FWK_RESSTR(STR_LANGSTATUS_MULTIPLE_LANGUAGES
) );
128 m_xStatusbarItem
->setQuickHelpText(FWK_RESSTR(STR_LANGSTATUS_HINT
));
132 void LangSelectionStatusbarController::LangMenu(
133 const css::awt::Point
& aPos
)
134 throw (css::uno::RuntimeException
)
140 Reference
< awt::XPopupMenu
> xPopupMenu( awt::PopupMenu::create( m_xContext
) );
141 //sub menu that contains all items except the last two items: Separator + Set Language for Paragraph
142 Reference
< awt::XPopupMenu
> subPopupMenu( awt::PopupMenu::create( m_xContext
) );
144 // get languages to be displayed in the menu
145 std::set
< OUString
> aLangItems
;
146 FillLangItems( aLangItems
, m_xFrame
, m_aLangGuessHelper
,
147 m_nScriptType
, m_aCurLang
, m_aKeyboardLang
, m_aGuessedTextLang
);
149 // add first few entries to main menu
150 sal_Int16 nItemId
= static_cast< sal_Int16
>(MID_LANG_SEL_1
);
151 const OUString
sAsterisk("*"); // multiple languages in current selection
152 const OUString sEmpty
; // 'no language found' from language guessing
153 const OUString
sNone( SvtLanguageTable::GetLanguageString( LANGUAGE_NONE
));
154 std::map
< sal_Int16
, OUString
> aLangMap
;
155 std::set
< OUString
>::const_iterator it
;
156 for (it
= aLangItems
.begin(); it
!= aLangItems
.end(); ++it
)
158 const OUString
& rStr( *it
);
159 if ( rStr
!= sNone
&&
163 DBG_ASSERT( MID_LANG_SEL_1
<= nItemId
&& nItemId
<= MID_LANG_SEL_9
,
164 "nItemId outside of expected range!" );
165 xPopupMenu
->insertItem( nItemId
, rStr
, 0, nItemId
);
166 if ( rStr
== m_aCurLang
)
168 //make a sign for the current language
169 xPopupMenu
->checkItem( nItemId
, sal_True
);
171 aLangMap
[ nItemId
] = rStr
;
176 xPopupMenu
->insertItem( MID_LANG_SEL_NONE
, FWK_RESSTR(STR_LANGSTATUS_NONE
), 0, MID_LANG_SEL_NONE
);
177 if ( sNone
== m_aCurLang
)
178 xPopupMenu
->checkItem( MID_LANG_SEL_NONE
, sal_True
);
179 xPopupMenu
->insertItem( MID_LANG_SEL_RESET
, FWK_RESSTR(STR_RESET_TO_DEFAULT_LANGUAGE
), 0, MID_LANG_SEL_RESET
);
180 xPopupMenu
->insertItem( MID_LANG_SEL_MORE
, FWK_RESSTR(STR_LANGSTATUS_MORE
), 0, MID_LANG_SEL_MORE
);
182 // add entries to submenu ('set language for paragraph')
183 nItemId
= static_cast< sal_Int16
>(MID_LANG_PARA_1
);
184 for (it
= aLangItems
.begin(); it
!= aLangItems
.end(); ++it
)
186 const OUString
& rStr( *it
);
191 DBG_ASSERT( MID_LANG_PARA_1
<= nItemId
&& nItemId
<= MID_LANG_PARA_9
,
192 "nItemId outside of expected range!" );
193 subPopupMenu
->insertItem( nItemId
, rStr
, 0, nItemId
);
194 aLangMap
[nItemId
] = rStr
;
198 subPopupMenu
->insertItem( MID_LANG_PARA_NONE
, FWK_RESSTR(STR_LANGSTATUS_NONE
), 0, MID_LANG_PARA_NONE
);
199 subPopupMenu
->insertItem( MID_LANG_PARA_RESET
, FWK_RESSTR(STR_RESET_TO_DEFAULT_LANGUAGE
), 0, MID_LANG_PARA_RESET
);
200 subPopupMenu
->insertItem( MID_LANG_PARA_MORE
, FWK_RESSTR(STR_LANGSTATUS_MORE
), 0, MID_LANG_PARA_MORE
);
202 // add last two entries to main menu
203 xPopupMenu
->insertSeparator( MID_LANG_PARA_SEPARATOR
);
204 xPopupMenu
->insertItem( MID_LANG_PARA_STRING
, FWK_RESSTR(STR_SET_LANGUAGE_FOR_PARAGRAPH
), 0, MID_LANG_PARA_STRING
);
205 xPopupMenu
->setPopupMenu( MID_LANG_PARA_STRING
, subPopupMenu
);
207 // now display the popup menu and execute every command ...
209 Reference
< awt::XWindowPeer
> xParent( m_xParentWindow
, UNO_QUERY
);
210 com::sun::star::awt::Rectangle
aRect( aPos
.X
, aPos
.Y
, 0, 0 );
211 sal_Int16 nId
= xPopupMenu
->execute( xParent
, aRect
, com::sun::star::awt::PopupMenuDirection::EXECUTE_UP
+16 );
213 if ( nId
&& m_xFrame
.is() )
215 OUStringBuffer aBuff
;
216 //set selected language as current language for selection
217 const OUString aSelectedLang
= aLangMap
[nId
];
219 if (MID_LANG_SEL_1
<= nId
&& nId
<= MID_LANG_SEL_9
)
221 aBuff
.append( ".uno:LanguageStatus?Language:string=Current_" );
222 aBuff
.append( aSelectedLang
);
224 else if (nId
== MID_LANG_SEL_NONE
)
226 //set None as current language for selection
227 aBuff
.append( ".uno:LanguageStatus?Language:string=Current_LANGUAGE_NONE" );
229 else if (nId
== MID_LANG_SEL_RESET
)
231 // reset language attributes for selection
232 aBuff
.append( ".uno:LanguageStatus?Language:string=Current_RESET_LANGUAGES" );
234 else if (nId
== MID_LANG_SEL_MORE
)
236 //open the dialog "format/character" for current selection
237 aBuff
.append( ".uno:FontDialog?Page:string=font" );
239 else if (MID_LANG_PARA_1
<= nId
&& nId
<= MID_LANG_PARA_9
)
241 aBuff
.append( ".uno:LanguageStatus?Language:string=Paragraph_" );
242 aBuff
.append( aSelectedLang
);
244 else if (nId
== MID_LANG_PARA_NONE
)
246 //set None as language for current paragraph
247 aBuff
.append( ".uno:LanguageStatus?Language:string=Paragraph_LANGUAGE_NONE" );
249 else if (nId
== MID_LANG_PARA_RESET
)
251 // reset language attributes for paragraph
252 aBuff
.append( ".uno:LanguageStatus?Language:string=Paragraph_RESET_LANGUAGES" );
254 else if (nId
== MID_LANG_PARA_MORE
)
256 //open the dialog "format/character" for current paragraph
257 aBuff
.append( ".uno:FontDialogForParagraph" );
260 const Sequence
< beans::PropertyValue
> aDummyArgs
;
261 execute( aBuff
.makeStringAndClear(), aDummyArgs
);
265 void SAL_CALL
LangSelectionStatusbarController::command(
266 const css::awt::Point
& aPos
,
267 ::sal_Int32 nCommand
,
268 sal_Bool
/*bMouseEvent*/,
269 const css::uno::Any
& /*aData*/ )
270 throw (css::uno::RuntimeException
, std::exception
)
272 if ( nCommand
& ::awt::Command::CONTEXTMENU
)
278 void SAL_CALL
LangSelectionStatusbarController::click(
279 const css::awt::Point
& aPos
)
280 throw (css::uno::RuntimeException
, std::exception
)
286 void SAL_CALL
LangSelectionStatusbarController::statusChanged( const FeatureStateEvent
& Event
)
287 throw ( RuntimeException
, std::exception
)
289 // This function will be called when observed data changes,
290 // for example the selection or keyboard language.
291 // - It displays the language in use in the status bar
292 // - and it stores the relevant data for creating the menu
293 // at some later point in the member variables
294 // m_nScriptType, m_aCurLang, m_aKeyboardLang, m_aGuessedText
296 SolarMutexGuard aSolarMutexGuard
;
302 m_nScriptType
= SvtScriptType::LATIN
| SvtScriptType::ASIAN
| SvtScriptType::COMPLEX
; //set the default value
304 if ( m_xStatusbarItem
.is() )
307 Sequence
< OUString
> aSeq
;
309 if ( Event
.State
>>= aStrValue
)
310 m_xStatusbarItem
->setText( aStrValue
);
311 else if ( Event
.State
>>= aSeq
)
313 if ( aSeq
.getLength() == 4 )
315 OUString aStatusText
= aSeq
[0];
316 if (aStatusText
== "*")
318 aStatusText
= FWK_RESSTR(STR_LANGSTATUS_MULTIPLE_LANGUAGES
);
320 m_xStatusbarItem
->setText( aStatusText
);
322 // Retrieve all other values from the sequence and
324 m_aCurLang
= aSeq
[0];
325 m_nScriptType
= static_cast< SvtScriptType
>( aSeq
[1].toInt32() );
326 m_aKeyboardLang
= aSeq
[2];
327 m_aGuessedTextLang
= aSeq
[3];
330 else if ( !Event
.State
.hasValue() )
332 m_xStatusbarItem
->setText( OUString() );
333 m_bShowMenu
= false; // no language -> no menu
340 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
* SAL_CALL
341 com_sun_star_comp_framework_LangSelectionStatusbarController_get_implementation(
342 css::uno::XComponentContext
*context
,
343 css::uno::Sequence
<css::uno::Any
> const &)
345 return cppu::acquire(new LangSelectionStatusbarController(context
));
348 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */