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 #ifndef __FRAMEWORK_HELPER_TITLEBARUPDATE_HXX_ 32 #include <helper/titlebarupdate.hxx> 33 #endif 34 35 //_________________________________________________________________________________________________________________ 36 // my own includes 37 //_________________________________________________________________________________________________________________ 38 39 #ifndef __FRAMEWORK_PATTERN_WINDOW_HXX_ 40 #include <pattern/window.hxx> 41 #endif 42 43 #ifndef __FRAMEWORK_THREADHELP_WRITEGUARD_HXX_ 44 #include <threadhelp/writeguard.hxx> 45 #endif 46 47 #ifndef __FRAMEWORK_THREADHELP_READGUARD_HXX_ 48 #include <threadhelp/readguard.hxx> 49 #endif 50 51 #ifndef __FRAMEWORK_MACROS_GENERIC_HXX_ 52 #include <macros/generic.hxx> 53 #endif 54 55 #ifndef __FRAMEWORK_SERVICES_H_ 56 #include <services.h> 57 #endif 58 59 #ifndef __FRAMEWORK_PROPETIES_H_ 60 #include <properties.h> 61 #endif 62 63 //_________________________________________________________________________________________________________________ 64 // interface includes 65 //_________________________________________________________________________________________________________________ 66 67 #ifndef _COM_SUN_STAR_AWT_XWINDOW_HPP_ 68 #include <com/sun/star/awt/XWindow.hpp> 69 #endif 70 71 #ifndef _COM_SUN_STAR_LANG_XSERVICXEINFO_HPP_ 72 #include <com/sun/star/lang/XServiceInfo.hpp> 73 #endif 74 75 #ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_ 76 #include <com/sun/star/lang/IllegalArgumentException.hpp> 77 #endif 78 79 #ifndef _COM_SUN_STAR_FRAME_XMODULEMANAGER_HPP_ 80 #include <com/sun/star/frame/XModuleManager.hpp> 81 #endif 82 83 #ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_ 84 #include <com/sun/star/container/XNameAccess.hpp> 85 #endif 86 87 #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ 88 #include <com/sun/star/beans/XPropertySet.hpp> 89 #endif 90 91 #ifndef _COM_SUN_STAR_BEANS_XMATERIALHOLDER_HPP_ 92 #include <com/sun/star/beans/XMaterialHolder.hpp> 93 #endif 94 95 #ifndef _COM_SUN_STAR_FRAME_XTITLECHANGEBROADCASTER_HPP_ 96 #include <com/sun/star/frame/XTitleChangeBroadcaster.hpp> 97 #endif 98 99 #ifndef _COM_SUN_STAR_BEANS_NAMEDVALUE_HPP_ 100 #include <com/sun/star/beans/NamedValue.hpp> 101 #endif 102 103 //_________________________________________________________________________________________________________________ 104 // other includes 105 //_________________________________________________________________________________________________________________ 106 107 #include <comphelper/sequenceashashmap.hxx> 108 #include <unotools/configmgr.hxx> 109 #include <unotools/bootstrap.hxx> 110 #include <vcl/window.hxx> 111 #include <vcl/syswin.hxx> 112 #include <toolkit/unohlp.hxx> 113 #include <vcl/svapp.hxx> 114 #include <vcl/wrkwin.hxx> 115 #include <tools/diagnose_ex.h> 116 117 //_________________________________________________________________________________________________________________ 118 // namespace 119 120 namespace framework{ 121 122 //_________________________________________________________________________________________________________________ 123 // const 124 125 static const ::sal_Int32 INVALID_ICON_ID = -1; 126 static const ::sal_Int32 DEFAULT_ICON_ID = 0; 127 128 //_________________________________________________________________________________________________________________ 129 // definitions 130 131 //***************************************************************************************************************** 132 // XInterface, XTypeProvider 133 134 DEFINE_XINTERFACE_5(TitleBarUpdate , 135 OWeakObject , 136 DIRECT_INTERFACE (css::lang::XTypeProvider ), 137 DIRECT_INTERFACE (css::lang::XInitialization ), 138 DIRECT_INTERFACE (css::frame::XFrameActionListener ), 139 DIRECT_INTERFACE (css::frame::XTitleChangeListener ), 140 DERIVED_INTERFACE(css::lang::XEventListener,css::frame::XFrameActionListener)) 141 142 DEFINE_XTYPEPROVIDER_5(TitleBarUpdate , 143 css::lang::XTypeProvider , 144 css::lang::XInitialization , 145 css::frame::XFrameActionListener, 146 css::frame::XTitleChangeListener, 147 css::lang::XEventListener ) 148 149 //***************************************************************************************************************** 150 TitleBarUpdate::TitleBarUpdate(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) 151 : ThreadHelpBase (&Application::GetSolarMutex()) 152 , m_xSMGR (xSMGR ) 153 , m_xFrame ( ) 154 { 155 } 156 157 //***************************************************************************************************************** 158 TitleBarUpdate::~TitleBarUpdate() 159 { 160 } 161 162 //***************************************************************************************************************** 163 void SAL_CALL TitleBarUpdate::initialize(const css::uno::Sequence< css::uno::Any >& lArguments) 164 throw(css::uno::Exception , 165 css::uno::RuntimeException) 166 { 167 // check arguments 168 css::uno::Reference< css::frame::XFrame > xFrame; 169 if (lArguments.getLength() < 1) 170 throw css::lang::IllegalArgumentException( 171 DECLARE_ASCII("Empty argument list!"), 172 static_cast< ::cppu::OWeakObject* >(this), 173 1); 174 175 lArguments[0] >>= xFrame; 176 if (!xFrame.is()) 177 throw css::lang::IllegalArgumentException( 178 DECLARE_ASCII("No valid frame specified!"), 179 static_cast< ::cppu::OWeakObject* >(this), 180 1); 181 182 // SYNCHRONIZED -> 183 WriteGuard aWriteLock(m_aLock); 184 // hold the frame as weak reference(!) so it can die everytimes :-) 185 m_xFrame = xFrame; 186 aWriteLock.unlock(); 187 // <- SYNCHRONIZED 188 189 // start listening 190 xFrame->addFrameActionListener(this); 191 192 css::uno::Reference< css::frame::XTitleChangeBroadcaster > xBroadcaster(xFrame, css::uno::UNO_QUERY); 193 if (xBroadcaster.is ()) 194 xBroadcaster->addTitleChangeListener (this); 195 } 196 197 //***************************************************************************************************************** 198 void SAL_CALL TitleBarUpdate::frameAction(const css::frame::FrameActionEvent& aEvent) 199 throw(css::uno::RuntimeException) 200 { 201 // we are interested on events only, which must trigger a title bar update 202 // because component was changed. 203 if ( 204 (aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED ) || 205 (aEvent.Action == css::frame::FrameAction_COMPONENT_REATTACHED) || 206 (aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) 207 ) 208 { 209 impl_forceUpdate (); 210 } 211 } 212 213 //***************************************************************************************************************** 214 void SAL_CALL TitleBarUpdate::titleChanged(const css::frame::TitleChangedEvent& /* aEvent */) 215 throw (css::uno::RuntimeException) 216 { 217 impl_forceUpdate (); 218 } 219 220 //***************************************************************************************************************** 221 void SAL_CALL TitleBarUpdate::disposing(const css::lang::EventObject&) 222 throw(css::uno::RuntimeException) 223 { 224 // nothing todo here - because we hold the frame as weak reference only 225 } 226 227 //***************************************************************************************************************** 228 ::sal_Bool TitleBarUpdate::implst_getModuleInfo(const css::uno::Reference< css::frame::XFrame >& xFrame, 229 TModuleInfo& rInfo ) 230 { 231 if ( ! xFrame.is ()) 232 return sal_False; 233 234 // SYNCHRONIZED -> 235 ReadGuard aReadLock(m_aLock); 236 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 237 aReadLock.unlock(); 238 // <- SYNCHRONIZED 239 240 try 241 { 242 css::uno::Reference< css::frame::XModuleManager > xModuleManager( 243 xSMGR->createInstance(SERVICENAME_MODULEMANAGER), 244 css::uno::UNO_QUERY_THROW); 245 246 css::uno::Reference< css::container::XNameAccess > xConfig( 247 xModuleManager, 248 css::uno::UNO_QUERY_THROW); 249 250 rInfo.sID = xModuleManager->identify(xFrame); 251 ::comphelper::SequenceAsHashMap lProps = xConfig->getByName (rInfo.sID); 252 253 rInfo.sUIName = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_UINAME, ::rtl::OUString()); 254 rInfo.nIcon = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_ICON , INVALID_ICON_ID ); 255 256 // Note: If we could retrieve a module id ... everything is OK. 257 // UIName and Icon ID are optional values ! 258 ::sal_Bool bSuccess = (rInfo.sID.getLength () > 0); 259 return bSuccess; 260 } 261 catch(const css::uno::Exception&) 262 {} 263 264 return sal_False; 265 } 266 267 //***************************************************************************************************************** 268 void TitleBarUpdate::impl_forceUpdate() 269 { 270 // SYNCHRONIZED -> 271 ReadGuard aReadLock(m_aLock); 272 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR ; 273 css::uno::Reference< css::frame::XFrame > xFrame(m_xFrame.get(), css::uno::UNO_QUERY); 274 aReadLock.unlock(); 275 // <- SYNCHRONIZED 276 277 // frame already gone ? We hold it weak only ... 278 if ( ! xFrame.is()) 279 return; 280 281 // no window -> no chance to set/update title and icon 282 css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow(); 283 if ( ! xWindow.is()) 284 return; 285 286 impl_updateIcon (xFrame); 287 impl_updateTitle (xFrame); 288 } 289 290 //***************************************************************************************************************** 291 void TitleBarUpdate::impl_updateIcon(const css::uno::Reference< css::frame::XFrame >& xFrame) 292 { 293 css::uno::Reference< css::frame::XController > xController = xFrame->getController (); 294 css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow (); 295 296 if ( 297 ( ! xController.is() ) || 298 ( ! xWindow.is() ) 299 ) 300 return; 301 302 // a) set default value to an invalid one. So we can start further searches for right icon id, if 303 // first steps failed! 304 sal_Int32 nIcon = INVALID_ICON_ID; 305 306 // b) try to find information on controller property set directly 307 // Don't forget to catch possible exceptions - because these property is an optional one! 308 css::uno::Reference< css::beans::XPropertySet > xSet( xController, css::uno::UNO_QUERY ); 309 if ( xSet.is() ) 310 { 311 try 312 { 313 css::uno::Reference< css::beans::XPropertySetInfo > const xPSI( xSet->getPropertySetInfo(), css::uno::UNO_SET_THROW ); 314 if ( xPSI->hasPropertyByName( CONTROLLER_PROPNAME_ICONID ) ) 315 xSet->getPropertyValue( CONTROLLER_PROPNAME_ICONID ) >>= nIcon; 316 } 317 catch(const css::uno::Exception&) 318 { 319 DBG_UNHANDLED_EXCEPTION(); 320 } 321 } 322 323 // c) if b) failed ... identify the used module and retrieve set icon from module config. 324 // Tirck :-) Module was already specified outside and aInfo contains all needed informations. 325 if ( nIcon == INVALID_ICON_ID ) 326 { 327 TModuleInfo aInfo; 328 if (implst_getModuleInfo(xFrame, aInfo)) 329 nIcon = aInfo.nIcon; 330 } 331 332 // d) if all steps failed - use fallback :-) 333 // ... means using the global staroffice icon 334 if( nIcon == INVALID_ICON_ID ) 335 nIcon = DEFAULT_ICON_ID; 336 337 // e) set icon on container window now 338 // Don't forget SolarMutex! We use vcl directly :-( 339 // Check window pointer for right WorkWindow class too!!! 340 341 // VCL SYNCHRONIZED -> 342 ::vos::OClearableGuard aSolarLock( Application::GetSolarMutex() ); 343 344 Window* pWindow = (VCLUnoHelper::GetWindow( xWindow )); 345 if ( 346 ( pWindow ) && 347 ( pWindow->GetType() == WINDOW_WORKWINDOW ) 348 ) 349 { 350 WorkWindow* pWorkWindow = (WorkWindow*)pWindow; 351 pWorkWindow->SetIcon( (sal_uInt16)nIcon ); 352 353 css::uno::Reference< css::frame::XModel > xModel = xController->getModel(); 354 rtl::OUString aURL; 355 if( xModel.is() ) 356 aURL = xModel->getURL(); 357 pWorkWindow->SetRepresentedURL( aURL ); 358 } 359 360 aSolarLock.clear(); 361 // <- VCL SYNCHRONIZED 362 } 363 364 //***************************************************************************************************************** 365 void TitleBarUpdate::impl_updateTitle(const css::uno::Reference< css::frame::XFrame >& xFrame) 366 { 367 // no window ... no chance to set any title -> return 368 css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow (); 369 if ( ! xWindow.is() ) 370 return; 371 372 css::uno::Reference< css::frame::XTitle > xTitle(xFrame, css::uno::UNO_QUERY); 373 if ( ! xTitle.is() ) 374 return; 375 376 const ::rtl::OUString sTitle = xTitle->getTitle (); 377 378 // VCL SYNCHRONIZED -> 379 ::vos::OClearableGuard aSolarLock( Application::GetSolarMutex() ); 380 381 Window* pWindow = (VCLUnoHelper::GetWindow( xWindow )); 382 if ( 383 ( pWindow ) && 384 ( pWindow->GetType() == WINDOW_WORKWINDOW ) 385 ) 386 { 387 WorkWindow* pWorkWindow = (WorkWindow*)pWindow; 388 pWorkWindow->SetText( sTitle ); 389 } 390 391 aSolarLock.clear(); 392 // <- VCL SYNCHRONIZED 393 } 394 395 } // namespace framework 396