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