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     throw(css::uno::Exception       ,
161           css::uno::RuntimeException)
162 {
163     // check arguments
164     css::uno::Reference< css::frame::XFrame > xFrame;
165     if (lArguments.getLength() < 1)
166         throw css::lang::IllegalArgumentException(
167                 DECLARE_ASCII("Empty argument list!"),
168                 static_cast< ::cppu::OWeakObject* >(this),
169                 1);
170 
171     lArguments[0] >>= xFrame;
172     if (!xFrame.is())
173         throw css::lang::IllegalArgumentException(
174                 DECLARE_ASCII("No valid frame specified!"),
175                 static_cast< ::cppu::OWeakObject* >(this),
176                 1);
177 
178     // SYNCHRONIZED ->
179     WriteGuard aWriteLock(m_aLock);
180     // hold the frame as weak reference(!) so it can die everytimes :-)
181     m_xFrame = xFrame;
182     aWriteLock.unlock();
183     // <- SYNCHRONIZED
184 
185     // start listening
186     xFrame->addFrameActionListener(this);
187 
188     css::uno::Reference< css::frame::XTitleChangeBroadcaster > xBroadcaster(xFrame, css::uno::UNO_QUERY);
189     if (xBroadcaster.is ())
190         xBroadcaster->addTitleChangeListener (this);
191 }
192 
193 //*****************************************************************************************************************
frameAction(const css::frame::FrameActionEvent & aEvent)194 void SAL_CALL TitleBarUpdate::frameAction(const css::frame::FrameActionEvent& aEvent)
195     throw(css::uno::RuntimeException)
196 {
197     // we are interested on events only, which must trigger a title bar update
198     // because component was changed.
199     if (
200         (aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED  ) ||
201         (aEvent.Action == css::frame::FrameAction_COMPONENT_REATTACHED) ||
202         (aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING )
203        )
204     {
205         impl_forceUpdate ();
206     }
207 }
208 
209 //*****************************************************************************************************************
titleChanged(const css::frame::TitleChangedEvent &)210 void SAL_CALL TitleBarUpdate::titleChanged(const css::frame::TitleChangedEvent& /* aEvent */)
211     throw (css::uno::RuntimeException)
212 {
213     impl_forceUpdate ();
214 }
215 
216 //*****************************************************************************************************************
disposing(const css::lang::EventObject &)217 void SAL_CALL TitleBarUpdate::disposing(const css::lang::EventObject&)
218     throw(css::uno::RuntimeException)
219 {
220     // nothing todo here - because we hold the frame as weak reference only
221 }
222 
223 //*****************************************************************************************************************
implst_getModuleInfo(const css::uno::Reference<css::frame::XFrame> & xFrame,TModuleInfo & rInfo)224 ::sal_Bool TitleBarUpdate::implst_getModuleInfo(const css::uno::Reference< css::frame::XFrame >& xFrame,
225                                                       TModuleInfo&                               rInfo )
226 {
227     if ( ! xFrame.is ())
228         return sal_False;
229 
230     // SYNCHRONIZED ->
231     ReadGuard aReadLock(m_aLock);
232     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
233     aReadLock.unlock();
234     // <- SYNCHRONIZED
235 
236     try
237     {
238         css::uno::Reference< css::frame::XModuleManager > xModuleManager(
239             xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
240             css::uno::UNO_QUERY_THROW);
241 
242         css::uno::Reference< css::container::XNameAccess > xConfig(
243             xModuleManager,
244             css::uno::UNO_QUERY_THROW);
245 
246                                         rInfo.sID = xModuleManager->identify(xFrame);
247         ::comphelper::SequenceAsHashMap lProps    = xConfig->getByName (rInfo.sID);
248 
249         rInfo.sUIName = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_UINAME, ::rtl::OUString());
250         rInfo.nIcon   = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_ICON  , INVALID_ICON_ID  );
251 
252 		// Note: If we could retrieve a module id ... everything is OK.
253 		// UIName and Icon ID are optional values !
254         ::sal_Bool bSuccess = (rInfo.sID.getLength () > 0);
255         return bSuccess;
256     }
257     catch(const css::uno::Exception&)
258         {}
259 
260     return sal_False;
261 }
262 
263 //*****************************************************************************************************************
impl_forceUpdate()264 void TitleBarUpdate::impl_forceUpdate()
265 {
266     // SYNCHRONIZED ->
267     ReadGuard aReadLock(m_aLock);
268     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR ;
269     css::uno::Reference< css::frame::XFrame >              xFrame(m_xFrame.get(), css::uno::UNO_QUERY);
270     aReadLock.unlock();
271     // <- SYNCHRONIZED
272 
273     // frame already gone ? We hold it weak only ...
274     if ( ! xFrame.is())
275         return;
276 
277     // no window -> no chance to set/update title and icon
278     css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow();
279     if ( ! xWindow.is())
280         return;
281 
282     impl_updateIcon  (xFrame);
283     impl_updateTitle (xFrame);
284 }
285 
286 //*****************************************************************************************************************
impl_updateIcon(const css::uno::Reference<css::frame::XFrame> & xFrame)287 void TitleBarUpdate::impl_updateIcon(const css::uno::Reference< css::frame::XFrame >& xFrame)
288 {
289     css::uno::Reference< css::frame::XController > xController = xFrame->getController      ();
290     css::uno::Reference< css::awt::XWindow >       xWindow     = xFrame->getContainerWindow ();
291 
292     if (
293         ( ! xController.is() ) ||
294         ( ! xWindow.is()     )
295        )
296         return;
297 
298     // a) set default value to an invalid one. So we can start further searches for right icon id, if
299     //    first steps failed!
300     sal_Int32 nIcon = INVALID_ICON_ID;
301 
302     // b) try to find information on controller property set directly
303     //    Don't forget to catch possible exceptions - because these property is an optional one!
304     css::uno::Reference< css::beans::XPropertySet > xSet( xController, css::uno::UNO_QUERY );
305     if ( xSet.is() )
306     {
307         try
308         {
309             css::uno::Reference< css::beans::XPropertySetInfo > const xPSI( xSet->getPropertySetInfo(), css::uno::UNO_SET_THROW );
310             if ( xPSI->hasPropertyByName( CONTROLLER_PROPNAME_ICONID ) )
311                 xSet->getPropertyValue( CONTROLLER_PROPNAME_ICONID ) >>= nIcon;
312         }
313         catch(const css::uno::Exception&)
314         {
315             DBG_UNHANDLED_EXCEPTION();
316         }
317     }
318 
319     // c) if b) failed ... identify the used module and retrieve set icon from module config.
320     //    Tirck :-) Module was already specified outside and aInfo contains all needed informations.
321     if ( nIcon == INVALID_ICON_ID )
322 	{
323 		TModuleInfo aInfo;
324 		if (implst_getModuleInfo(xFrame, aInfo))
325 			nIcon = aInfo.nIcon;
326 	}
327 
328     // d) if all steps failed - use fallback :-)
329     //    ... means using the global staroffice icon
330     if( nIcon == INVALID_ICON_ID )
331         nIcon = DEFAULT_ICON_ID;
332 
333     // e) set icon on container window now
334     //    Don't forget SolarMutex! We use vcl directly :-(
335     //    Check window pointer for right WorkWindow class too!!!
336 
337     // VCL SYNCHRONIZED ->
338     ::vos::OClearableGuard aSolarLock( Application::GetSolarMutex() );
339 
340     Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
341     if (
342         ( pWindow                                 ) &&
343         ( pWindow->GetType() == WINDOW_WORKWINDOW )
344        )
345     {
346         WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
347         pWorkWindow->SetIcon( (sal_uInt16)nIcon );
348 
349         css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
350         rtl::OUString aURL;
351         if( xModel.is() )
352             aURL = xModel->getURL();
353         pWorkWindow->SetRepresentedURL( aURL );
354     }
355 
356     aSolarLock.clear();
357     // <- VCL SYNCHRONIZED
358 }
359 
360 //*****************************************************************************************************************
impl_updateTitle(const css::uno::Reference<css::frame::XFrame> & xFrame)361 void TitleBarUpdate::impl_updateTitle(const css::uno::Reference< css::frame::XFrame >& xFrame)
362 {
363 	// no window ... no chance to set any title -> return
364     css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
365     if ( ! xWindow.is() )
366         return;
367 
368 	css::uno::Reference< css::frame::XTitle > xTitle(xFrame, css::uno::UNO_QUERY);
369 	if ( ! xTitle.is() )
370 		return;
371 
372 	const ::rtl::OUString sTitle = xTitle->getTitle ();
373 
374     // VCL SYNCHRONIZED ->
375     ::vos::OClearableGuard aSolarLock( Application::GetSolarMutex() );
376 
377     Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
378     if (
379         ( pWindow                                 ) &&
380         ( pWindow->GetType() == WINDOW_WORKWINDOW )
381        )
382     {
383         WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
384         pWorkWindow->SetText( sTitle );
385     }
386 
387     aSolarLock.clear();
388     // <- VCL SYNCHRONIZED
389 }
390 
391 } // namespace framework
392