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