xref: /trunk/main/framework/source/helper/titlebarupdate.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 
27 #ifndef __FRAMEWORK_HELPER_TITLEBARUPDATE_HXX_
28 #include <helper/titlebarupdate.hxx>
29 #endif
30 
31 //_________________________________________________________________________________________________________________
32 //  my own includes
33 //_________________________________________________________________________________________________________________
34 
35 #ifndef __FRAMEWORK_PATTERN_WINDOW_HXX_
36 #include <pattern/window.hxx>
37 #endif
38 
39 #ifndef __FRAMEWORK_THREADHELP_WRITEGUARD_HXX_
40 #include <threadhelp/writeguard.hxx>
41 #endif
42 
43 #ifndef __FRAMEWORK_THREADHELP_READGUARD_HXX_
44 #include <threadhelp/readguard.hxx>
45 #endif
46 
47 #ifndef __FRAMEWORK_MACROS_GENERIC_HXX_
48 #include <macros/generic.hxx>
49 #endif
50 
51 #ifndef __FRAMEWORK_SERVICES_H_
52 #include <services.h>
53 #endif
54 
55 #ifndef __FRAMEWORK_PROPETIES_H_
56 #include <properties.h>
57 #endif
58 
59 //_________________________________________________________________________________________________________________
60 //  interface includes
61 //_________________________________________________________________________________________________________________
62 
63 #ifndef _COM_SUN_STAR_AWT_XWINDOW_HPP_
64 #include <com/sun/star/awt/XWindow.hpp>
65 #endif
66 
67 #ifndef _COM_SUN_STAR_LANG_XSERVICXEINFO_HPP_
68 #include <com/sun/star/lang/XServiceInfo.hpp>
69 #endif
70 
71 #ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_
72 #include <com/sun/star/lang/IllegalArgumentException.hpp>
73 #endif
74 
75 #ifndef _COM_SUN_STAR_FRAME_XMODULEMANAGER_HPP_
76 #include <com/sun/star/frame/XModuleManager.hpp>
77 #endif
78 
79 #ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
80 #include <com/sun/star/container/XNameAccess.hpp>
81 #endif
82 
83 #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
84 #include <com/sun/star/beans/XPropertySet.hpp>
85 #endif
86 
87 #ifndef _COM_SUN_STAR_BEANS_XMATERIALHOLDER_HPP_
88 #include <com/sun/star/beans/XMaterialHolder.hpp>
89 #endif
90 
91 #ifndef _COM_SUN_STAR_FRAME_XTITLECHANGEBROADCASTER_HPP_
92 #include <com/sun/star/frame/XTitleChangeBroadcaster.hpp>
93 #endif
94 
95 #ifndef _COM_SUN_STAR_BEANS_NAMEDVALUE_HPP_
96 #include <com/sun/star/beans/NamedValue.hpp>
97 #endif
98 
99 //_________________________________________________________________________________________________________________
100 //  other includes
101 //_________________________________________________________________________________________________________________
102 
103 #include <comphelper/sequenceashashmap.hxx>
104 #include <unotools/configmgr.hxx>
105 #include <unotools/bootstrap.hxx>
106 #include <vcl/window.hxx>
107 #include <vcl/syswin.hxx>
108 #include <toolkit/helper/vclunohelper.hxx>
109 #include <vcl/svapp.hxx>
110 #include <vcl/wrkwin.hxx>
111 #include <tools/diagnose_ex.h>
112 
113 //_________________________________________________________________________________________________________________
114 //  namespace
115 
116 namespace framework{
117 
118 //_________________________________________________________________________________________________________________
119 //  const
120 
121 static const ::sal_Int32 INVALID_ICON_ID = -1;
122 static const ::sal_Int32 DEFAULT_ICON_ID =  0;
123 
124 //_________________________________________________________________________________________________________________
125 //  definitions
126 
127 //*****************************************************************************************************************
128 //  XInterface, XTypeProvider
129 
DEFINE_XINTERFACE_5(TitleBarUpdate,OWeakObject,DIRECT_INTERFACE (css::lang::XTypeProvider),DIRECT_INTERFACE (css::lang::XInitialization),DIRECT_INTERFACE (css::frame::XFrameActionListener),DIRECT_INTERFACE (css::frame::XTitleChangeListener),DERIVED_INTERFACE (css::lang::XEventListener,css::frame::XFrameActionListener))130 DEFINE_XINTERFACE_5(TitleBarUpdate                                                              ,
131                     OWeakObject                                                                 ,
132                     DIRECT_INTERFACE (css::lang::XTypeProvider                                  ),
133                     DIRECT_INTERFACE (css::lang::XInitialization                                ),
134                     DIRECT_INTERFACE (css::frame::XFrameActionListener                          ),
135                     DIRECT_INTERFACE (css::frame::XTitleChangeListener                          ),
136                     DERIVED_INTERFACE(css::lang::XEventListener,css::frame::XFrameActionListener))
137 
138 DEFINE_XTYPEPROVIDER_5(TitleBarUpdate                  ,
139                        css::lang::XTypeProvider        ,
140                        css::lang::XInitialization      ,
141                        css::frame::XFrameActionListener,
142                        css::frame::XTitleChangeListener,
143                        css::lang::XEventListener       )
144 
145 //*****************************************************************************************************************
146 TitleBarUpdate::TitleBarUpdate(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
147     : ThreadHelpBase          (&Application::GetSolarMutex())
148     , m_xSMGR                 (xSMGR                        )
149     , m_xFrame                (                             )
150 {
151 }
152 
153 //*****************************************************************************************************************
~TitleBarUpdate()154 TitleBarUpdate::~TitleBarUpdate()
155 {
156 }
157 
158 //*****************************************************************************************************************
initialize(const css::uno::Sequence<css::uno::Any> & lArguments)159 void SAL_CALL TitleBarUpdate::initialize(const css::uno::Sequence< css::uno::Any >& lArguments)
160 {
161     // check arguments
162     css::uno::Reference< css::frame::XFrame > xFrame;
163     if (lArguments.getLength() < 1)
164         throw css::lang::IllegalArgumentException(
165                 DECLARE_ASCII("Empty argument list!"),
166                 static_cast< ::cppu::OWeakObject* >(this),
167                 1);
168 
169     lArguments[0] >>= xFrame;
170     if (!xFrame.is())
171         throw css::lang::IllegalArgumentException(
172                 DECLARE_ASCII("No valid frame specified!"),
173                 static_cast< ::cppu::OWeakObject* >(this),
174                 1);
175 
176     // SYNCHRONIZED ->
177     WriteGuard aWriteLock(m_aLock);
178     // hold the frame as weak reference(!) so it can die everytimes :-)
179     m_xFrame = xFrame;
180     aWriteLock.unlock();
181     // <- SYNCHRONIZED
182 
183     // start listening
184     xFrame->addFrameActionListener(this);
185 
186     css::uno::Reference< css::frame::XTitleChangeBroadcaster > xBroadcaster(xFrame, css::uno::UNO_QUERY);
187     if (xBroadcaster.is ())
188         xBroadcaster->addTitleChangeListener (this);
189 }
190 
191 //*****************************************************************************************************************
frameAction(const css::frame::FrameActionEvent & aEvent)192 void SAL_CALL TitleBarUpdate::frameAction(const css::frame::FrameActionEvent& aEvent)
193 {
194     // we are interested on events only, which must trigger a title bar update
195     // because component was changed.
196     if (
197         (aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED  ) ||
198         (aEvent.Action == css::frame::FrameAction_COMPONENT_REATTACHED) ||
199         (aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING )
200        )
201     {
202         impl_forceUpdate ();
203     }
204 }
205 
206 //*****************************************************************************************************************
titleChanged(const css::frame::TitleChangedEvent &)207 void SAL_CALL TitleBarUpdate::titleChanged(const css::frame::TitleChangedEvent& /* aEvent */)
208 {
209     impl_forceUpdate ();
210 }
211 
212 //*****************************************************************************************************************
disposing(const css::lang::EventObject &)213 void SAL_CALL TitleBarUpdate::disposing(const css::lang::EventObject&)
214 {
215     // nothing todo here - because we hold the frame as weak reference only
216 }
217 
218 //*****************************************************************************************************************
implst_getModuleInfo(const css::uno::Reference<css::frame::XFrame> & xFrame,TModuleInfo & rInfo)219 ::sal_Bool TitleBarUpdate::implst_getModuleInfo(const css::uno::Reference< css::frame::XFrame >& xFrame,
220                                                       TModuleInfo&                               rInfo )
221 {
222     if ( ! xFrame.is ())
223         return sal_False;
224 
225     // SYNCHRONIZED ->
226     ReadGuard aReadLock(m_aLock);
227     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
228     aReadLock.unlock();
229     // <- SYNCHRONIZED
230 
231     try
232     {
233         css::uno::Reference< css::frame::XModuleManager > xModuleManager(
234             xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
235             css::uno::UNO_QUERY_THROW);
236 
237         css::uno::Reference< css::container::XNameAccess > xConfig(
238             xModuleManager,
239             css::uno::UNO_QUERY_THROW);
240 
241                                         rInfo.sID = xModuleManager->identify(xFrame);
242         ::comphelper::SequenceAsHashMap lProps    = xConfig->getByName (rInfo.sID);
243 
244         rInfo.sUIName = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_UINAME, ::rtl::OUString());
245         rInfo.nIcon   = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_ICON  , INVALID_ICON_ID  );
246 
247         // Note: If we could retrieve a module id ... everything is OK.
248         // UIName and Icon ID are optional values !
249         ::sal_Bool bSuccess = (rInfo.sID.getLength () > 0);
250         return bSuccess;
251     }
252     catch(const css::uno::Exception&)
253         {}
254 
255     return sal_False;
256 }
257 
258 //*****************************************************************************************************************
impl_forceUpdate()259 void TitleBarUpdate::impl_forceUpdate()
260 {
261     // SYNCHRONIZED ->
262     ReadGuard aReadLock(m_aLock);
263     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR ;
264     css::uno::Reference< css::frame::XFrame >              xFrame(m_xFrame.get(), css::uno::UNO_QUERY);
265     aReadLock.unlock();
266     // <- SYNCHRONIZED
267 
268     // frame already gone ? We hold it weak only ...
269     if ( ! xFrame.is())
270         return;
271 
272     // no window -> no chance to set/update title and icon
273     css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow();
274     if ( ! xWindow.is())
275         return;
276 
277     impl_updateIcon  (xFrame);
278     impl_updateTitle (xFrame);
279 }
280 
281 //*****************************************************************************************************************
impl_updateIcon(const css::uno::Reference<css::frame::XFrame> & xFrame)282 void TitleBarUpdate::impl_updateIcon(const css::uno::Reference< css::frame::XFrame >& xFrame)
283 {
284     css::uno::Reference< css::frame::XController > xController = xFrame->getController      ();
285     css::uno::Reference< css::awt::XWindow >       xWindow     = xFrame->getContainerWindow ();
286 
287     if (
288         ( ! xController.is() ) ||
289         ( ! xWindow.is()     )
290        )
291         return;
292 
293     // a) set default value to an invalid one. So we can start further searches for right icon id, if
294     //    first steps failed!
295     sal_Int32 nIcon = INVALID_ICON_ID;
296 
297     // b) try to find information on controller property set directly
298     //    Don't forget to catch possible exceptions - because these property is an optional one!
299     css::uno::Reference< css::beans::XPropertySet > xSet( xController, css::uno::UNO_QUERY );
300     if ( xSet.is() )
301     {
302         try
303         {
304             css::uno::Reference< css::beans::XPropertySetInfo > const xPSI( xSet->getPropertySetInfo(), css::uno::UNO_SET_THROW );
305             if ( xPSI->hasPropertyByName( CONTROLLER_PROPNAME_ICONID ) )
306                 xSet->getPropertyValue( CONTROLLER_PROPNAME_ICONID ) >>= nIcon;
307         }
308         catch(const css::uno::Exception&)
309         {
310             DBG_UNHANDLED_EXCEPTION();
311         }
312     }
313 
314     // c) if b) failed ... identify the used module and retrieve set icon from module config.
315     //    Tirck :-) Module was already specified outside and aInfo contains all needed informations.
316     if ( nIcon == INVALID_ICON_ID )
317     {
318         TModuleInfo aInfo;
319         if (implst_getModuleInfo(xFrame, aInfo))
320             nIcon = aInfo.nIcon;
321     }
322 
323     // d) if all steps failed - use fallback :-)
324     //    ... means using the global staroffice icon
325     if( nIcon == INVALID_ICON_ID )
326         nIcon = DEFAULT_ICON_ID;
327 
328     // e) set icon on container window now
329     //    Don't forget SolarMutex! We use vcl directly :-(
330     //    Check window pointer for right WorkWindow class too!!!
331 
332     // VCL SYNCHRONIZED ->
333     ::vos::OClearableGuard aSolarLock( Application::GetSolarMutex() );
334 
335     Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
336     if (
337         ( pWindow                                 ) &&
338         ( pWindow->GetType() == WINDOW_WORKWINDOW )
339        )
340     {
341         WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
342         pWorkWindow->SetIcon( (sal_uInt16)nIcon );
343 
344         css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
345         rtl::OUString aURL;
346         if( xModel.is() )
347             aURL = xModel->getURL();
348         pWorkWindow->SetRepresentedURL( aURL );
349     }
350 
351     aSolarLock.clear();
352     // <- VCL SYNCHRONIZED
353 }
354 
355 //*****************************************************************************************************************
impl_updateTitle(const css::uno::Reference<css::frame::XFrame> & xFrame)356 void TitleBarUpdate::impl_updateTitle(const css::uno::Reference< css::frame::XFrame >& xFrame)
357 {
358     // no window ... no chance to set any title -> return
359     css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
360     if ( ! xWindow.is() )
361         return;
362 
363     css::uno::Reference< css::frame::XTitle > xTitle(xFrame, css::uno::UNO_QUERY);
364     if ( ! xTitle.is() )
365         return;
366 
367     const ::rtl::OUString sTitle = xTitle->getTitle ();
368 
369     // VCL SYNCHRONIZED ->
370     ::vos::OClearableGuard aSolarLock( Application::GetSolarMutex() );
371 
372     Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
373     if (
374         ( pWindow                                 ) &&
375         ( pWindow->GetType() == WINDOW_WORKWINDOW )
376        )
377     {
378         WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
379         pWorkWindow->SetText( sTitle );
380     }
381 
382     aSolarLock.clear();
383     // <- VCL SYNCHRONIZED
384 }
385 
386 } // namespace framework
387