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/langselectionmenucontroller.hxx> 32 33 //_________________________________________________________________________________________________________________ 34 // my own includes 35 //_________________________________________________________________________________________________________________ 36 #include <threadhelp/resetableguard.hxx> 37 #include "services.h" 38 39 //_________________________________________________________________________________________________________________ 40 // interface includes 41 //_________________________________________________________________________________________________________________ 42 #include <com/sun/star/awt/XDevice.hpp> 43 #include <com/sun/star/beans/PropertyValue.hpp> 44 #include <com/sun/star/awt/MenuItemStyle.hpp> 45 #include <com/sun/star/frame/XDispatchProvider.hpp> 46 47 //_________________________________________________________________________________________________________________ 48 // includes of other projects 49 //_________________________________________________________________________________________________________________ 50 51 #ifndef _VCL_MENU_HXX_ 52 #include <vcl/menu.hxx> 53 #endif 54 #include <vcl/svapp.hxx> 55 #include <vcl/i18nhelp.hxx> 56 #include <tools/urlobj.hxx> 57 #include <rtl/ustrbuf.hxx> 58 #ifndef _VCL_MNEMONIC_HXX_ 59 #include <vcl/mnemonic.hxx> 60 #endif 61 #include <com/sun/star/awt/XMenuExtended.hpp> 62 #include <comphelper/processfactory.hxx> 63 64 #include <com/sun/star/document/XDocumentLanguages.hpp> 65 #include <com/sun/star/frame/XPopupMenuController.hpp> 66 #include <com/sun/star/linguistic2/XLanguageGuessing.hpp> 67 68 #include <i18npool/mslangid.hxx> 69 #include <svl/languageoptions.hxx> 70 #include <com/sun/star/awt/MenuItemStyle.hpp> 71 #include <svtools/langtab.hxx> 72 #include <classes/fwlresid.hxx> 73 74 #ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_ 75 #include <classes/resource.hrc> 76 #endif 77 #include <dispatch/uieventloghelper.hxx> 78 79 #include "helper/mischelper.hxx" 80 #include <vos/mutex.hxx> 81 82 #include <map> 83 #include <set> 84 85 //_________________________________________________________________________________________________________________ 86 // Defines 87 //_________________________________________________________________________________________________________________ 88 // 89 using namespace ::com::sun::star; 90 using namespace com::sun::star::uno; 91 using namespace com::sun::star::lang; 92 using namespace com::sun::star::frame; 93 using namespace com::sun::star::beans; 94 using namespace com::sun::star::util; 95 96 using ::rtl::OUString; 97 98 namespace framework 99 { 100 101 DEFINE_XSERVICEINFO_MULTISERVICE ( LanguageSelectionMenuController , 102 OWeakObject , 103 SERVICENAME_POPUPMENUCONTROLLER , 104 IMPLEMENTATIONNAME_LANGUAGESELECTIONMENUCONTROLLER 105 ) 106 107 DEFINE_INIT_SERVICE ( LanguageSelectionMenuController, {} ) 108 109 LanguageSelectionMenuController::LanguageSelectionMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : 110 svt::PopupMenuControllerBase( xServiceManager ), 111 m_bShowMenu( sal_True ), 112 m_aLangGuessHelper( xServiceManager ) 113 { 114 } 115 116 LanguageSelectionMenuController::~LanguageSelectionMenuController() 117 { 118 } 119 120 // XEventListener 121 void SAL_CALL LanguageSelectionMenuController::disposing( const EventObject& ) throw ( RuntimeException ) 122 { 123 Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); 124 125 osl::MutexGuard aLock( m_aMutex ); 126 m_xFrame.clear(); 127 m_xDispatch.clear(); 128 m_xLanguageDispatch.clear(); 129 m_xServiceManager.clear(); 130 131 if ( m_xPopupMenu.is() ) 132 m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); 133 m_xPopupMenu.clear(); 134 } 135 136 // XStatusListener 137 void SAL_CALL LanguageSelectionMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException ) 138 { 139 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); 140 141 if (rBHelper.bDisposed || rBHelper.bInDispose) 142 return; 143 144 m_bShowMenu = sal_True; 145 m_nScriptType = LS_SCRIPT_LATIN | LS_SCRIPT_ASIAN | LS_SCRIPT_COMPLEX; //set the default value 146 147 OUString aStrValue; 148 Sequence< OUString > aSeq; 149 150 if ( Event.State >>= aSeq ) 151 { 152 if ( aSeq.getLength() == 4 ) 153 { 154 // Retrieve all other values from the sequence and 155 // store it members! 156 m_aCurLang = aSeq[0]; 157 m_nScriptType = static_cast< sal_Int16 >(aSeq[1].toInt32()); 158 m_aKeyboardLang = aSeq[2]; 159 m_aGuessedTextLang = aSeq[3]; 160 } 161 } 162 else if ( !Event.State.hasValue() ) 163 { 164 m_bShowMenu = sal_False; // no language -> no sub-menu entries -> disable menu 165 } 166 } 167 168 // XMenuListener 169 void LanguageSelectionMenuController::impl_select(const Reference< XDispatch >& _xDispatch,const ::com::sun::star::util::URL& aTargetURL) 170 { 171 Reference< XDispatch > xDispatch = _xDispatch; 172 173 if ( aTargetURL.Complete == m_aMenuCommandURL_Font ) 174 { //open format/character dialog for current selection 175 xDispatch = m_xMenuDispatch_Font; 176 } 177 else if ( aTargetURL.Complete == m_aMenuCommandURL_Lang ) 178 { //open language tab-page in tools/options dialog 179 xDispatch = m_xMenuDispatch_Lang; 180 } 181 else if ( aTargetURL.Complete == m_aMenuCommandURL_CharDlgForParagraph ) 182 { //open format/character dialog for current selection 183 xDispatch = m_xMenuDispatch_CharDlgForParagraph; 184 } 185 186 if ( !xDispatch.is() ) 187 { 188 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); 189 if ( xDispatchProvider.is() ) 190 xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 ); 191 } 192 193 if ( xDispatch.is() ) 194 { 195 Sequence<PropertyValue> aArgs; 196 if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# 197 UiEventLogHelper( OUString::createFromAscii("LanguageSelectionMenuController")).log( m_xServiceManager, m_xFrame, aTargetURL, aArgs ); 198 xDispatch->dispatch( aTargetURL, aArgs ); 199 } 200 } 201 202 // XPopupMenuController 203 void LanguageSelectionMenuController::impl_setPopupMenu() 204 { 205 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); 206 207 com::sun::star::util::URL aTargetURL; 208 209 // Register for language updates 210 aTargetURL.Complete = m_aLangStatusCommandURL; 211 m_xURLTransformer->parseStrict( aTargetURL ); 212 m_xLanguageDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 ); 213 214 // Register for setting languages and opening language dialog 215 aTargetURL.Complete = m_aMenuCommandURL_Lang; 216 m_xURLTransformer->parseStrict( aTargetURL ); 217 m_xMenuDispatch_Lang = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 ); 218 219 // Register for opening character dialog 220 aTargetURL.Complete = m_aMenuCommandURL_Font; 221 m_xURLTransformer->parseStrict( aTargetURL ); 222 m_xMenuDispatch_Font = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 ); 223 224 // Register for opening character dialog with preselected paragraph 225 aTargetURL.Complete = m_aMenuCommandURL_CharDlgForParagraph; 226 m_xURLTransformer->parseStrict( aTargetURL ); 227 m_xMenuDispatch_CharDlgForParagraph = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 ); 228 } 229 230 void LanguageSelectionMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu , const Mode eMode ) 231 { 232 VCLXPopupMenu* pVCLPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); 233 PopupMenu* pPopupMenu = 0; 234 235 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); 236 237 resetPopupMenu( rPopupMenu ); 238 if (!m_bShowMenu) 239 return; 240 241 if ( pVCLPopupMenu ) 242 pPopupMenu = (PopupMenu *)pVCLPopupMenu->GetMenu(); 243 244 String aCmd; 245 String aCmd_Dialog; 246 String aCmd_Language; 247 if( eMode == MODE_SetLanguageSelectionMenu ) 248 { 249 aCmd_Dialog.AppendAscii(".uno:FontDialog?Language:string=*"); 250 aCmd_Language.AppendAscii(".uno:LanguageStatus?Language:string=Current_"); 251 } 252 else if ( eMode == MODE_SetLanguageParagraphMenu ) 253 { 254 aCmd_Dialog.AppendAscii(".uno:FontDialogForParagraph"); 255 aCmd_Language.AppendAscii(".uno:LanguageStatus?Language:string=Paragraph_"); 256 } 257 else if ( eMode == MODE_SetLanguageAllTextMenu ) 258 { 259 aCmd_Dialog.AppendAscii(".uno:LanguageStatus?Language:string=*"); 260 aCmd_Language.AppendAscii(".uno:LanguageStatus?Language:string=Default_"); 261 } 262 263 SvtLanguageTable aLanguageTable; 264 265 // get languages to be displayed in the menu 266 std::set< OUString > aLangItems; 267 FillLangItems( aLangItems, aLanguageTable, m_xFrame, m_aLangGuessHelper, 268 m_nScriptType, m_aCurLang, m_aKeyboardLang, m_aGuessedTextLang ); 269 270 // 271 // now add menu entries 272 // the different menues purpose will be handled by the different string 273 // for aCmd_Dialog and aCmd_Language 274 // 275 276 sal_Int16 nItemId = 1; // in this control the item id is not important for executing the command 277 const OUString sAsterix(RTL_CONSTASCII_USTRINGPARAM("*")); // multiple languages in current selection 278 const OUString sEmpty; // 'no language found' from language guessing 279 std::map< sal_Int16, OUString > aLangMap; 280 std::set< OUString >::const_iterator it; 281 for (it = aLangItems.begin(); it != aLangItems.end(); ++it) 282 { 283 const OUString & rStr( *it ); 284 if (rStr != OUString( aLanguageTable.GetString( LANGUAGE_NONE ) )&& 285 rStr != sAsterix && 286 rStr != sEmpty) 287 { 288 pPopupMenu->InsertItem( nItemId, rStr ); 289 aCmd = aCmd_Language; 290 aCmd += String( rStr ); 291 pPopupMenu->SetItemCommand( nItemId, aCmd ); 292 if (rStr == m_aCurLang && eMode == MODE_SetLanguageSelectionMenu ) 293 { 294 //make a sign for the current language 295 pPopupMenu->CheckItem( nItemId, sal_True ); 296 } 297 aLangMap[ nItemId ] = rStr; 298 ++nItemId; 299 } 300 } 301 302 // entry for LANGUAGE_NONE 303 ++nItemId; 304 pPopupMenu->InsertItem( nItemId, String(FwlResId( STR_LANGSTATUS_NONE )) ); 305 aCmd=aCmd_Language; 306 aCmd.AppendAscii("LANGUAGE_NONE"); 307 pPopupMenu->SetItemCommand( nItemId, aCmd ); 308 309 // entry for 'Reset to default language' 310 ++nItemId; 311 pPopupMenu->InsertItem( nItemId, String(FwlResId( STR_RESET_TO_DEFAULT_LANGUAGE )) ); 312 aCmd=aCmd_Language; 313 aCmd.AppendAscii("RESET_LANGUAGES"); 314 pPopupMenu->SetItemCommand( nItemId, aCmd ); 315 316 // entry for opening the Format/Character dialog 317 ++nItemId; 318 pPopupMenu->InsertItem( nItemId, String(FwlResId( STR_LANGSTATUS_MORE ))); 319 pPopupMenu->SetItemCommand( nItemId, aCmd_Dialog ); 320 } 321 322 323 void SAL_CALL LanguageSelectionMenuController::updatePopupMenu() throw ( ::com::sun::star::uno::RuntimeException ) 324 { 325 svt::PopupMenuControllerBase::updatePopupMenu(); 326 327 // Force status update to get information about the current languages 328 osl::ClearableMutexGuard aLock( m_aMutex ); 329 Reference< XDispatch > xDispatch( m_xLanguageDispatch ); 330 com::sun::star::util::URL aTargetURL; 331 aTargetURL.Complete = m_aLangStatusCommandURL; 332 m_xURLTransformer->parseStrict( aTargetURL ); 333 aLock.clear(); 334 335 if ( xDispatch.is() ) 336 { 337 xDispatch->addStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); 338 xDispatch->removeStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); 339 } 340 341 // TODO: Fill menu with the information retrieved by the status update 342 343 if( m_aCommandURL.equalsAscii( ".uno:SetLanguageSelectionMenu" )) 344 { 345 fillPopupMenu(m_xPopupMenu, MODE_SetLanguageSelectionMenu ); 346 } 347 else if( m_aCommandURL.equalsAscii( ".uno:SetLanguageParagraphMenu" )) 348 { 349 fillPopupMenu(m_xPopupMenu, MODE_SetLanguageParagraphMenu ); 350 } 351 else if( m_aCommandURL.equalsAscii( ".uno:SetLanguageAllTextMenu" )) 352 { 353 fillPopupMenu(m_xPopupMenu, MODE_SetLanguageAllTextMenu ); 354 } 355 } 356 357 // XInitialization 358 void SAL_CALL LanguageSelectionMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) 359 { 360 osl::MutexGuard aLock( m_aMutex ); 361 362 sal_Bool bInitalized( m_bInitialized ); 363 if ( !bInitalized ) 364 { 365 svt::PopupMenuControllerBase::initialize(aArguments); 366 367 if ( m_bInitialized ) 368 { 369 m_aLangStatusCommandURL = OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:LanguageStatus" )); 370 m_aMenuCommandURL_Lang = m_aLangStatusCommandURL; 371 m_aMenuCommandURL_Font = OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontDialog" )); 372 m_aMenuCommandURL_CharDlgForParagraph = OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontDialogForParagraph" )); 373 } 374 } 375 } 376 377 } 378 379