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