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 // now add menu entries 266 // the different menu purposes will be handled by the different string 267 // for aCmd_Dialog and aCmd_Language 268 269 sal_Int16 nItemId = 1; // in this control the item id is not important for executing the command 270 const OUString sAsterix(RTL_CONSTASCII_USTRINGPARAM("*")); // multiple languages in current selection 271 const OUString sEmpty; // 'no language found' from language guessing 272 std::map< sal_Int16, OUString > aLangMap; 273 std::set< OUString >::const_iterator it; 274 for (it = aLangItems.begin(); it != aLangItems.end(); ++it) 275 { 276 const OUString & rStr( *it ); 277 if (rStr != OUString( aLanguageTable.GetString( LANGUAGE_NONE ) )&& 278 rStr != sAsterix && 279 rStr != sEmpty) 280 { 281 pPopupMenu->InsertItem( nItemId, rStr ); 282 aCmd = aCmd_Language; 283 aCmd += String( rStr ); 284 pPopupMenu->SetItemCommand( nItemId, aCmd ); 285 if (rStr == m_aCurLang && eMode == MODE_SetLanguageSelectionMenu ) 286 { 287 //make a sign for the current language 288 pPopupMenu->CheckItem( nItemId, sal_True ); 289 } 290 aLangMap[ nItemId ] = rStr; 291 ++nItemId; 292 } 293 } 294 295 // entry for LANGUAGE_NONE 296 ++nItemId; 297 pPopupMenu->InsertItem( nItemId, String(FwlResId( STR_LANGSTATUS_NONE )) ); 298 aCmd=aCmd_Language; 299 aCmd.AppendAscii("LANGUAGE_NONE"); 300 pPopupMenu->SetItemCommand( nItemId, aCmd ); 301 302 // entry for 'Reset to default language' 303 ++nItemId; 304 pPopupMenu->InsertItem( nItemId, String(FwlResId( STR_RESET_TO_DEFAULT_LANGUAGE )) ); 305 aCmd=aCmd_Language; 306 aCmd.AppendAscii("RESET_LANGUAGES"); 307 pPopupMenu->SetItemCommand( nItemId, aCmd ); 308 309 // entry for opening the Format/Character dialog 310 ++nItemId; 311 pPopupMenu->InsertItem( nItemId, String(FwlResId( STR_LANGSTATUS_MORE ))); 312 pPopupMenu->SetItemCommand( nItemId, aCmd_Dialog ); 313 } 314 315 316 void SAL_CALL LanguageSelectionMenuController::updatePopupMenu() throw ( ::com::sun::star::uno::RuntimeException ) 317 { 318 svt::PopupMenuControllerBase::updatePopupMenu(); 319 320 // Force status update to get information about the current languages 321 osl::ClearableMutexGuard aLock( m_aMutex ); 322 Reference< XDispatch > xDispatch( m_xLanguageDispatch ); 323 com::sun::star::util::URL aTargetURL; 324 aTargetURL.Complete = m_aLangStatusCommandURL; 325 m_xURLTransformer->parseStrict( aTargetURL ); 326 aLock.clear(); 327 328 if ( xDispatch.is() ) 329 { 330 xDispatch->addStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); 331 xDispatch->removeStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); 332 } 333 334 // TODO: Fill menu with the information retrieved by the status update 335 336 if( m_aCommandURL.equalsAscii( ".uno:SetLanguageSelectionMenu" )) 337 { 338 fillPopupMenu(m_xPopupMenu, MODE_SetLanguageSelectionMenu ); 339 } 340 else if( m_aCommandURL.equalsAscii( ".uno:SetLanguageParagraphMenu" )) 341 { 342 fillPopupMenu(m_xPopupMenu, MODE_SetLanguageParagraphMenu ); 343 } 344 else if( m_aCommandURL.equalsAscii( ".uno:SetLanguageAllTextMenu" )) 345 { 346 fillPopupMenu(m_xPopupMenu, MODE_SetLanguageAllTextMenu ); 347 } 348 } 349 350 // XInitialization 351 void SAL_CALL LanguageSelectionMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) 352 { 353 osl::MutexGuard aLock( m_aMutex ); 354 355 sal_Bool bInitialized( m_bInitialized ); 356 if ( !bInitialized ) 357 { 358 svt::PopupMenuControllerBase::initialize(aArguments); 359 360 if ( m_bInitialized ) 361 { 362 m_aLangStatusCommandURL = OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:LanguageStatus" )); 363 m_aMenuCommandURL_Lang = m_aLangStatusCommandURL; 364 m_aMenuCommandURL_Font = OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontDialog" )); 365 m_aMenuCommandURL_CharDlgForParagraph = OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontDialogForParagraph" )); 366 } 367 } 368 } 369 370 } 371 372 /* vim: set noet sw=4 ts=4: */ 373