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