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 0 : virtual OUString SAL_CALL getImplementationName()
70 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
71 : {
72 0 : 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 0 : virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames()
82 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
83 : {
84 0 : css::uno::Sequence< OUString > aSeq(1);
85 0 : aSeq[0] = OUString("com.sun.star.frame.TaskCreator");
86 0 : 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 0 : TaskCreatorService::TaskCreatorService(const css::uno::Reference< css::uno::XComponentContext >& xContext)
119 : : TaskCreatorService_BASE(m_aMutex)
120 0 : , m_xContext (xContext )
121 : {
122 0 : }
123 :
124 0 : TaskCreatorService::~TaskCreatorService()
125 : {
126 0 : }
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 0 : 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 0 : ::comphelper::SequenceAsHashMap lArgs(lArguments);
140 :
141 0 : css::uno::Reference< css::frame::XFrame > xParentFrame = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_PARENTFRAME) , css::uno::Reference< css::frame::XFrame >());
142 0 : OUString sFrameName = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_FRAMENAME) , OUString() );
143 0 : bool bVisible = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_MAKEVISIBLE) , sal_False );
144 0 : bool bCreateTopWindow = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_CREATETOPWINDOW) , sal_True );
145 : // only possize=[0,0,0,0] triggers default handling of vcl !
146 0 : css::awt::Rectangle aPosSize = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_POSSIZE) , css::awt::Rectangle(0, 0, 0, 0) );
147 0 : css::uno::Reference< css::awt::XWindow > xContainerWindow = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_CONTAINERWINDOW) , css::uno::Reference< css::awt::XWindow >() );
148 0 : bool bSupportPersistentWindowState = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_SUPPORTPERSISTENTWINDOWSTATE) , sal_False );
149 0 : bool bEnableTitleBarUpdate = lArgs.getUnpackedValueOrDefault(OUString(ARGUMENT_ENABLE_TITLEBARUPDATE) , sal_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 0 : OUString sRightName = impl_filterNames(sFrameName);
154 :
155 : // if no external frame window was given ... create a new one.
156 0 : if ( ! xContainerWindow.is())
157 : {
158 0 : css::uno::Reference< css::awt::XWindow > xParentWindow;
159 0 : if (xParentFrame.is())
160 0 : xParentWindow = xParentFrame->getContainerWindow();
161 :
162 : // Parent has no own window ...
163 : // So we have to create a top level window always !
164 0 : if ( ! xParentWindow.is())
165 0 : bCreateTopWindow = true;
166 :
167 0 : 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 0 : css::uno::Reference< css::frame::XDesktop > xDesktop(xParentFrame, css::uno::UNO_QUERY);
176 : bool bTopLevelDocumentWindow = (
177 0 : sRightName.isEmpty() &&
178 : (
179 0 : (! xParentFrame.is() ) ||
180 0 : ( xDesktop.is() )
181 : )
182 0 : );
183 0 : if (bTopLevelDocumentWindow)
184 0 : implts_applyDocStyleToWindow(xContainerWindow);
185 : //------------------->
186 :
187 : // create the new frame
188 0 : 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 0 : if (bSupportPersistentWindowState)
194 0 : 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 0 : if (bTopLevelDocumentWindow)
201 0 : 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 0 : if (bEnableTitleBarUpdate)
207 0 : implts_establishTitleBarUpdate(xFrame);
208 :
209 : // Make it visible directly here ...
210 : // if its required from outside.
211 0 : if (bVisible)
212 0 : xContainerWindow->setVisible(bVisible);
213 :
214 0 : return css::uno::Reference< css::uno::XInterface >(xFrame, css::uno::UNO_QUERY_THROW);
215 : }
216 :
217 0 : void TaskCreatorService::implts_applyDocStyleToWindow(const css::uno::Reference< css::awt::XWindow >& xWindow) const
218 : {
219 : // SYNCHRONIZED ->
220 0 : SolarMutexGuard aSolarGuard;
221 0 : Window* pVCLWindow = VCLUnoHelper::GetWindow(xWindow);
222 0 : if (pVCLWindow)
223 0 : pVCLWindow->SetExtendedStyle(WB_EXT_DOCUMENT);
224 : // <- SYNCHRONIZED
225 0 : }
226 :
227 0 : 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 0 : 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 0 : css::uno::Reference< css::awt::XWindowPeer > xParentWindowPeer;
236 0 : 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 0 : css::awt::WindowDescriptor aDescriptor;
246 0 : if (bTopWindow)
247 : {
248 0 : aDescriptor.Type = css::awt::WindowClass_TOP;
249 0 : aDescriptor.WindowServiceName = "window";
250 0 : aDescriptor.ParentIndex = -1;
251 0 : aDescriptor.Parent = css::uno::Reference< css::awt::XWindowPeer >();
252 0 : 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 0 : 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 0 : css::uno::Reference< css::awt::XWindowPeer > xPeer = xToolkit->createWindow( aDescriptor );
271 0 : css::uno::Reference< css::awt::XWindow > xWindow ( xPeer, css::uno::UNO_QUERY );
272 0 : 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 0 : if (bTopWindow)
276 0 : xPeer->setBackground(::svtools::ColorConfig().GetColorValue(::svtools::APPBACKGROUND).nColor);
277 : else
278 0 : xPeer->setBackground(0xffffffff);
279 :
280 0 : return xWindow;
281 : }
282 :
283 0 : css::uno::Reference< css::frame::XFrame2 > TaskCreatorService::implts_createFrame( const css::uno::Reference< css::frame::XFrame >& xParentFrame ,
284 : const css::uno::Reference< css::awt::XWindow >& xContainerWindow,
285 : const OUString& sName )
286 : {
287 : // create new frame.
288 0 : css::uno::Reference< css::frame::XFrame2 > xNewFrame = css::frame::Frame::create( m_xContext );
289 :
290 : // Set window on frame.
291 : // Do it before calling any other interface methods ...
292 : // The new created frame must be initialized before you can do anything else there.
293 0 : xNewFrame->initialize( xContainerWindow );
294 :
295 : // Put frame to the frame tree.
296 : // Note: The property creator/parent will be set on the new putted frame automaticly ... by the parent container.
297 0 : if (xParentFrame.is())
298 : {
299 0 : css::uno::Reference< css::frame::XFramesSupplier > xSupplier (xParentFrame, css::uno::UNO_QUERY_THROW);
300 0 : css::uno::Reference< css::frame::XFrames > xContainer = xSupplier->getFrames();
301 0 : xContainer->append( css::uno::Reference<css::frame::XFrame>(xNewFrame, css::uno::UNO_QUERY_THROW) );
302 : }
303 :
304 : // Set it's API name (if there is one from outside)
305 0 : if (!sName.isEmpty())
306 0 : xNewFrame->setName( sName );
307 :
308 0 : return xNewFrame;
309 : }
310 :
311 0 : void TaskCreatorService::implts_establishWindowStateListener( const css::uno::Reference< css::frame::XFrame2 >& xFrame )
312 : {
313 : // Special feature: It's allowed for frames using a top level window only!
314 : // We must create a special listener service and couple it with the new created task frame.
315 : // He will restore or save the window state of it ...
316 : // See used classes for further information too.
317 0 : PersistentWindowState* pPersistentStateHandler = new PersistentWindowState( m_xContext );
318 0 : css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pPersistentStateHandler), css::uno::UNO_QUERY_THROW);
319 :
320 0 : css::uno::Sequence< css::uno::Any > lInitData(1);
321 0 : lInitData[0] <<= xFrame;
322 0 : xInit->initialize(lInitData);
323 0 : }
324 :
325 0 : void TaskCreatorService::implts_establishDocModifyListener( const css::uno::Reference< css::frame::XFrame2 >& xFrame )
326 : {
327 : // Special feature: It's allowed for frames using a top level window only!
328 : // We must create a special listener service and couple it with the new created task frame.
329 : // It will tag the window as modified if the underlying model was modified ...
330 0 : TagWindowAsModified* pTag = new TagWindowAsModified();
331 0 : css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pTag), css::uno::UNO_QUERY_THROW);
332 :
333 0 : css::uno::Sequence< css::uno::Any > lInitData(1);
334 0 : lInitData[0] <<= xFrame;
335 0 : xInit->initialize(lInitData);
336 0 : }
337 :
338 0 : void TaskCreatorService::implts_establishTitleBarUpdate( const css::uno::Reference< css::frame::XFrame2 >& xFrame )
339 : {
340 0 : TitleBarUpdate* pHelper = new TitleBarUpdate (m_xContext);
341 0 : css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pHelper), css::uno::UNO_QUERY_THROW);
342 :
343 0 : css::uno::Sequence< css::uno::Any > lInitData(1);
344 0 : lInitData[0] <<= xFrame;
345 0 : xInit->initialize(lInitData);
346 0 : }
347 :
348 0 : OUString TaskCreatorService::impl_filterNames( const OUString& sName )
349 : {
350 0 : OUString sFiltered;
351 0 : if (TargetHelper::isValidNameForFrame(sName))
352 0 : sFiltered = sName;
353 0 : return sFiltered;
354 : }
355 :
356 0 : struct Instance {
357 0 : explicit Instance(
358 : css::uno::Reference<css::uno::XComponentContext> const & context):
359 : instance(
360 0 : static_cast<cppu::OWeakObject *>(new TaskCreatorService(context)))
361 : {
362 0 : }
363 :
364 : css::uno::Reference<css::uno::XInterface> instance;
365 : };
366 :
367 : struct Singleton:
368 : public rtl::StaticWithArg<
369 : Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton>
370 : {};
371 :
372 : }
373 :
374 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
375 0 : com_sun_star_comp_framework_TaskCreator_get_implementation(
376 : css::uno::XComponentContext *context,
377 : css::uno::Sequence<css::uno::Any> const &)
378 : {
379 : return cppu::acquire(static_cast<cppu::OWeakObject *>(
380 0 : Singleton::get(context).instance.get()));
381 : }
382 :
383 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|