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 #include <uielement/controlmenucontroller.hxx> 27 28 //_________________________________________________________________________________________________________________ 29 // my own includes 30 //_________________________________________________________________________________________________________________ 31 #include <threadhelp/resetableguard.hxx> 32 #include "services.h" 33 34 //_________________________________________________________________________________________________________________ 35 // interface includes 36 //_________________________________________________________________________________________________________________ 37 #include <com/sun/star/awt/XDevice.hpp> 38 #include <com/sun/star/beans/PropertyValue.hpp> 39 #include <com/sun/star/awt/MenuItemStyle.hpp> 40 #include <com/sun/star/frame/XDispatchProvider.hpp> 41 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp> 42 #include <com/sun/star/container/XNameContainer.hpp> 43 #include <com/sun/star/beans/XPropertySet.hpp> 44 45 //_________________________________________________________________________________________________________________ 46 // includes of other projects 47 //_________________________________________________________________________________________________________________ 48 49 #include <vcl/menu.hxx> 50 #include <vcl/svapp.hxx> 51 #include <vcl/i18nhelp.hxx> 52 #include <tools/urlobj.hxx> 53 #include <rtl/ustrbuf.hxx> 54 #include <rtl/strbuf.hxx> 55 #include <svl/solar.hrc> 56 #include <tools/rcid.h> 57 #include <vcl/image.hxx> 58 #include <svtools/menuoptions.hxx> 59 #include <dispatch/uieventloghelper.hxx> 60 #include <vos/mutex.hxx> 61 62 // Copied from svx 63 // Function-Id's 64 #define RID_FMSHELL_CONVERSIONMENU (RID_FORMS_START + 4) 65 #define RID_SVXIMGLIST_FMEXPL (RID_FORMS_START + 0) 66 #define RID_SVXIMGLIST_FMEXPL_HC (RID_FORMS_START + 2) 67 68 // Forms - Ids, used to address images from image list 69 #define SID_FMSLOTS_START (SID_SVX_START + 592) 70 #define SID_MORE_FMSLOTS_START (SID_SVX_START + 702) 71 72 #define SID_FM_CONVERTTO_EDIT (SID_MORE_FMSLOTS_START + 32) 73 #define SID_FM_CONVERTTO_BUTTON (SID_MORE_FMSLOTS_START + 33) 74 #define SID_FM_CONVERTTO_FIXEDTEXT (SID_MORE_FMSLOTS_START + 34) 75 #define SID_FM_CONVERTTO_LISTBOX (SID_MORE_FMSLOTS_START + 35) 76 #define SID_FM_CONVERTTO_CHECKBOX (SID_MORE_FMSLOTS_START + 36) 77 #define SID_FM_CONVERTTO_RADIOBUTTON (SID_MORE_FMSLOTS_START + 37) 78 #define SID_FM_CONVERTTO_GROUPBOX (SID_MORE_FMSLOTS_START + 38) 79 #define SID_FM_CONVERTTO_COMBOBOX (SID_MORE_FMSLOTS_START + 39) 80 #define SID_FM_CONVERTTO_GRID (SID_MORE_FMSLOTS_START + 40) 81 #define SID_FM_CONVERTTO_IMAGEBUTTON (SID_MORE_FMSLOTS_START + 41) 82 #define SID_FM_CONVERTTO_FILECONTROL (SID_MORE_FMSLOTS_START + 42) 83 #define SID_FM_CONVERTTO_DATE (SID_MORE_FMSLOTS_START + 43) 84 #define SID_FM_CONVERTTO_TIME (SID_MORE_FMSLOTS_START + 44) 85 #define SID_FM_CONVERTTO_NUMERIC (SID_MORE_FMSLOTS_START + 45) 86 #define SID_FM_CONVERTTO_CURRENCY (SID_MORE_FMSLOTS_START + 46) 87 #define SID_FM_CONVERTTO_PATTERN (SID_MORE_FMSLOTS_START + 47) 88 #define SID_FM_CONVERTTO_IMAGECONTROL (SID_MORE_FMSLOTS_START + 48) 89 #define SID_FM_CONVERTTO_FORMATTED (SID_MORE_FMSLOTS_START + 49) 90 #define SID_FM_CONVERTTO_SCROLLBAR (SID_MORE_FMSLOTS_START + 68) 91 #define SID_FM_CONVERTTO_SPINBUTTON (SID_MORE_FMSLOTS_START + 69) 92 93 #define SID_FM_DATEFIELD (SID_MORE_FMSLOTS_START + 2) 94 #define SID_FM_TIMEFIELD (SID_MORE_FMSLOTS_START + 3) 95 #define SID_FM_NUMERICFIELD (SID_MORE_FMSLOTS_START + 4) 96 #define SID_FM_CURRENCYFIELD (SID_MORE_FMSLOTS_START + 5) 97 #define SID_FM_PATTERNFIELD (SID_MORE_FMSLOTS_START + 6) 98 #define SID_FM_IMAGECONTROL (SID_MORE_FMSLOTS_START + 8) 99 #define SID_FM_FORMATTEDFIELD (SID_MORE_FMSLOTS_START + 26) 100 #define SID_FM_SCROLLBAR (SID_MORE_FMSLOTS_START + 66) 101 #define SID_FM_SPINBUTTON (SID_MORE_FMSLOTS_START + 67) 102 #define SID_FM_CONFIG (SID_FMSLOTS_START + 1) 103 #define SID_FM_PUSHBUTTON (SID_FMSLOTS_START + 2) 104 #define SID_FM_RADIOBUTTON (SID_FMSLOTS_START + 3) 105 #define SID_FM_CHECKBOX (SID_FMSLOTS_START + 4) 106 #define SID_FM_FIXEDTEXT (SID_FMSLOTS_START + 5) 107 #define SID_FM_GROUPBOX (SID_FMSLOTS_START + 6) 108 #define SID_FM_EDIT (SID_FMSLOTS_START + 7) 109 #define SID_FM_LISTBOX (SID_FMSLOTS_START + 8) 110 #define SID_FM_COMBOBOX (SID_FMSLOTS_START + 9) 111 #define SID_FM_URLBUTTON (SID_FMSLOTS_START + 10) 112 #define SID_FM_DBGRID (SID_FMSLOTS_START + 11) 113 #define SID_FM_IMAGEBUTTON (SID_FMSLOTS_START + 12) 114 #define SID_FM_FILECONTROL (SID_FMSLOTS_START + 13) 115 116 sal_Int16 nConvertSlots[] = 117 { 118 SID_FM_CONVERTTO_EDIT, 119 SID_FM_CONVERTTO_BUTTON, 120 SID_FM_CONVERTTO_FIXEDTEXT, 121 SID_FM_CONVERTTO_LISTBOX, 122 SID_FM_CONVERTTO_CHECKBOX, 123 SID_FM_CONVERTTO_RADIOBUTTON, 124 SID_FM_CONVERTTO_GROUPBOX, 125 SID_FM_CONVERTTO_COMBOBOX, 126 // SID_FM_CONVERTTO_GRID, 127 SID_FM_CONVERTTO_IMAGEBUTTON, 128 SID_FM_CONVERTTO_FILECONTROL, 129 SID_FM_CONVERTTO_DATE, 130 SID_FM_CONVERTTO_TIME, 131 SID_FM_CONVERTTO_NUMERIC, 132 SID_FM_CONVERTTO_CURRENCY, 133 SID_FM_CONVERTTO_PATTERN, 134 SID_FM_CONVERTTO_IMAGECONTROL, 135 SID_FM_CONVERTTO_FORMATTED, 136 SID_FM_CONVERTTO_SCROLLBAR, 137 SID_FM_CONVERTTO_SPINBUTTON 138 }; 139 140 sal_Int16 nCreateSlots[] = 141 { 142 SID_FM_EDIT, 143 SID_FM_PUSHBUTTON, 144 SID_FM_FIXEDTEXT, 145 SID_FM_LISTBOX, 146 SID_FM_CHECKBOX, 147 SID_FM_RADIOBUTTON, 148 SID_FM_GROUPBOX, 149 SID_FM_COMBOBOX, 150 // SID_FM_DBGRID, 151 SID_FM_IMAGEBUTTON, 152 SID_FM_FILECONTROL, 153 SID_FM_DATEFIELD, 154 SID_FM_TIMEFIELD, 155 SID_FM_NUMERICFIELD, 156 SID_FM_CURRENCYFIELD, 157 SID_FM_PATTERNFIELD, 158 SID_FM_IMAGECONTROL, 159 SID_FM_FORMATTEDFIELD, 160 SID_FM_SCROLLBAR, 161 SID_FM_SPINBUTTON 162 }; 163 164 const char* aCommands[] = 165 { 166 ".uno:ConvertToEdit", 167 ".uno:ConvertToButton", 168 ".uno:ConvertToFixed", 169 ".uno:ConvertToList", 170 ".uno:ConvertToCheckBox", 171 ".uno:ConvertToRadio", 172 ".uno:ConvertToGroup", 173 ".uno:ConvertToCombo", 174 // ".uno:ConvertToGrid", 175 ".uno:ConvertToImageBtn", 176 ".uno:ConvertToFileControl", 177 ".uno:ConvertToDate", 178 ".uno:ConvertToTime", 179 ".uno:ConvertToNumeric", 180 ".uno:ConvertToCurrency", 181 ".uno:ConvertToPattern", 182 ".uno:ConvertToImageControl", 183 ".uno:ConvertToFormatted", 184 ".uno:ConvertToScrollBar", 185 ".uno:ConvertToSpinButton" 186 }; 187 188 //_________________________________________________________________________________________________________________ 189 // Defines 190 //_________________________________________________________________________________________________________________ 191 // 192 193 using namespace com::sun::star::uno; 194 using namespace com::sun::star::lang; 195 using namespace com::sun::star::frame; 196 using namespace com::sun::star::beans; 197 using namespace com::sun::star::util; 198 using namespace com::sun::star::style; 199 using namespace com::sun::star::container; 200 201 namespace framework 202 { 203 204 DEFINE_XSERVICEINFO_MULTISERVICE ( ControlMenuController , 205 OWeakObject , 206 SERVICENAME_POPUPMENUCONTROLLER , 207 IMPLEMENTATIONNAME_CONTROLMENUCONTROLLER 208 ) 209 210 DEFINE_INIT_SERVICE ( ControlMenuController, {} ) 211 212 ControlMenuController::ControlMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : 213 svt::PopupMenuControllerBase( xServiceManager ), 214 m_pResPopupMenu( 0 ) 215 { 216 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); 217 m_bWasHiContrast = rSettings.GetHighContrastMode(); 218 m_bShowMenuImages = rSettings.GetUseImagesInMenus(); 219 220 } 221 222 ControlMenuController::~ControlMenuController() 223 { 224 } 225 226 // private function 227 void ControlMenuController::updateImagesPopupMenu( PopupMenu* pPopupMenu ) 228 { 229 rtl::OUString aResName( RTL_CONSTASCII_USTRINGPARAM( "svx" )); 230 231 ResMgr* pResMgr = ResMgr::CreateResMgr( rtl::OUStringToOString( aResName, RTL_TEXTENCODING_ASCII_US )); 232 ResId aResId( m_bWasHiContrast ? RID_SVXIMGLIST_FMEXPL_HC : RID_SVXIMGLIST_FMEXPL, *pResMgr ); 233 aResId.SetRT( RSC_IMAGELIST ); 234 235 if ( pResMgr->IsAvailable( aResId )) 236 { 237 ImageList aImageList( aResId ); 238 for ( sal_uInt32 i=0; i < sizeof(nConvertSlots)/sizeof(nConvertSlots[0]); ++i ) 239 { 240 // das entsprechende Image dran 241 if ( m_bShowMenuImages ) 242 pPopupMenu->SetItemImage( nConvertSlots[i], aImageList.GetImage(nCreateSlots[i])); 243 else 244 pPopupMenu->SetItemImage( nConvertSlots[i], Image() ); 245 } 246 } 247 248 delete pResMgr; 249 } 250 251 // private function 252 void ControlMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu ) 253 { 254 VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); 255 PopupMenu* pVCLPopupMenu = 0; 256 257 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); 258 259 resetPopupMenu( rPopupMenu ); 260 if ( pPopupMenu ) 261 pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); 262 263 if ( pVCLPopupMenu && m_pResPopupMenu ) 264 *pVCLPopupMenu = *m_pResPopupMenu; 265 } 266 267 // XEventListener 268 void SAL_CALL ControlMenuController::disposing( const EventObject& ) throw ( RuntimeException ) 269 { 270 Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); 271 272 osl::ResettableMutexGuard aLock( m_aMutex ); 273 m_xFrame.clear(); 274 m_xDispatch.clear(); 275 m_xServiceManager.clear(); 276 277 if ( m_xPopupMenu.is() ) 278 m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); 279 m_xPopupMenu.clear(); 280 delete m_pResPopupMenu; 281 } 282 283 // XStatusListener 284 void SAL_CALL ControlMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException ) 285 { 286 osl::ResettableMutexGuard aLock( m_aMutex ); 287 288 sal_uInt16 nMenuId = 0; 289 for (sal_uInt32 i=0; i < sizeof(aCommands)/sizeof(aCommands[0]); ++i) 290 { 291 if ( Event.FeatureURL.Complete.equalsAscii( aCommands[i] )) 292 { 293 nMenuId = nConvertSlots[i]; 294 break; 295 } 296 } 297 298 if ( nMenuId ) 299 { 300 VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( m_xPopupMenu ); 301 302 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); 303 304 PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); 305 306 if ( !Event.IsEnabled && pVCLPopupMenu->GetItemPos( nMenuId ) != MENU_ITEM_NOTFOUND ) 307 pVCLPopupMenu->RemoveItem( pVCLPopupMenu->GetItemPos( nMenuId )); 308 else if ( Event.IsEnabled && pVCLPopupMenu->GetItemPos( nMenuId ) == MENU_ITEM_NOTFOUND ) 309 { 310 sal_Int16 nSourcePos = m_pResPopupMenu->GetItemPos(nMenuId); 311 sal_Int16 nPrevInSource = nSourcePos; 312 sal_uInt16 nPrevInConversion = MENU_ITEM_NOTFOUND; 313 while (nPrevInSource>0) 314 { 315 sal_Int16 nPrevId = m_pResPopupMenu->GetItemId(--nPrevInSource); 316 317 // do we have the source's predecessor in our conversion menu, too ? 318 nPrevInConversion = pVCLPopupMenu->GetItemPos( nPrevId ); 319 if ( nPrevInConversion != MENU_ITEM_NOTFOUND ) 320 break; 321 } 322 323 if ( MENU_ITEM_NOTFOUND == nPrevInConversion ) 324 // none of the items which precede the nSID-slot in the source menu are present in our conversion menu 325 nPrevInConversion = sal::static_int_cast< sal_uInt16 >(-1); // put the item at the first position 326 327 pVCLPopupMenu->InsertItem( nMenuId, m_pResPopupMenu->GetItemText( nMenuId ), m_pResPopupMenu->GetItemBits( nMenuId ), ++nPrevInConversion ); 328 pVCLPopupMenu->SetItemImage( nMenuId, m_pResPopupMenu->GetItemImage( nMenuId )); 329 pVCLPopupMenu->SetHelpId( nMenuId, m_pResPopupMenu->GetHelpId( nMenuId )); 330 } 331 } 332 } 333 334 // XMenuListener 335 void ControlMenuController::impl_select(const Reference< XDispatch >& /*_xDispatch*/,const ::com::sun::star::util::URL& aURL) 336 { 337 UrlToDispatchMap::iterator pIter = m_aURLToDispatchMap.find( aURL.Complete ); 338 if ( pIter != m_aURLToDispatchMap.end() ) 339 { 340 Sequence<PropertyValue> aArgs; 341 Reference< XDispatch > xDispatch = pIter->second; 342 if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# 343 UiEventLogHelper(::rtl::OUString::createFromAscii("ControlMenuController")).log(m_xServiceManager, m_xFrame, aURL, aArgs); 344 if ( xDispatch.is() ) 345 xDispatch->dispatch( aURL, aArgs ); 346 } 347 } 348 349 void SAL_CALL ControlMenuController::activate( const css::awt::MenuEvent& ) throw (RuntimeException) 350 { 351 osl::ResettableMutexGuard aLock( m_aMutex ); 352 353 if ( m_xPopupMenu.is() ) 354 { 355 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); 356 357 // Check if some modes have changed so we have to update our menu images 358 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); 359 sal_Bool bIsHiContrast = rSettings.GetHighContrastMode(); 360 sal_Bool bShowMenuImages = rSettings.GetUseImagesInMenus(); 361 sal_Bool bUpdateImages = (( m_bWasHiContrast != bIsHiContrast ) || ( bShowMenuImages != m_bShowMenuImages )); 362 363 if ( bUpdateImages ) 364 { 365 // The mode has changed or the complete menu so we have to retrieve all images again 366 m_bWasHiContrast = bIsHiContrast; 367 m_bShowMenuImages = bShowMenuImages; 368 369 VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXPopupMenu::GetImplementation( m_xPopupMenu ); 370 if ( pPopupMenu ) 371 { 372 PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); 373 if ( pVCLPopupMenu && bUpdateImages ) 374 updateImagesPopupMenu( pVCLPopupMenu ); 375 } 376 } 377 } 378 } 379 380 // XPopupMenuController 381 void ControlMenuController::impl_setPopupMenu() 382 { 383 if ( m_pResPopupMenu == 0 ) 384 { 385 rtl::OStringBuffer aBuf( 32 ); 386 aBuf.append( "svx" ); 387 388 ResMgr* pResMgr = ResMgr::CreateResMgr( aBuf.getStr() ); 389 if ( pResMgr ) 390 { 391 ResId aResId( RID_FMSHELL_CONVERSIONMENU, *pResMgr ); 392 aResId.SetRT( RSC_MENU ); 393 if ( pResMgr->IsAvailable( aResId )) 394 m_pResPopupMenu = new PopupMenu( aResId ); 395 396 updateImagesPopupMenu( m_pResPopupMenu ); 397 delete pResMgr; 398 } 399 } // if ( m_pResPopupMenu == 0 ) 400 } 401 402 void SAL_CALL ControlMenuController::updatePopupMenu() throw (::com::sun::star::uno::RuntimeException) 403 { 404 osl::ResettableMutexGuard aLock( m_aMutex ); 405 406 throwIfDisposed(); 407 408 if ( m_xFrame.is() && m_xPopupMenu.is() ) 409 { 410 URL aTargetURL; 411 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); 412 fillPopupMenu( m_xPopupMenu ); 413 m_aURLToDispatchMap.free(); 414 415 for (sal_uInt32 i=0; i<sizeof(aCommands)/sizeof(aCommands[0]); ++i) 416 { 417 aTargetURL.Complete = rtl::OUString::createFromAscii( aCommands[i] ); 418 m_xURLTransformer->parseStrict( aTargetURL ); 419 420 Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); 421 if ( xDispatch.is() ) 422 { 423 xDispatch->addStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); 424 xDispatch->removeStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); 425 m_aURLToDispatchMap.insert( UrlToDispatchMap::value_type( aTargetURL.Complete, xDispatch )); 426 } 427 } 428 } 429 } 430 431 // XInitialization 432 void SAL_CALL ControlMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) 433 { 434 osl::ResettableMutexGuard aLock( m_aMutex ); 435 svt::PopupMenuControllerBase::initialize(aArguments); 436 m_aBaseURL = ::rtl::OUString(); 437 } 438 439 } 440