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