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/helper/vclunohelper.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 //-----------------------------------------------
DEFINE_XINTERFACE_3(TaskCreatorService,OWeakObject,DIRECT_INTERFACE (css::lang::XTypeProvider),DIRECT_INTERFACE (css::lang::XServiceInfo),DIRECT_INTERFACE (css::lang::XSingleServiceFactory))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 //-----------------------------------------------
~TaskCreatorService()115 TaskCreatorService::~TaskCreatorService()
116 {
117 }
118
119 //-----------------------------------------------
createInstance()120 css::uno::Reference< css::uno::XInterface > SAL_CALL TaskCreatorService::createInstance()
121 {
122 return createInstanceWithArguments(css::uno::Sequence< css::uno::Any >());
123 }
124
125 //-----------------------------------------------
createInstanceWithArguments(const css::uno::Sequence<css::uno::Any> & lArguments)126 css::uno::Reference< css::uno::XInterface > SAL_CALL TaskCreatorService::createInstanceWithArguments(const css::uno::Sequence< css::uno::Any >& lArguments)
127 {
128 static ::rtl::OUString DEFAULTVAL_FRAMENAME = ::rtl::OUString();
129 static sal_Bool DEFAULTVAL_MAKEVISIBLE = sal_False;
130 static sal_Bool DEFAULTVAL_CREATETOPWINDOW = sal_True;
131 static css::awt::Rectangle DEFAULTVAL_POSSIZE = css::awt::Rectangle(0, 0, 0, 0); // only possize=[0,0,0,0] triggers default handling of vcl !
132 static sal_Bool DEFAULTVAL_SUPPORTPERSSISTENTWINDOWSTATE = sal_False;
133 static sal_Bool DEFAULTVAL_ENABLE_TITLEBARUPDATE = sal_True;
134
135 ::comphelper::SequenceAsHashMap lArgs(lArguments);
136
137 css::uno::Reference< css::frame::XFrame > xParentFrame = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_PARENTFRAME , css::uno::Reference< css::frame::XFrame >());
138 ::rtl::OUString sFrameName = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_FRAMENAME , DEFAULTVAL_FRAMENAME );
139 sal_Bool bVisible = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_MAKEVISIBLE , DEFAULTVAL_MAKEVISIBLE );
140 sal_Bool bCreateTopWindow = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_CREATETOPWINDOW , DEFAULTVAL_CREATETOPWINDOW );
141 css::awt::Rectangle aPosSize = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_POSSIZE , DEFAULTVAL_POSSIZE );
142 css::uno::Reference< css::awt::XWindow > xContainerWindow = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_CONTAINERWINDOW , css::uno::Reference< css::awt::XWindow >() );
143 sal_Bool bSupportPersistentWindowState = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_SUPPORTPERSISTENTWINDOWSTATE , DEFAULTVAL_SUPPORTPERSSISTENTWINDOWSTATE );
144 sal_Bool bEnableTitleBarUpdate = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_ENABLE_TITLEBARUPDATE , DEFAULTVAL_ENABLE_TITLEBARUPDATE );
145
146 /* SAFE { */
147 ReadGuard aReadLock( m_aLock );
148 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
149 aReadLock.unlock();
150 /* } SAFE */
151
152 // We use FrameName property to set it as API name of the new created frame later.
153 // But those frame names must be different from the set of special target names as e.g. _blank, _self etcpp !
154 ::rtl::OUString sRightName = impl_filterNames(sFrameName);
155
156 // if no external frame window was given ... create a new one.
157 if ( ! xContainerWindow.is())
158 {
159 css::uno::Reference< css::awt::XWindow > xParentWindow;
160 if (xParentFrame.is())
161 xParentWindow = xParentFrame->getContainerWindow();
162
163 // Parent has no own window ...
164 // So we have to create a top level window always !
165 if ( ! xParentWindow.is())
166 bCreateTopWindow = sal_True;
167
168 xContainerWindow = implts_createContainerWindow(xParentWindow, aPosSize, bCreateTopWindow);
169 }
170
171 //------------------->
172 // HACK #125187# + #i53630#
173 // Mark all document windows as "special ones", so VCL can bind
174 // special features to it. Because VCL doesn't know anything about documents ...
175 // Note: Doing so it's no longer supported, that e.g. our wizards can use findFrame(_blank)
176 // to create it's previes frames. They must do it manually by using WindowDescriptor+Toolkit!
177 css::uno::Reference< css::frame::XDesktop > xDesktop(xParentFrame, css::uno::UNO_QUERY);
178 ::sal_Bool bTopLevelDocumentWindow = (
179 (sRightName.getLength () < 1) &&
180 (
181 (! xParentFrame.is() ) ||
182 ( xDesktop.is() )
183 )
184 );
185 if (bTopLevelDocumentWindow)
186 implts_applyDocStyleToWindow(xContainerWindow);
187 //------------------->
188
189 // create the new frame
190 css::uno::Reference< css::frame::XFrame > xFrame = implts_createFrame(xParentFrame, xContainerWindow, sRightName);
191
192 // special freature:
193 // A special listener will restore pos/size states in case
194 // a component was loaded into the frame first time.
195 if (bSupportPersistentWindowState)
196 implts_establishWindowStateListener(xFrame);
197
198 // special feature: On Mac we need tagging the window in case
199 // the underlying model was modified.
200 // VCL will ignore our calls in case different platform then Mac
201 // is used ...
202 if (bTopLevelDocumentWindow)
203 implts_establishDocModifyListener (xFrame);
204
205 // special freature:
206 // A special listener will update title bar (text and icon)
207 // if component of frame will be changed.
208 if (bEnableTitleBarUpdate)
209 implts_establishTitleBarUpdate(xFrame);
210
211 // Make it visible directly here ...
212 // if its required from outside.
213 if (bVisible)
214 xContainerWindow->setVisible(bVisible);
215
216 return css::uno::Reference< css::uno::XInterface >(xFrame, css::uno::UNO_QUERY_THROW);
217 }
218
219 //-----------------------------------------------
implts_applyDocStyleToWindow(const css::uno::Reference<css::awt::XWindow> & xWindow) const220 void TaskCreatorService::implts_applyDocStyleToWindow(const css::uno::Reference< css::awt::XWindow >& xWindow) const
221 {
222 // SYNCHRONIZED ->
223 ::vos::OClearableGuard aSolarGuard(Application::GetSolarMutex());
224 Window* pVCLWindow = VCLUnoHelper::GetWindow(xWindow);
225 if (pVCLWindow)
226 pVCLWindow->SetExtendedStyle(WB_EXT_DOCUMENT);
227 aSolarGuard.clear();
228 // <- SYNCHRONIZED
229 }
230
231 //-----------------------------------------------
implts_createContainerWindow(const css::uno::Reference<css::awt::XWindow> & xParentWindow,const css::awt::Rectangle & aPosSize,sal_Bool bTopWindow)232 css::uno::Reference< css::awt::XWindow > TaskCreatorService::implts_createContainerWindow( const css::uno::Reference< css::awt::XWindow >& xParentWindow ,
233 const css::awt::Rectangle& aPosSize ,
234 sal_Bool bTopWindow )
235 {
236 // SAFE ->
237 ReadGuard aReadLock( m_aLock );
238 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
239 aReadLock.unlock();
240 // <- SAFE
241
242 // get toolkit to create task container window
243 css::uno::Reference< css::awt::XToolkit > xToolkit( xSMGR->createInstance( SERVICENAME_VCLTOOLKIT ), css::uno::UNO_QUERY_THROW);
244
245 // Check if child frames can be created really. We need at least a valid window at the parent frame ...
246 css::uno::Reference< css::awt::XWindowPeer > xParentWindowPeer;
247 if ( ! bTopWindow)
248 {
249 if ( ! xParentWindow.is())
250 bTopWindow = sal_False;
251 else
252 xParentWindowPeer = css::uno::Reference< css::awt::XWindowPeer >(xParentWindow, css::uno::UNO_QUERY_THROW);
253 }
254
255 // describe window properties.
256 css::awt::WindowDescriptor aDescriptor;
257 if (bTopWindow)
258 {
259 aDescriptor.Type = css::awt::WindowClass_TOP ;
260 aDescriptor.WindowServiceName = DECLARE_ASCII("window") ;
261 aDescriptor.ParentIndex = -1 ;
262 aDescriptor.Parent = css::uno::Reference< css::awt::XWindowPeer >() ;
263 aDescriptor.Bounds = aPosSize ;
264 aDescriptor.WindowAttributes = css::awt::WindowAttribute::BORDER |
265 css::awt::WindowAttribute::MOVEABLE |
266 css::awt::WindowAttribute::SIZEABLE |
267 css::awt::WindowAttribute::CLOSEABLE |
268 css::awt::VclWindowPeerAttribute::CLIPCHILDREN ;
269 }
270 else
271 {
272 aDescriptor.Type = css::awt::WindowClass_TOP ;
273 aDescriptor.WindowServiceName = DECLARE_ASCII("dockingwindow") ;
274 aDescriptor.ParentIndex = 1 ;
275 aDescriptor.Parent = xParentWindowPeer ;
276 aDescriptor.Bounds = aPosSize ;
277 aDescriptor.WindowAttributes = css::awt::VclWindowPeerAttribute::CLIPCHILDREN ;
278 }
279
280 // create a new blank container window and get access to parent container to append new created task.
281 css::uno::Reference< css::awt::XWindowPeer > xPeer = xToolkit->createWindow( aDescriptor );
282 css::uno::Reference< css::awt::XWindow > xWindow ( xPeer, css::uno::UNO_QUERY );
283 if ( ! xWindow.is())
284 throw css::uno::Exception(::rtl::OUString::createFromAscii("TaskCreator service was not able to create suitable frame window."),
285 static_cast< ::cppu::OWeakObject* >(this));
286 if (bTopWindow)
287 xPeer->setBackground(::svtools::ColorConfig().GetColorValue(::svtools::APPBACKGROUND).nColor);
288 else
289 xPeer->setBackground(0xffffffff);
290
291 return xWindow;
292 }
293
294 //-----------------------------------------------
implts_createFrame(const css::uno::Reference<css::frame::XFrame> & xParentFrame,const css::uno::Reference<css::awt::XWindow> & xContainerWindow,const::rtl::OUString & sName)295 css::uno::Reference< css::frame::XFrame > TaskCreatorService::implts_createFrame( const css::uno::Reference< css::frame::XFrame >& xParentFrame ,
296 const css::uno::Reference< css::awt::XWindow >& xContainerWindow,
297 const ::rtl::OUString& sName )
298 {
299 // SAFE ->
300 ReadGuard aReadLock( m_aLock );
301 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
302 aReadLock.unlock();
303 // <- SAFE
304
305 // create new frame.
306 css::uno::Reference< css::frame::XFrame > xNewFrame( xSMGR->createInstance( SERVICENAME_FRAME ), css::uno::UNO_QUERY_THROW );
307
308 // Set window on frame.
309 // Do it before calling any other interface methods ...
310 // The new created frame must be initialized before you can do anything else there.
311 xNewFrame->initialize( xContainerWindow );
312
313 // Put frame to the frame tree.
314 // Note: The property creator/parent will be set on the new putted frame automatically ... by the parent container.
315 if (xParentFrame.is())
316 {
317 css::uno::Reference< css::frame::XFramesSupplier > xSupplier (xParentFrame, css::uno::UNO_QUERY_THROW);
318 css::uno::Reference< css::frame::XFrames > xContainer = xSupplier->getFrames();
319 xContainer->append( xNewFrame );
320 }
321
322 // Set it's API name (if there is one from outside)
323 if (sName.getLength())
324 xNewFrame->setName( sName );
325
326 return xNewFrame;
327 }
328
329 //-----------------------------------------------
implts_establishWindowStateListener(const css::uno::Reference<css::frame::XFrame> & xFrame)330 void TaskCreatorService::implts_establishWindowStateListener( const css::uno::Reference< css::frame::XFrame >& xFrame )
331 {
332 // SAFE ->
333 ReadGuard aReadLock( m_aLock );
334 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
335 aReadLock.unlock();
336 // <- SAFE
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 // He will restore or save the window state of it ...
341 // See used classes for further informations too.
342 PersistentWindowState* pPersistentStateHandler = new PersistentWindowState(xSMGR);
343 css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pPersistentStateHandler), css::uno::UNO_QUERY_THROW);
344
345 css::uno::Sequence< css::uno::Any > lInitData(1);
346 lInitData[0] <<= xFrame;
347 xInit->initialize(lInitData);
348 }
349
350 //-----------------------------------------------
implts_establishDocModifyListener(const css::uno::Reference<css::frame::XFrame> & xFrame)351 void TaskCreatorService::implts_establishDocModifyListener( const css::uno::Reference< css::frame::XFrame >& xFrame )
352 {
353 // SAFE ->
354 ReadGuard aReadLock( m_aLock );
355 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
356 aReadLock.unlock();
357 // <- SAFE
358
359 // Special feature: It's allowed for frames using a top level window only!
360 // We must create a special listener service and couple it with the new created task frame.
361 // It will tag the window as modified if the underlying model was modified ...
362 TagWindowAsModified* pTag = new TagWindowAsModified(xSMGR);
363 css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pTag), css::uno::UNO_QUERY_THROW);
364
365 css::uno::Sequence< css::uno::Any > lInitData(1);
366 lInitData[0] <<= xFrame;
367 xInit->initialize(lInitData);
368 }
369
370 //-----------------------------------------------
implts_establishTitleBarUpdate(const css::uno::Reference<css::frame::XFrame> & xFrame)371 void TaskCreatorService::implts_establishTitleBarUpdate( const css::uno::Reference< css::frame::XFrame >& xFrame )
372 {
373 // SAFE ->
374 ReadGuard aReadLock( m_aLock );
375 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
376 aReadLock.unlock();
377 // <- SAFE
378
379 TitleBarUpdate* pHelper = new TitleBarUpdate (xSMGR);
380 css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pHelper), css::uno::UNO_QUERY_THROW);
381
382 css::uno::Sequence< css::uno::Any > lInitData(1);
383 lInitData[0] <<= xFrame;
384 xInit->initialize(lInitData);
385 }
386
387 //-----------------------------------------------
impl_filterNames(const::rtl::OUString & sName)388 ::rtl::OUString TaskCreatorService::impl_filterNames( const ::rtl::OUString& sName )
389 {
390 ::rtl::OUString sFiltered;
391 if (TargetHelper::isValidNameForFrame(sName))
392 sFiltered = sName;
393 return sFiltered;
394 }
395
396 } // namespace framework
397