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