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/Frame.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/helper/vclunohelper.hxx>
44 : #include <vcl/window.hxx>
45 :
46 : //_______________________________________________
47 : // namespaces
48 :
49 : namespace framework
50 : {
51 : //-----------------------------------------------
52 8327 : 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 686 : DEFINE_XSERVICEINFO_ONEINSTANCESERVICE_2(TaskCreatorService ,
66 : ::cppu::OWeakObject ,
67 : "com.sun.star.frame.TaskCreator",
68 : IMPLEMENTATIONNAME_FWK_TASKCREATOR)
69 :
70 : //-----------------------------------------------
71 61 : 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 information!
78 : */
79 : }
80 : )
81 :
82 : //-----------------------------------------------
83 61 : TaskCreatorService::TaskCreatorService(const css::uno::Reference< css::uno::XComponentContext >& xContext)
84 61 : : ThreadHelpBase (&Application::GetSolarMutex())
85 : , ::cppu::OWeakObject( )
86 122 : , m_xContext (xContext )
87 : {
88 61 : }
89 :
90 : //-----------------------------------------------
91 120 : TaskCreatorService::~TaskCreatorService()
92 : {
93 120 : }
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 1103 : 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 1103 : ::comphelper::SequenceAsHashMap lArgs(lArguments);
109 :
110 2206 : css::uno::Reference< css::frame::XFrame > xParentFrame = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_PARENTFRAME) , css::uno::Reference< css::frame::XFrame >());
111 2206 : OUString sFrameName = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_FRAMENAME) , OUString() );
112 1103 : sal_Bool bVisible = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_MAKEVISIBLE) , sal_False );
113 1103 : sal_Bool bCreateTopWindow = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_CREATETOPWINDOW) , sal_True );
114 : // only possize=[0,0,0,0] triggers default handling of vcl !
115 1103 : css::awt::Rectangle aPosSize = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_POSSIZE) , css::awt::Rectangle(0, 0, 0, 0) );
116 2206 : css::uno::Reference< css::awt::XWindow > xContainerWindow = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_CONTAINERWINDOW) , css::uno::Reference< css::awt::XWindow >() );
117 1103 : sal_Bool bSupportPersistentWindowState = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_SUPPORTPERSISTENTWINDOWSTATE) , sal_False );
118 1103 : sal_Bool bEnableTitleBarUpdate = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_ENABLE_TITLEBARUPDATE) , sal_True );
119 :
120 : // We use FrameName property to set it as API name of the new created frame later.
121 : // But those frame names must be different from the set of special target names as e.g. _blank, _self etcpp !
122 2206 : OUString sRightName = impl_filterNames(sFrameName);
123 :
124 : // if no external frame window was given ... create a new one.
125 1103 : if ( ! xContainerWindow.is())
126 : {
127 1102 : css::uno::Reference< css::awt::XWindow > xParentWindow;
128 1102 : if (xParentFrame.is())
129 1102 : xParentWindow = xParentFrame->getContainerWindow();
130 :
131 : // Parent has no own window ...
132 : // So we have to create a top level window always !
133 1102 : if ( ! xParentWindow.is())
134 1102 : bCreateTopWindow = sal_True;
135 :
136 1102 : xContainerWindow = implts_createContainerWindow(xParentWindow, aPosSize, bCreateTopWindow);
137 : }
138 :
139 : // #i53630#
140 : // Mark all document windows as "special ones", so VCL can bind
141 : // special features to it. Because VCL doesnt know anything about documents ...
142 : // Note: Doing so it's no longer supported, that e.g. our wizards can use findFrame(_blank)
143 : // to create it's previes frames. They must do it manually by using WindowDescriptor+Toolkit!
144 2206 : css::uno::Reference< css::frame::XDesktop > xDesktop(xParentFrame, css::uno::UNO_QUERY);
145 : ::sal_Bool bTopLevelDocumentWindow = (
146 3300 : sRightName.isEmpty() &&
147 : (
148 2198 : (! xParentFrame.is() ) ||
149 1099 : ( xDesktop.is() )
150 : )
151 1103 : );
152 1103 : if (bTopLevelDocumentWindow)
153 1098 : implts_applyDocStyleToWindow(xContainerWindow);
154 : //------------------->
155 :
156 : // create the new frame
157 2206 : css::uno::Reference< css::frame::XFrame2 > xFrame = implts_createFrame(xParentFrame, xContainerWindow, sRightName);
158 :
159 : // special freature:
160 : // A special listener will restore pos/size states in case
161 : // a component was loaded into the frame first time.
162 1103 : if (bSupportPersistentWindowState)
163 1102 : implts_establishWindowStateListener(xFrame);
164 :
165 : // special feature: On Mac we need tagging the window in case
166 : // the underlying model was modified.
167 : // VCL will ignore our calls in case different platform then Mac
168 : // is used ...
169 1103 : if (bTopLevelDocumentWindow)
170 1098 : implts_establishDocModifyListener (xFrame);
171 :
172 : // special freature:
173 : // A special listener will update title bar (text and icon)
174 : // if component of frame will be changed.
175 1103 : if (bEnableTitleBarUpdate)
176 1103 : implts_establishTitleBarUpdate(xFrame);
177 :
178 : // Make it visible directly here ...
179 : // if its required from outside.
180 1103 : if (bVisible)
181 0 : xContainerWindow->setVisible(bVisible);
182 :
183 2206 : return css::uno::Reference< css::uno::XInterface >(xFrame, css::uno::UNO_QUERY_THROW);
184 : }
185 :
186 : //-----------------------------------------------
187 1098 : void TaskCreatorService::implts_applyDocStyleToWindow(const css::uno::Reference< css::awt::XWindow >& xWindow) const
188 : {
189 : // SYNCHRONIZED ->
190 1098 : SolarMutexGuard aSolarGuard;
191 1098 : Window* pVCLWindow = VCLUnoHelper::GetWindow(xWindow);
192 1098 : if (pVCLWindow)
193 1098 : pVCLWindow->SetExtendedStyle(WB_EXT_DOCUMENT);
194 : // <- SYNCHRONIZED
195 1098 : }
196 :
197 : //-----------------------------------------------
198 1102 : css::uno::Reference< css::awt::XWindow > TaskCreatorService::implts_createContainerWindow( const css::uno::Reference< css::awt::XWindow >& xParentWindow ,
199 : const css::awt::Rectangle& aPosSize ,
200 : sal_Bool bTopWindow )
201 : {
202 : // SAFE ->
203 1102 : ReadGuard aReadLock( m_aLock );
204 2204 : css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
205 1102 : aReadLock.unlock();
206 : // <- SAFE
207 :
208 : // get toolkit to create task container window
209 2204 : css::uno::Reference< css::awt::XToolkit2 > xToolkit = css::awt::Toolkit::create( xContext );
210 :
211 : // Check if child frames can be created realy. We need at least a valid window at the parent frame ...
212 2204 : css::uno::Reference< css::awt::XWindowPeer > xParentWindowPeer;
213 1102 : if ( ! bTopWindow)
214 : {
215 0 : if ( ! xParentWindow.is())
216 0 : bTopWindow = sal_False;
217 : else
218 0 : xParentWindowPeer = css::uno::Reference< css::awt::XWindowPeer >(xParentWindow, css::uno::UNO_QUERY_THROW);
219 : }
220 :
221 : // describe window properties.
222 2204 : css::awt::WindowDescriptor aDescriptor;
223 1102 : if (bTopWindow)
224 : {
225 1102 : aDescriptor.Type = css::awt::WindowClass_TOP ;
226 1102 : aDescriptor.WindowServiceName = OUString("window");
227 1102 : aDescriptor.ParentIndex = -1 ;
228 1102 : aDescriptor.Parent = css::uno::Reference< css::awt::XWindowPeer >() ;
229 1102 : aDescriptor.Bounds = aPosSize ;
230 : aDescriptor.WindowAttributes = css::awt::WindowAttribute::BORDER |
231 : css::awt::WindowAttribute::MOVEABLE |
232 : css::awt::WindowAttribute::SIZEABLE |
233 : css::awt::WindowAttribute::CLOSEABLE |
234 1102 : css::awt::VclWindowPeerAttribute::CLIPCHILDREN ;
235 : }
236 : else
237 : {
238 0 : aDescriptor.Type = css::awt::WindowClass_TOP ;
239 0 : aDescriptor.WindowServiceName = OUString("dockingwindow");
240 0 : aDescriptor.ParentIndex = 1 ;
241 0 : aDescriptor.Parent = xParentWindowPeer ;
242 0 : aDescriptor.Bounds = aPosSize ;
243 0 : aDescriptor.WindowAttributes = css::awt::VclWindowPeerAttribute::CLIPCHILDREN ;
244 : }
245 :
246 : // create a new blank container window and get access to parent container to append new created task.
247 2204 : css::uno::Reference< css::awt::XWindowPeer > xPeer = xToolkit->createWindow( aDescriptor );
248 1102 : css::uno::Reference< css::awt::XWindow > xWindow ( xPeer, css::uno::UNO_QUERY );
249 1102 : if ( ! xWindow.is())
250 : throw css::uno::Exception("TaskCreator service was not able to create suitable frame window.",
251 0 : static_cast< ::cppu::OWeakObject* >(this));
252 1102 : if (bTopWindow)
253 1102 : xPeer->setBackground(::svtools::ColorConfig().GetColorValue(::svtools::APPBACKGROUND).nColor);
254 : else
255 0 : xPeer->setBackground(0xffffffff);
256 :
257 2204 : return xWindow;
258 : }
259 :
260 : //-----------------------------------------------
261 1103 : css::uno::Reference< css::frame::XFrame2 > TaskCreatorService::implts_createFrame( const css::uno::Reference< css::frame::XFrame >& xParentFrame ,
262 : const css::uno::Reference< css::awt::XWindow >& xContainerWindow,
263 : const OUString& sName )
264 : {
265 : // SAFE ->
266 1103 : ReadGuard aReadLock( m_aLock );
267 2206 : css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
268 1103 : aReadLock.unlock();
269 : // <- SAFE
270 :
271 : // create new frame.
272 1103 : css::uno::Reference< css::frame::XFrame2 > xNewFrame = css::frame::Frame::create( xContext );
273 :
274 : // Set window on frame.
275 : // Do it before calling any other interface methods ...
276 : // The new created frame must be initialized before you can do anything else there.
277 1103 : xNewFrame->initialize( xContainerWindow );
278 :
279 : // Put frame to the frame tree.
280 : // Note: The property creator/parent will be set on the new putted frame automaticly ... by the parent container.
281 1103 : if (xParentFrame.is())
282 : {
283 1103 : css::uno::Reference< css::frame::XFramesSupplier > xSupplier (xParentFrame, css::uno::UNO_QUERY_THROW);
284 2206 : css::uno::Reference< css::frame::XFrames > xContainer = xSupplier->getFrames();
285 2206 : xContainer->append( css::uno::Reference<css::frame::XFrame>(xNewFrame, css::uno::UNO_QUERY_THROW) );
286 : }
287 :
288 : // Set it's API name (if there is one from outside)
289 1103 : if (!sName.isEmpty())
290 4 : xNewFrame->setName( sName );
291 :
292 2206 : return xNewFrame;
293 : }
294 :
295 : //-----------------------------------------------
296 1102 : void TaskCreatorService::implts_establishWindowStateListener( const css::uno::Reference< css::frame::XFrame2 >& xFrame )
297 : {
298 : // SAFE ->
299 1102 : ReadGuard aReadLock( m_aLock );
300 2204 : css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
301 1102 : aReadLock.unlock();
302 : // <- SAFE
303 :
304 : // Special feature: It's allowed for frames using a top level window only!
305 : // We must create a special listener service and couple it with the new created task frame.
306 : // He will restore or save the window state of it ...
307 : // See used classes for further information too.
308 1102 : PersistentWindowState* pPersistentStateHandler = new PersistentWindowState( xContext );
309 2204 : css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pPersistentStateHandler), css::uno::UNO_QUERY_THROW);
310 :
311 2204 : css::uno::Sequence< css::uno::Any > lInitData(1);
312 1102 : lInitData[0] <<= xFrame;
313 2204 : xInit->initialize(lInitData);
314 1102 : }
315 :
316 : //-----------------------------------------------
317 1098 : void TaskCreatorService::implts_establishDocModifyListener( const css::uno::Reference< css::frame::XFrame2 >& xFrame )
318 : {
319 : // Special feature: It's allowed for frames using a top level window only!
320 : // We must create a special listener service and couple it with the new created task frame.
321 : // It will tag the window as modified if the underlying model was modified ...
322 1098 : TagWindowAsModified* pTag = new TagWindowAsModified();
323 1098 : css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pTag), css::uno::UNO_QUERY_THROW);
324 :
325 2196 : css::uno::Sequence< css::uno::Any > lInitData(1);
326 1098 : lInitData[0] <<= xFrame;
327 2196 : xInit->initialize(lInitData);
328 1098 : }
329 :
330 : //-----------------------------------------------
331 1103 : void TaskCreatorService::implts_establishTitleBarUpdate( const css::uno::Reference< css::frame::XFrame2 >& xFrame )
332 : {
333 : // SAFE ->
334 1103 : ReadGuard aReadLock( m_aLock );
335 2206 : css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
336 1103 : aReadLock.unlock();
337 : // <- SAFE
338 :
339 1103 : TitleBarUpdate* pHelper = new TitleBarUpdate (xContext);
340 2206 : css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pHelper), css::uno::UNO_QUERY_THROW);
341 :
342 2206 : css::uno::Sequence< css::uno::Any > lInitData(1);
343 1103 : lInitData[0] <<= xFrame;
344 2206 : xInit->initialize(lInitData);
345 1103 : }
346 :
347 : //-----------------------------------------------
348 1103 : OUString TaskCreatorService::impl_filterNames( const OUString& sName )
349 : {
350 1103 : OUString sFiltered;
351 1103 : if (TargetHelper::isValidNameForFrame(sName))
352 5 : sFiltered = sName;
353 1103 : return sFiltered;
354 : }
355 :
356 402 : } // namespace framework
357 :
358 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|