xref: /trunk/main/framework/source/services/taskcreatorsrv.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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