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 #include "services/taskcreatorsrv.hxx" 31 32 //_______________________________________________ 33 // own includes 34 #include <helper/persistentwindowstate.hxx> 35 #include <helper/tagwindowasmodified.hxx> 36 #include <helper/titlebarupdate.hxx> 37 #include <threadhelp/readguard.hxx> 38 #include <threadhelp/writeguard.hxx> 39 #include <loadenv/targethelper.hxx> 40 #include <services.h> 41 42 //_______________________________________________ 43 // interface includes 44 #include <com/sun/star/frame/XFrame.hpp> 45 #include <com/sun/star/frame/XController.hpp> 46 #include <com/sun/star/frame/XModel.hpp> 47 #include <com/sun/star/frame/XDesktop.hpp> 48 #include <com/sun/star/awt/XTopWindow.hpp> 49 #include <com/sun/star/awt/WindowDescriptor.hpp> 50 #include <com/sun/star/awt/WindowAttribute.hpp> 51 #include <com/sun/star/awt/VclWindowPeerAttribute.hpp> 52 53 //_______________________________________________ 54 // other includes 55 #include <svtools/colorcfg.hxx> 56 #include <vcl/svapp.hxx> 57 58 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ 59 #include <toolkit/unohlp.hxx> 60 #endif 61 #include <vcl/window.hxx> 62 63 //_______________________________________________ 64 // namespaces 65 66 namespace framework 67 { 68 69 //----------------------------------------------- 70 const ::rtl::OUString TaskCreatorService::ARGUMENT_PARENTFRAME = ::rtl::OUString::createFromAscii("ParentFrame" ); // XFrame 71 const ::rtl::OUString TaskCreatorService::ARGUMENT_FRAMENAME = ::rtl::OUString::createFromAscii("FrameName" ); // OUString 72 const ::rtl::OUString TaskCreatorService::ARGUMENT_MAKEVISIBLE = ::rtl::OUString::createFromAscii("MakeVisible" ); // sal_Bool 73 const ::rtl::OUString TaskCreatorService::ARGUMENT_CREATETOPWINDOW = ::rtl::OUString::createFromAscii("CreateTopWindow" ); // sal_Bool 74 const ::rtl::OUString TaskCreatorService::ARGUMENT_POSSIZE = ::rtl::OUString::createFromAscii("PosSize" ); // Rectangle 75 const ::rtl::OUString TaskCreatorService::ARGUMENT_CONTAINERWINDOW = ::rtl::OUString::createFromAscii("ContainerWindow" ); // XWindow 76 const ::rtl::OUString TaskCreatorService::ARGUMENT_SUPPORTPERSISTENTWINDOWSTATE = ::rtl::OUString::createFromAscii("SupportPersistentWindowState" ); // sal_Bool 77 const ::rtl::OUString TaskCreatorService::ARGUMENT_ENABLE_TITLEBARUPDATE = ::rtl::OUString::createFromAscii("EnableTitleBarUpdate" ); // sal_Bool 78 79 //----------------------------------------------- 80 DEFINE_XINTERFACE_3(TaskCreatorService , 81 OWeakObject , 82 DIRECT_INTERFACE(css::lang::XTypeProvider ), 83 DIRECT_INTERFACE(css::lang::XServiceInfo ), 84 DIRECT_INTERFACE(css::lang::XSingleServiceFactory)) 85 86 //----------------------------------------------- 87 DEFINE_XTYPEPROVIDER_3(TaskCreatorService , 88 css::lang::XTypeProvider , 89 css::lang::XServiceInfo , 90 css::lang::XSingleServiceFactory) 91 92 //----------------------------------------------- 93 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(TaskCreatorService , 94 ::cppu::OWeakObject , 95 SERVICENAME_TASKCREATOR , 96 IMPLEMENTATIONNAME_FWK_TASKCREATOR) 97 98 //----------------------------------------------- 99 DEFINE_INIT_SERVICE( 100 TaskCreatorService, 101 { 102 /*Attention 103 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance() 104 to create a new instance of this class by our own supported service factory. 105 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations! 106 */ 107 } 108 ) 109 110 //----------------------------------------------- 111 TaskCreatorService::TaskCreatorService(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) 112 : ThreadHelpBase (&Application::GetSolarMutex()) 113 , ::cppu::OWeakObject( ) 114 , m_xSMGR (xSMGR ) 115 { 116 } 117 118 //----------------------------------------------- 119 TaskCreatorService::~TaskCreatorService() 120 { 121 } 122 123 //----------------------------------------------- 124 css::uno::Reference< css::uno::XInterface > SAL_CALL TaskCreatorService::createInstance() 125 throw(css::uno::Exception , 126 css::uno::RuntimeException) 127 { 128 return createInstanceWithArguments(css::uno::Sequence< css::uno::Any >()); 129 } 130 131 //----------------------------------------------- 132 css::uno::Reference< css::uno::XInterface > SAL_CALL TaskCreatorService::createInstanceWithArguments(const css::uno::Sequence< css::uno::Any >& lArguments) 133 throw(css::uno::Exception , 134 css::uno::RuntimeException) 135 { 136 static ::rtl::OUString DEFAULTVAL_FRAMENAME = ::rtl::OUString(); 137 static sal_Bool DEFAULTVAL_MAKEVISIBLE = sal_False; 138 static sal_Bool DEFAULTVAL_CREATETOPWINDOW = sal_True; 139 static css::awt::Rectangle DEFAULTVAL_POSSIZE = css::awt::Rectangle(0, 0, 0, 0); // only possize=[0,0,0,0] triggers default handling of vcl ! 140 static sal_Bool DEFAULTVAL_SUPPORTPERSSISTENTWINDOWSTATE = sal_False; 141 static sal_Bool DEFAULTVAL_ENABLE_TITLEBARUPDATE = sal_True; 142 143 ::comphelper::SequenceAsHashMap lArgs(lArguments); 144 145 css::uno::Reference< css::frame::XFrame > xParentFrame = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_PARENTFRAME , css::uno::Reference< css::frame::XFrame >()); 146 ::rtl::OUString sFrameName = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_FRAMENAME , DEFAULTVAL_FRAMENAME ); 147 sal_Bool bVisible = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_MAKEVISIBLE , DEFAULTVAL_MAKEVISIBLE ); 148 sal_Bool bCreateTopWindow = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_CREATETOPWINDOW , DEFAULTVAL_CREATETOPWINDOW ); 149 css::awt::Rectangle aPosSize = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_POSSIZE , DEFAULTVAL_POSSIZE ); 150 css::uno::Reference< css::awt::XWindow > xContainerWindow = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_CONTAINERWINDOW , css::uno::Reference< css::awt::XWindow >() ); 151 sal_Bool bSupportPersistentWindowState = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_SUPPORTPERSISTENTWINDOWSTATE , DEFAULTVAL_SUPPORTPERSSISTENTWINDOWSTATE ); 152 sal_Bool bEnableTitleBarUpdate = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_ENABLE_TITLEBARUPDATE , DEFAULTVAL_ENABLE_TITLEBARUPDATE ); 153 154 /* SAFE { */ 155 ReadGuard aReadLock( m_aLock ); 156 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 157 aReadLock.unlock(); 158 /* } SAFE */ 159 160 // We use FrameName property to set it as API name of the new created frame later. 161 // But those frame names must be different from the set of special target names as e.g. _blank, _self etcpp ! 162 ::rtl::OUString sRightName = impl_filterNames(sFrameName); 163 164 // if no external frame window was given ... create a new one. 165 if ( ! xContainerWindow.is()) 166 { 167 css::uno::Reference< css::awt::XWindow > xParentWindow; 168 if (xParentFrame.is()) 169 xParentWindow = xParentFrame->getContainerWindow(); 170 171 // Parent has no own window ... 172 // So we have to create a top level window always ! 173 if ( ! xParentWindow.is()) 174 bCreateTopWindow = sal_True; 175 176 xContainerWindow = implts_createContainerWindow(xParentWindow, aPosSize, bCreateTopWindow); 177 } 178 179 //-------------------> 180 // HACK #125187# + #i53630# 181 // Mark all document windows as "special ones", so VCL can bind 182 // special features to it. Because VCL doesnt know anything about documents ... 183 // Note: Doing so it's no longer supported, that e.g. our wizards can use findFrame(_blank) 184 // to create it's previes frames. They must do it manually by using WindowDescriptor+Toolkit! 185 css::uno::Reference< css::frame::XDesktop > xDesktop(xParentFrame, css::uno::UNO_QUERY); 186 ::sal_Bool bTopLevelDocumentWindow = ( 187 (sRightName.getLength () < 1) && 188 ( 189 (! xParentFrame.is() ) || 190 ( xDesktop.is() ) 191 ) 192 ); 193 if (bTopLevelDocumentWindow) 194 implts_applyDocStyleToWindow(xContainerWindow); 195 //-------------------> 196 197 // create the new frame 198 css::uno::Reference< css::frame::XFrame > xFrame = implts_createFrame(xParentFrame, xContainerWindow, sRightName); 199 200 // special freature: 201 // A special listener will restore pos/size states in case 202 // a component was loaded into the frame first time. 203 if (bSupportPersistentWindowState) 204 implts_establishWindowStateListener(xFrame); 205 206 // special feature: On Mac we need tagging the window in case 207 // the underlying model was modified. 208 // VCL will ignore our calls in case different platform then Mac 209 // is used ... 210 if (bTopLevelDocumentWindow) 211 implts_establishDocModifyListener (xFrame); 212 213 // special freature: 214 // A special listener will update title bar (text and icon) 215 // if component of frame will be changed. 216 if (bEnableTitleBarUpdate) 217 implts_establishTitleBarUpdate(xFrame); 218 219 // Make it visible directly here ... 220 // if its required from outside. 221 if (bVisible) 222 xContainerWindow->setVisible(bVisible); 223 224 return css::uno::Reference< css::uno::XInterface >(xFrame, css::uno::UNO_QUERY_THROW); 225 } 226 227 //----------------------------------------------- 228 void TaskCreatorService::implts_applyDocStyleToWindow(const css::uno::Reference< css::awt::XWindow >& xWindow) const 229 { 230 // SYNCHRONIZED -> 231 ::vos::OClearableGuard aSolarGuard(Application::GetSolarMutex()); 232 Window* pVCLWindow = VCLUnoHelper::GetWindow(xWindow); 233 if (pVCLWindow) 234 pVCLWindow->SetExtendedStyle(WB_EXT_DOCUMENT); 235 aSolarGuard.clear(); 236 // <- SYNCHRONIZED 237 } 238 239 //----------------------------------------------- 240 css::uno::Reference< css::awt::XWindow > TaskCreatorService::implts_createContainerWindow( const css::uno::Reference< css::awt::XWindow >& xParentWindow , 241 const css::awt::Rectangle& aPosSize , 242 sal_Bool bTopWindow ) 243 { 244 // SAFE -> 245 ReadGuard aReadLock( m_aLock ); 246 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 247 aReadLock.unlock(); 248 // <- SAFE 249 250 // get toolkit to create task container window 251 css::uno::Reference< css::awt::XToolkit > xToolkit( xSMGR->createInstance( SERVICENAME_VCLTOOLKIT ), css::uno::UNO_QUERY_THROW); 252 253 // Check if child frames can be created realy. We need at least a valid window at the parent frame ... 254 css::uno::Reference< css::awt::XWindowPeer > xParentWindowPeer; 255 if ( ! bTopWindow) 256 { 257 if ( ! xParentWindow.is()) 258 bTopWindow = sal_False; 259 else 260 xParentWindowPeer = css::uno::Reference< css::awt::XWindowPeer >(xParentWindow, css::uno::UNO_QUERY_THROW); 261 } 262 263 // describe window properties. 264 css::awt::WindowDescriptor aDescriptor; 265 if (bTopWindow) 266 { 267 aDescriptor.Type = css::awt::WindowClass_TOP ; 268 aDescriptor.WindowServiceName = DECLARE_ASCII("window") ; 269 aDescriptor.ParentIndex = -1 ; 270 aDescriptor.Parent = css::uno::Reference< css::awt::XWindowPeer >() ; 271 aDescriptor.Bounds = aPosSize ; 272 aDescriptor.WindowAttributes = css::awt::WindowAttribute::BORDER | 273 css::awt::WindowAttribute::MOVEABLE | 274 css::awt::WindowAttribute::SIZEABLE | 275 css::awt::WindowAttribute::CLOSEABLE | 276 css::awt::VclWindowPeerAttribute::CLIPCHILDREN ; 277 } 278 else 279 { 280 aDescriptor.Type = css::awt::WindowClass_TOP ; 281 aDescriptor.WindowServiceName = DECLARE_ASCII("dockingwindow") ; 282 aDescriptor.ParentIndex = 1 ; 283 aDescriptor.Parent = xParentWindowPeer ; 284 aDescriptor.Bounds = aPosSize ; 285 aDescriptor.WindowAttributes = css::awt::VclWindowPeerAttribute::CLIPCHILDREN ; 286 } 287 288 // create a new blank container window and get access to parent container to append new created task. 289 css::uno::Reference< css::awt::XWindowPeer > xPeer = xToolkit->createWindow( aDescriptor ); 290 css::uno::Reference< css::awt::XWindow > xWindow ( xPeer, css::uno::UNO_QUERY ); 291 if ( ! xWindow.is()) 292 throw css::uno::Exception(::rtl::OUString::createFromAscii("TaskCreator service was not able to create suitable frame window."), 293 static_cast< ::cppu::OWeakObject* >(this)); 294 if (bTopWindow) 295 xPeer->setBackground(::svtools::ColorConfig().GetColorValue(::svtools::APPBACKGROUND).nColor); 296 else 297 xPeer->setBackground(0xffffffff); 298 299 return xWindow; 300 } 301 302 //----------------------------------------------- 303 css::uno::Reference< css::frame::XFrame > TaskCreatorService::implts_createFrame( const css::uno::Reference< css::frame::XFrame >& xParentFrame , 304 const css::uno::Reference< css::awt::XWindow >& xContainerWindow, 305 const ::rtl::OUString& sName ) 306 { 307 // SAFE -> 308 ReadGuard aReadLock( m_aLock ); 309 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 310 aReadLock.unlock(); 311 // <- SAFE 312 313 // create new frame. 314 css::uno::Reference< css::frame::XFrame > xNewFrame( xSMGR->createInstance( SERVICENAME_FRAME ), css::uno::UNO_QUERY_THROW ); 315 316 // Set window on frame. 317 // Do it before calling any other interface methods ... 318 // The new created frame must be initialized before you can do anything else there. 319 xNewFrame->initialize( xContainerWindow ); 320 321 // Put frame to the frame tree. 322 // Note: The property creator/parent will be set on the new putted frame automaticly ... by the parent container. 323 if (xParentFrame.is()) 324 { 325 css::uno::Reference< css::frame::XFramesSupplier > xSupplier (xParentFrame, css::uno::UNO_QUERY_THROW); 326 css::uno::Reference< css::frame::XFrames > xContainer = xSupplier->getFrames(); 327 xContainer->append( xNewFrame ); 328 } 329 330 // Set it's API name (if there is one from outside) 331 if (sName.getLength()) 332 xNewFrame->setName( sName ); 333 334 return xNewFrame; 335 } 336 337 //----------------------------------------------- 338 void TaskCreatorService::implts_establishWindowStateListener( const css::uno::Reference< css::frame::XFrame >& xFrame ) 339 { 340 // SAFE -> 341 ReadGuard aReadLock( m_aLock ); 342 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 343 aReadLock.unlock(); 344 // <- SAFE 345 346 // Special feature: It's allowed for frames using a top level window only! 347 // We must create a special listener service and couple it with the new created task frame. 348 // He will restore or save the window state of it ... 349 // See used classes for further informations too. 350 PersistentWindowState* pPersistentStateHandler = new PersistentWindowState(xSMGR); 351 css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pPersistentStateHandler), css::uno::UNO_QUERY_THROW); 352 353 css::uno::Sequence< css::uno::Any > lInitData(1); 354 lInitData[0] <<= xFrame; 355 xInit->initialize(lInitData); 356 } 357 358 //----------------------------------------------- 359 void TaskCreatorService::implts_establishDocModifyListener( const css::uno::Reference< css::frame::XFrame >& xFrame ) 360 { 361 // SAFE -> 362 ReadGuard aReadLock( m_aLock ); 363 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 364 aReadLock.unlock(); 365 // <- SAFE 366 367 // Special feature: It's allowed for frames using a top level window only! 368 // We must create a special listener service and couple it with the new created task frame. 369 // It will tag the window as modified if the underlying model was modified ... 370 TagWindowAsModified* pTag = new TagWindowAsModified(xSMGR); 371 css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pTag), css::uno::UNO_QUERY_THROW); 372 373 css::uno::Sequence< css::uno::Any > lInitData(1); 374 lInitData[0] <<= xFrame; 375 xInit->initialize(lInitData); 376 } 377 378 //----------------------------------------------- 379 void TaskCreatorService::implts_establishTitleBarUpdate( const css::uno::Reference< css::frame::XFrame >& xFrame ) 380 { 381 // SAFE -> 382 ReadGuard aReadLock( m_aLock ); 383 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 384 aReadLock.unlock(); 385 // <- SAFE 386 387 TitleBarUpdate* pHelper = new TitleBarUpdate (xSMGR); 388 css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pHelper), css::uno::UNO_QUERY_THROW); 389 390 css::uno::Sequence< css::uno::Any > lInitData(1); 391 lInitData[0] <<= xFrame; 392 xInit->initialize(lInitData); 393 } 394 395 //----------------------------------------------- 396 ::rtl::OUString TaskCreatorService::impl_filterNames( const ::rtl::OUString& sName ) 397 { 398 ::rtl::OUString sFiltered; 399 if (TargetHelper::isValidNameForFrame(sName)) 400 sFiltered = sName; 401 return sFiltered; 402 } 403 404 } // namespace framework 405