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