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