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