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