Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #include <uielement/langselectionstatusbarcontroller.hxx>
22 : #include <classes/fwkresid.hxx>
23 : #include <services.h>
24 : #include <classes/resource.hrc>
25 : #include <osl/mutex.hxx>
26 : #include <vcl/svapp.hxx>
27 : #include <vcl/window.hxx>
28 : #include <vcl/status.hxx>
29 : #include <toolkit/unohlp.hxx>
30 : #include <toolkit/helper/convert.hxx>
31 :
32 : #include <com/sun/star/frame/XPopupMenuController.hpp>
33 : #include <toolkit/helper/vclunohelper.hxx>
34 : #include <com/sun/star/awt/PopupMenu.hpp>
35 : #include <com/sun/star/awt/PopupMenuDirection.hpp>
36 : #include <svtools/langtab.hxx>
37 : #include "sal/types.h"
38 : #include <vcl/svapp.hxx>
39 : #include <com/sun/star/awt/MenuItemStyle.hpp>
40 : #include <com/sun/star/document/XDocumentLanguages.hpp>
41 : #include <i18npool/mslangid.hxx>
42 : #include <com/sun/star/i18n/ScriptType.hpp>
43 : #include <com/sun/star/frame/XModule.hpp>
44 : #include <com/sun/star/frame/XModel.hpp>
45 :
46 : #include <classes/fwkresid.hxx>
47 : #include <classes/resource.hrc>
48 : #include <com/sun/star/frame/XFrame.hpp>
49 : #include <com/sun/star/frame/XDispatch.hpp>
50 : #include <com/sun/star/frame/XDispatchProvider.hpp>
51 : #include <com/sun/star/util/URLTransformer.hpp>
52 : #include <com/sun/star/util/XURLTransformer.hpp>
53 : #include <comphelper/processfactory.hxx>
54 :
55 : #include <toolkit/unohlp.hxx>
56 : #include <tools/gen.hxx>
57 : #include <com/sun/star/awt/Command.hpp>
58 : #include <svl/languageoptions.hxx>
59 : #include <com/sun/star/linguistic2/XLanguageGuessing.hpp>
60 :
61 : #include "helper/mischelper.hxx"
62 :
63 : #include <map>
64 : #include <set>
65 :
66 : using namespace ::cppu;
67 : using namespace ::com::sun::star;
68 : using namespace ::com::sun::star::uno;
69 : using namespace ::com::sun::star::lang;
70 : using namespace ::com::sun::star::frame;
71 : using namespace ::com::sun::star::i18n;
72 : using namespace ::com::sun::star::document;
73 :
74 : using ::rtl::OUString;
75 :
76 :
77 : namespace framework
78 : {
79 :
80 :
81 38 : DEFINE_XSERVICEINFO_MULTISERVICE ( LangSelectionStatusbarController ,
82 : OWeakObject ,
83 : SERVICENAME_STATUSBARCONTROLLER ,
84 : IMPLEMENTATIONNAME_LANGSELECTIONSTATUSBARCONTROLLER
85 : )
86 :
87 0 : DEFINE_INIT_SERVICE ( LangSelectionStatusbarController, {} )
88 :
89 0 : LangSelectionStatusbarController::LangSelectionStatusbarController( const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) :
90 : svt::StatusbarController( xServiceManager, uno::Reference< frame::XFrame >(), OUString(), 0 ),
91 : m_bShowMenu( sal_True ),
92 : m_nScriptType( LS_SCRIPT_LATIN | LS_SCRIPT_ASIAN | LS_SCRIPT_COMPLEX ),
93 0 : m_aLangGuessHelper( xServiceManager )
94 : {
95 0 : }
96 :
97 : // XInterface
98 0 : Any SAL_CALL LangSelectionStatusbarController::queryInterface( const Type& rType )
99 : throw ( RuntimeException )
100 : {
101 0 : return svt::StatusbarController::queryInterface( rType );
102 : }
103 :
104 0 : void SAL_CALL LangSelectionStatusbarController::acquire() throw ()
105 : {
106 0 : svt::StatusbarController::acquire();
107 0 : }
108 :
109 0 : void SAL_CALL LangSelectionStatusbarController::release() throw ()
110 : {
111 0 : svt::StatusbarController::release();
112 0 : }
113 :
114 0 : void SAL_CALL LangSelectionStatusbarController::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments )
115 : throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
116 : {
117 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::initialize" );
118 0 : SolarMutexGuard aSolarMutexGuard;
119 :
120 0 : svt::StatusbarController::initialize( aArguments );
121 :
122 0 : if ( m_xParentWindow.is() && m_nID > 0 )
123 : {
124 0 : Window* pWindow = VCLUnoHelper::GetWindow( m_xParentWindow );
125 0 : if ( pWindow && ( pWindow->GetType() == WINDOW_STATUSBAR ))
126 : {
127 0 : StatusBar* pStatusBar = (StatusBar *)pWindow;
128 0 : pStatusBar->SetItemText( m_nID, FwkResId( STR_LANGSTATUS_MULTIPLE_LANGUAGES ) );
129 : }
130 0 : }
131 0 : }
132 :
133 : // XComponent
134 0 : void SAL_CALL LangSelectionStatusbarController::dispose()
135 : throw (::com::sun::star::uno::RuntimeException)
136 : {
137 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::dispose" );
138 0 : svt::StatusbarController::dispose();
139 0 : }
140 :
141 : // XEventListener
142 0 : void SAL_CALL LangSelectionStatusbarController::disposing( const com::sun::star::lang::EventObject& Source )
143 : throw ( RuntimeException )
144 : {
145 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::disposing" );
146 0 : svt::StatusbarController::disposing( Source );
147 0 : }
148 :
149 : // XStatusbarController
150 0 : ::sal_Bool SAL_CALL LangSelectionStatusbarController::mouseButtonDown(
151 : const ::com::sun::star::awt::MouseEvent& )
152 : throw (::com::sun::star::uno::RuntimeException)
153 : {
154 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::mouseButtonDown" );
155 0 : return sal_False;
156 : }
157 :
158 0 : ::sal_Bool SAL_CALL LangSelectionStatusbarController::mouseMove(
159 : const ::com::sun::star::awt::MouseEvent& )
160 : throw (::com::sun::star::uno::RuntimeException)
161 : {
162 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::mouseMove" );
163 0 : return sal_False;
164 : }
165 :
166 0 : ::sal_Bool SAL_CALL LangSelectionStatusbarController::mouseButtonUp(
167 : const ::com::sun::star::awt::MouseEvent& )
168 : throw (::com::sun::star::uno::RuntimeException)
169 : {
170 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::mouseButtonUp" );
171 0 : return sal_False;
172 : }
173 :
174 0 : void LangSelectionStatusbarController::LangMenu()
175 : throw (::com::sun::star::uno::RuntimeException)
176 : {
177 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::LangMenu" );
178 0 : if (!m_bShowMenu)
179 0 : return;
180 :
181 : //add context menu
182 0 : Reference< awt::XPopupMenu > xPopupMenu( awt::PopupMenu::create( comphelper::getComponentContext(m_xServiceManager) ) );
183 : //sub menu that contains all items except the last two items: Separator + Set Language for Paragraph
184 0 : Reference< awt::XPopupMenu > subPopupMenu( awt::PopupMenu::create( comphelper::getComponentContext(m_xServiceManager) ) );
185 :
186 0 : SvtLanguageTable aLanguageTable;
187 :
188 : // get languages to be displayed in the menu
189 0 : std::set< OUString > aLangItems;
190 : FillLangItems( aLangItems, aLanguageTable, m_xFrame, m_aLangGuessHelper,
191 0 : m_nScriptType, m_aCurLang, m_aKeyboardLang, m_aGuessedTextLang );
192 :
193 : // add first few entries to main menu
194 0 : sal_Int16 nItemId = static_cast< sal_Int16 >(MID_LANG_SEL_1);
195 0 : const OUString sAsterix(RTL_CONSTASCII_USTRINGPARAM("*")); // multiple languages in current selection
196 0 : const OUString sEmpty; // 'no language found' from language guessing
197 0 : std::map< sal_Int16, OUString > aLangMap;
198 0 : std::set< OUString >::const_iterator it;
199 0 : for (it = aLangItems.begin(); it != aLangItems.end(); ++it)
200 : {
201 0 : const OUString & rStr( *it );
202 0 : if ( rStr != OUString( aLanguageTable.GetString( LANGUAGE_NONE ) ) &&
203 0 : rStr != sAsterix &&
204 0 : rStr != sEmpty)
205 : {
206 : DBG_ASSERT( MID_LANG_SEL_1 <= nItemId && nItemId <= MID_LANG_SEL_9,
207 : "nItemId outside of expected range!" );
208 0 : xPopupMenu->insertItem( nItemId, rStr, css::awt::MenuItemStyle::RADIOCHECK, nItemId );
209 0 : if ( rStr == m_aCurLang )
210 : {
211 : //make a sign for the current language
212 0 : xPopupMenu->checkItem( nItemId, sal_True );
213 : }
214 0 : aLangMap[ nItemId ] = rStr;
215 0 : ++nItemId;
216 : }
217 : }
218 0 : xPopupMenu->insertItem( MID_LANG_SEL_NONE, String( FwkResId( STR_LANGSTATUS_NONE )), css::awt::MenuItemStyle::RADIOCHECK, MID_LANG_SEL_NONE );
219 0 : if ( aLanguageTable.GetString( LANGUAGE_NONE ) == m_aCurLang )
220 0 : xPopupMenu->checkItem( MID_LANG_SEL_NONE, sal_True );
221 :
222 0 : xPopupMenu->insertItem( MID_LANG_SEL_RESET, String( FwkResId( STR_RESET_TO_DEFAULT_LANGUAGE )), 0, MID_LANG_SEL_RESET );
223 0 : xPopupMenu->insertItem( MID_LANG_SEL_MORE, String( FwkResId( STR_LANGSTATUS_MORE )), 0, MID_LANG_SEL_MORE );
224 :
225 : // add entries to submenu ('set language for paragraph')
226 0 : nItemId = static_cast< sal_Int16 >(MID_LANG_PARA_1);
227 0 : for (it = aLangItems.begin(); it != aLangItems.end(); ++it)
228 : {
229 0 : const OUString & rStr( *it );
230 0 : if( rStr != OUString( aLanguageTable.GetString( LANGUAGE_NONE ) )&&
231 0 : rStr != sAsterix &&
232 0 : rStr != sEmpty)
233 : {
234 : DBG_ASSERT( MID_LANG_PARA_1 <= nItemId && nItemId <= MID_LANG_PARA_9,
235 : "nItemId outside of expected range!" );
236 0 : subPopupMenu->insertItem( nItemId, rStr, 0, nItemId );
237 0 : aLangMap[nItemId] = rStr;
238 0 : ++nItemId;
239 : }
240 : }
241 0 : subPopupMenu->insertItem( MID_LANG_PARA_NONE, String( FwkResId( STR_LANGSTATUS_NONE )), 0, MID_LANG_PARA_NONE );
242 0 : subPopupMenu->insertItem( MID_LANG_PARA_RESET, String( FwkResId( STR_RESET_TO_DEFAULT_LANGUAGE )), 0, MID_LANG_PARA_RESET );
243 0 : subPopupMenu->insertItem( MID_LANG_PARA_MORE, String( FwkResId( STR_LANGSTATUS_MORE )), 0, MID_LANG_PARA_MORE );
244 :
245 : // add last two entries to main menu
246 0 : xPopupMenu->insertSeparator( MID_LANG_PARA_SEPERATOR );
247 0 : xPopupMenu->insertItem( MID_LANG_PARA_STRING, String( FwkResId( STR_SET_LANGUAGE_FOR_PARAGRAPH )), 0, MID_LANG_PARA_STRING );
248 0 : xPopupMenu->setPopupMenu( MID_LANG_PARA_STRING, subPopupMenu );
249 :
250 :
251 : // now display the popup menu and execute every command ...
252 :
253 0 : Reference< awt::XWindowPeer > xParent( m_xParentWindow, UNO_QUERY );
254 :
255 0 : com::sun::star::awt::Rectangle aRectangle;
256 0 : Window* pWindow = VCLUnoHelper::GetWindow( m_xParentWindow );
257 0 : const Point mMousePos = pWindow->GetPointerPosPixel();
258 0 : aRectangle.X = mMousePos.X();
259 0 : aRectangle.Y = mMousePos.Y();
260 0 : sal_Int16 nId = xPopupMenu->execute( xParent, aRectangle, com::sun::star::awt::PopupMenuDirection::EXECUTE_UP+16 );
261 : //click "More..."
262 0 : if ( nId && m_xFrame.is() )
263 : {
264 0 : uno::Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
265 0 : util::URL aURL;
266 :
267 0 : if (MID_LANG_SEL_1 <= nId && nId <= MID_LANG_SEL_9)
268 : {
269 : //set selected language as current language for selection
270 0 : String aSelectedLang = aLangMap[nId];
271 0 : aURL.Complete += OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:LanguageStatus?Language:string=Current_"));
272 0 : aURL.Complete += aSelectedLang;
273 : }
274 0 : else if (nId == MID_LANG_SEL_NONE)
275 : {
276 : //set None as current language for selection
277 0 : aURL.Complete += OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:LanguageStatus?Language:string=Current_LANGUAGE_NONE"));
278 : }
279 0 : else if (nId == MID_LANG_SEL_RESET)
280 : {
281 : // reset language attributes for selection
282 0 : aURL.Complete += OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:LanguageStatus?Language:string=Current_RESET_LANGUAGES"));
283 : }
284 0 : else if (nId == MID_LANG_SEL_MORE)
285 : {
286 : //open the dialog "format/character" for current selection
287 0 : aURL.Complete += OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FontDialog?Language:string=*"));
288 : }
289 0 : else if (MID_LANG_PARA_1 <= nId && nId <= MID_LANG_PARA_9)
290 : {
291 : //set selected language for current paragraph
292 0 : String aSelectedLang = aLangMap[nId];
293 0 : aURL.Complete += OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:LanguageStatus?Language:string=Paragraph_"));
294 0 : aURL.Complete += aSelectedLang;
295 : }
296 0 : else if (nId == MID_LANG_PARA_NONE)
297 : {
298 : //set None as language for current paragraph
299 0 : aURL.Complete += OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:LanguageStatus?Language:string=Paragraph_LANGUAGE_NONE"));
300 : }
301 0 : else if (nId == MID_LANG_PARA_RESET)
302 : {
303 : // reset language attributes for paragraph
304 0 : aURL.Complete += OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:LanguageStatus?Language:string=Paragraph_RESET_LANGUAGES"));
305 : }
306 0 : else if (nId == MID_LANG_PARA_MORE)
307 : {
308 : //open the dialog "format/character" for current paragraph
309 0 : aURL.Complete += OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FontDialogForParagraph"));
310 : }
311 :
312 0 : uno::Reference< util::XURLTransformer > xURLTransformer( util::URLTransformer::create(::comphelper::getComponentContext(m_xServiceManager)) );
313 0 : xURLTransformer->parseStrict( aURL );
314 0 : uno::Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch(aURL, OUString(), 0);
315 0 : if( xDispatch.is() )
316 : {
317 0 : uno::Sequence< beans::PropertyValue > aPV;
318 0 : xDispatch->dispatch( aURL, aPV);
319 0 : }
320 0 : }
321 : }
322 :
323 0 : void SAL_CALL LangSelectionStatusbarController::command(
324 : const ::com::sun::star::awt::Point& /*aPos*/,
325 : ::sal_Int32 nCommand,
326 : ::sal_Bool /*bMouseEvent*/,
327 : const ::com::sun::star::uno::Any& /*aData*/ )
328 : throw (::com::sun::star::uno::RuntimeException)
329 : {
330 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::command" );
331 0 : if ( nCommand & ::awt::Command::CONTEXTMENU )
332 : {
333 0 : LangMenu();
334 : }
335 0 : }
336 :
337 0 : void SAL_CALL LangSelectionStatusbarController::paint(
338 : const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics >& xGraphics,
339 : const ::com::sun::star::awt::Rectangle& rOutputRectangle,
340 : ::sal_Int32 nItemId,
341 : ::sal_Int32 nStyle )
342 : throw (::com::sun::star::uno::RuntimeException)
343 : {
344 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::paint" );
345 0 : svt::StatusbarController::paint( xGraphics, rOutputRectangle, nItemId, nStyle );
346 0 : }
347 :
348 0 : void SAL_CALL LangSelectionStatusbarController::click()
349 : throw (::com::sun::star::uno::RuntimeException)
350 : {
351 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::click" );
352 0 : LangMenu();
353 0 : }
354 :
355 0 : void SAL_CALL LangSelectionStatusbarController::doubleClick()
356 : throw (::com::sun::star::uno::RuntimeException)
357 : {
358 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::doubleClick" );
359 0 : svt::StatusbarController::doubleClick();
360 0 : }
361 :
362 : // XStatusListener
363 0 : void SAL_CALL LangSelectionStatusbarController::statusChanged( const FeatureStateEvent& Event )
364 : throw ( RuntimeException )
365 : {
366 : // This function will be called when observed data changes,
367 : // for example the selection or keyboard language.
368 : // - It displays the language in use in the status bar
369 : // - and it stores the relevant data for creating the menu
370 : // at some later point in the member variables
371 : // m_nScriptType, m_aCurLang, m_aKeyboardLang, m_aGuessedText
372 :
373 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::statusChanged" );
374 0 : SolarMutexGuard aSolarMutexGuard;
375 :
376 0 : if ( m_bDisposed )
377 0 : return;
378 :
379 0 : m_bShowMenu = sal_True;
380 :
381 0 : m_nScriptType = LS_SCRIPT_LATIN | LS_SCRIPT_ASIAN | LS_SCRIPT_COMPLEX; //set the default value
382 0 : Window* pWindow = VCLUnoHelper::GetWindow( m_xParentWindow );
383 0 : if ( pWindow && pWindow->GetType() == WINDOW_STATUSBAR && m_nID != 0 )
384 : {
385 0 : OUString aStrValue;
386 0 : Sequence< OUString > aSeq;
387 :
388 0 : StatusBar* pStatusBar = (StatusBar *)pWindow;
389 0 : if ( Event.State >>= aStrValue )
390 0 : pStatusBar->SetItemText( m_nID, aStrValue );
391 0 : else if ( Event.State >>= aSeq )
392 : {
393 0 : if ( aSeq.getLength() == 4 )
394 : {
395 0 : const String aMultipleLangText( FwkResId( STR_LANGSTATUS_MULTIPLE_LANGUAGES ) );
396 0 : OUString aStatusText = aSeq[0];
397 0 : if ( 0 == aStatusText.compareToAscii( "*" ))
398 0 : aStatusText = aMultipleLangText;
399 0 : pStatusBar->SetItemText( m_nID, aStatusText );
400 :
401 : // Retrieve all other values from the sequence and
402 : // store it members!
403 0 : m_aCurLang = aSeq[0];
404 0 : m_nScriptType = static_cast< sal_Int16 >( aSeq[1].toInt32() );
405 0 : m_aKeyboardLang = aSeq[2];
406 0 : m_aGuessedTextLang = aSeq[3];
407 : }
408 : }
409 0 : else if ( !Event.State.hasValue() )
410 : {
411 0 : pStatusBar->SetItemText( m_nID, String() );
412 0 : m_bShowMenu = sal_False; // no language -> no menu
413 0 : }
414 0 : }
415 : }
416 :
417 : }
418 :
419 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|