Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <helper/titlebarupdate.hxx>
30 : :
31 : : #include <pattern/window.hxx>
32 : : #include <threadhelp/writeguard.hxx>
33 : : #include <threadhelp/readguard.hxx>
34 : : #include <macros/generic.hxx>
35 : : #include <services.h>
36 : : #include <properties.h>
37 : :
38 : : #include <com/sun/star/awt/XWindow.hpp>
39 : : #include <com/sun/star/lang/XServiceInfo.hpp>
40 : : #include <com/sun/star/lang/IllegalArgumentException.hpp>
41 : : #include <com/sun/star/frame/XModuleManager.hpp>
42 : : #include <com/sun/star/container/XNameAccess.hpp>
43 : : #include <com/sun/star/beans/XPropertySet.hpp>
44 : : #include <com/sun/star/beans/XMaterialHolder.hpp>
45 : : #include <com/sun/star/frame/XTitleChangeBroadcaster.hpp>
46 : : #include <com/sun/star/beans/NamedValue.hpp>
47 : :
48 : : #include <comphelper/sequenceashashmap.hxx>
49 : : #include <unotools/configmgr.hxx>
50 : : #include <unotools/bootstrap.hxx>
51 : : #include <vcl/window.hxx>
52 : : #include <vcl/syswin.hxx>
53 : : #include <toolkit/unohlp.hxx>
54 : : #include <vcl/svapp.hxx>
55 : : #include <vcl/wrkwin.hxx>
56 : : #include <tools/diagnose_ex.h>
57 : :
58 : : namespace framework{
59 : :
60 : : static const ::sal_Int32 INVALID_ICON_ID = -1;
61 : : static const ::sal_Int32 DEFAULT_ICON_ID = 0;
62 : :
63 : :
64 : : //*****************************************************************************************************************
65 : : // XInterface, XTypeProvider
66 : :
67 [ + + ][ + - ]: 141589 : DEFINE_XINTERFACE_5(TitleBarUpdate ,
68 : : OWeakObject ,
69 : : DIRECT_INTERFACE (css::lang::XTypeProvider ),
70 : : DIRECT_INTERFACE (css::lang::XInitialization ),
71 : : DIRECT_INTERFACE (css::frame::XFrameActionListener ),
72 : : DIRECT_INTERFACE (css::frame::XTitleChangeListener ),
73 : : DERIVED_INTERFACE(css::lang::XEventListener,css::frame::XFrameActionListener))
74 : :
75 [ # # ][ # # ]: 0 : DEFINE_XTYPEPROVIDER_5(TitleBarUpdate ,
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
76 : : css::lang::XTypeProvider ,
77 : : css::lang::XInitialization ,
78 : : css::frame::XFrameActionListener,
79 : : css::frame::XTitleChangeListener,
80 : : css::lang::XEventListener )
81 : :
82 : : //*****************************************************************************************************************
83 : 1745 : TitleBarUpdate::TitleBarUpdate(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
84 [ + - ]: 1745 : : ThreadHelpBase (&Application::GetSolarMutex())
85 : : , m_xSMGR (xSMGR )
86 [ + - ][ + - ]: 3490 : , m_xFrame ( )
87 : : {
88 : 1745 : }
89 : :
90 : : //*****************************************************************************************************************
91 [ + - ][ + - ]: 1444 : TitleBarUpdate::~TitleBarUpdate()
[ + - ]
92 : : {
93 [ - + ]: 2888 : }
94 : :
95 : : //*****************************************************************************************************************
96 : 1745 : void SAL_CALL TitleBarUpdate::initialize(const css::uno::Sequence< css::uno::Any >& lArguments)
97 : : throw(css::uno::Exception ,
98 : : css::uno::RuntimeException)
99 : : {
100 : : // check arguments
101 : 1745 : css::uno::Reference< css::frame::XFrame > xFrame;
102 [ - + ]: 1745 : if (lArguments.getLength() < 1)
103 : : throw css::lang::IllegalArgumentException(
104 : : DECLARE_ASCII("Empty argument list!"),
105 : : static_cast< ::cppu::OWeakObject* >(this),
106 [ # # ][ # # ]: 0 : 1);
[ # # ]
107 : :
108 [ + - ]: 1745 : lArguments[0] >>= xFrame;
109 [ - + ]: 1745 : if (!xFrame.is())
110 : : throw css::lang::IllegalArgumentException(
111 : : DECLARE_ASCII("No valid frame specified!"),
112 : : static_cast< ::cppu::OWeakObject* >(this),
113 [ # # ][ # # ]: 0 : 1);
[ # # ]
114 : :
115 : : // SYNCHRONIZED ->
116 [ + - ]: 1745 : WriteGuard aWriteLock(m_aLock);
117 : : // hold the frame as weak reference(!) so it can die everytimes :-)
118 [ + - ]: 1745 : m_xFrame = xFrame;
119 [ + - ]: 1745 : aWriteLock.unlock();
120 : : // <- SYNCHRONIZED
121 : :
122 : : // start listening
123 [ + - ][ + - ]: 1745 : xFrame->addFrameActionListener(this);
[ + - ]
124 : :
125 [ + - ]: 1745 : css::uno::Reference< css::frame::XTitleChangeBroadcaster > xBroadcaster(xFrame, css::uno::UNO_QUERY);
126 [ + - ]: 1745 : if (xBroadcaster.is ())
127 [ + - ][ + - ]: 1745 : xBroadcaster->addTitleChangeListener (this);
[ + - ][ + - ]
128 : 1745 : }
129 : :
130 : : //*****************************************************************************************************************
131 : 9587 : void SAL_CALL TitleBarUpdate::frameAction(const css::frame::FrameActionEvent& aEvent)
132 : : throw(css::uno::RuntimeException)
133 : : {
134 : : // we are interested on events only, which must trigger a title bar update
135 : : // because component was changed.
136 [ + + ][ + + ]: 9587 : if (
[ + + ]
137 : : (aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED ) ||
138 : : (aEvent.Action == css::frame::FrameAction_COMPONENT_REATTACHED) ||
139 : : (aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING )
140 : : )
141 : : {
142 : 3435 : impl_forceUpdate ();
143 : : }
144 : 9587 : }
145 : :
146 : : //*****************************************************************************************************************
147 : 1724 : void SAL_CALL TitleBarUpdate::titleChanged(const css::frame::TitleChangedEvent& /* aEvent */)
148 : : throw (css::uno::RuntimeException)
149 : : {
150 : 1724 : impl_forceUpdate ();
151 : 1724 : }
152 : :
153 : : //*****************************************************************************************************************
154 : 1654 : void SAL_CALL TitleBarUpdate::disposing(const css::lang::EventObject&)
155 : : throw(css::uno::RuntimeException)
156 : : {
157 : : // nothing todo here - because we hold the frame as weak reference only
158 : 1654 : }
159 : :
160 : : //http://live.gnome.org/GnomeShell/ApplicationBased
161 : : //See http://msdn.microsoft.com/en-us/library/dd378459(v=VS.85).aspx for future
162 : : //Windows 7 equivalent support
163 : 5159 : void TitleBarUpdate::impl_updateApplicationID(const css::uno::Reference< css::frame::XFrame >& xFrame)
164 : : {
165 [ + - ][ + - ]: 5159 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
166 [ - + ]: 5159 : if ( ! xWindow.is() )
167 : 5159 : return;
168 : :
169 : 5159 : ::rtl::OUString sApplicationID;
170 : : try
171 : : {
172 : : // SYNCHRONIZED ->
173 [ + - ]: 5159 : ReadGuard aReadLock(m_aLock);
174 : 5159 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
175 [ + - ]: 5159 : aReadLock.unlock();
176 : : // <- SYNCHRONIZED
177 : :
178 : : css::uno::Reference< css::frame::XModuleManager > xModuleManager(
179 [ + - ]: 5159 : xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
180 [ + - ][ + - ]: 5159 : css::uno::UNO_QUERY_THROW);
[ + - ]
181 : :
182 : : css::uno::Reference< css::container::XNameAccess > xConfig(
183 : : xModuleManager,
184 [ + - ]: 5159 : css::uno::UNO_QUERY_THROW);
185 : :
186 [ + - ][ + + ]: 5159 : rtl::OUString aModuleId = xModuleManager->identify(xFrame);
187 : 3441 : rtl::OUString sDesktopName;
188 : :
189 [ + + ][ + + : 6113 : if ( aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.TextDocument")) ||
+ - + + -
+ ]
190 : 894 : aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.GlobalDocument")) ||
191 : 894 : aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.WebDocument")) ||
192 : 884 : aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.xforms.XMLFormDocument")) )
193 : 2557 : sDesktopName = ::rtl::OUString("writer");
194 [ + + ]: 884 : else if ( aModuleId == "com.sun.star.sheet.SpreadsheetDocument" )
195 : 506 : sDesktopName = ::rtl::OUString("calc");
196 [ + + ]: 378 : else if ( aModuleId == "com.sun.star.presentation.PresentationDocument" )
197 : 56 : sDesktopName = ::rtl::OUString("impress");
198 [ + + ]: 322 : else if ( aModuleId == "com.sun.star.drawing.DrawingDocument" )
199 : 212 : sDesktopName = ::rtl::OUString("draw");
200 [ + + ]: 110 : else if ( aModuleId == "com.sun.star.formula.FormulaProperties" )
201 : 68 : sDesktopName = ::rtl::OUString("math");
202 [ + - + - : 252 : else if ( aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.sdb.DatabaseDocument")) ||
+ - + - +
- - + ]
[ - + ]
203 : 42 : aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.sdb.OfficeDatabaseDocument")) ||
204 : 42 : aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.sdb.RelationDesign")) ||
205 : 42 : aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.sdb.QueryDesign")) ||
206 : 42 : aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.sdb.TableDesign")) ||
207 : 42 : aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.sdb.DataSourceBrowser")) )
208 : 0 : sDesktopName = ::rtl::OUString("base");
209 : : else
210 : 42 : sDesktopName = ::rtl::OUString("startcenter");
211 : : sApplicationID = utl::ConfigManager::getProductName().
212 [ + - ]: 3441 : toAsciiLowerCase();
213 : 3441 : sApplicationID += ::rtl::OUString(sal_Unicode('-'));
214 [ - + ][ + - ]: 5159 : sApplicationID += sDesktopName;
215 : : }
216 [ + - ]: 1718 : catch(const css::uno::Exception&)
217 : : {
218 : : }
219 : :
220 : : // VCL SYNCHRONIZED ->
221 [ + - ]: 5159 : SolarMutexGuard aSolarGuard;
222 : :
223 [ + - ]: 5159 : Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
224 [ + - ][ + + ]: 10318 : if (
[ + + ]
225 : : ( pWindow ) &&
226 [ + - ]: 5159 : ( pWindow->GetType() == WINDOW_WORKWINDOW )
227 : : )
228 : : {
229 : 5153 : WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
230 [ + - ]: 5153 : pWorkWindow->SetApplicationID( sApplicationID );
231 [ + - ][ + - ]: 5159 : }
232 : : // <- VCL SYNCHRONIZED
233 : : }
234 : :
235 : :
236 : : //*****************************************************************************************************************
237 : 3505 : ::sal_Bool TitleBarUpdate::implst_getModuleInfo(const css::uno::Reference< css::frame::XFrame >& xFrame,
238 : : TModuleInfo& rInfo )
239 : : {
240 [ - + ]: 3505 : if ( ! xFrame.is ())
241 : 0 : return sal_False;
242 : :
243 : : // SYNCHRONIZED ->
244 [ + - ]: 3505 : ReadGuard aReadLock(m_aLock);
245 : 3505 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
246 [ + - ]: 3505 : aReadLock.unlock();
247 : : // <- SYNCHRONIZED
248 : :
249 : : try
250 : : {
251 : : css::uno::Reference< css::frame::XModuleManager > xModuleManager(
252 [ + - ]: 3505 : xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
253 [ + - ][ + - ]: 3505 : css::uno::UNO_QUERY_THROW);
[ + - ]
254 : :
255 : : css::uno::Reference< css::container::XNameAccess > xConfig(
256 : : xModuleManager,
257 [ + - ]: 3505 : css::uno::UNO_QUERY_THROW);
258 : :
259 [ + - ][ + + ]: 3505 : rInfo.sID = xModuleManager->identify(xFrame);
260 [ + - ][ + - ]: 3441 : ::comphelper::SequenceAsHashMap lProps = xConfig->getByName (rInfo.sID);
[ + - ]
261 : :
262 [ + - ][ + - ]: 3441 : rInfo.sUIName = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_UINAME, ::rtl::OUString());
263 [ + - ][ + - ]: 3441 : rInfo.nIcon = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_ICON , INVALID_ICON_ID );
264 : :
265 : : // Note: If we could retrieve a module id ... everything is OK.
266 : : // UIName and Icon ID are optional values !
267 : 3441 : ::sal_Bool bSuccess = !rInfo.sID.isEmpty();
268 [ - + ][ + - ]: 3505 : return bSuccess;
269 : : }
270 [ + - ]: 64 : catch(const css::uno::Exception&)
271 : : {}
272 : :
273 [ + - ]: 3505 : return sal_False;
274 : : }
275 : :
276 : : //*****************************************************************************************************************
277 : 5159 : void TitleBarUpdate::impl_forceUpdate()
278 : : {
279 : : // SYNCHRONIZED ->
280 [ + - ]: 5159 : ReadGuard aReadLock(m_aLock);
281 : 5159 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR ;
282 [ + - ][ + - ]: 5159 : css::uno::Reference< css::frame::XFrame > xFrame(m_xFrame.get(), css::uno::UNO_QUERY);
283 [ + - ]: 5159 : aReadLock.unlock();
284 : : // <- SYNCHRONIZED
285 : :
286 : : // frame already gone ? We hold it weak only ...
287 [ - + ]: 5159 : if ( ! xFrame.is())
288 : : return;
289 : :
290 : : // no window -> no chance to set/update title and icon
291 [ + - ][ + - ]: 5159 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow();
292 [ - + ]: 5159 : if ( ! xWindow.is())
293 : : return;
294 : :
295 [ + - ]: 5159 : impl_updateIcon (xFrame);
296 [ + - ]: 5159 : impl_updateTitle (xFrame);
297 : : #if defined(UNX) && !defined(MACOSX)
298 [ + - ][ - + ]: 5159 : impl_updateApplicationID (xFrame);
[ - + ][ - + ]
[ + - ][ + - ]
299 : : #endif
300 : : }
301 : :
302 : : //*****************************************************************************************************************
303 : 5159 : void TitleBarUpdate::impl_updateIcon(const css::uno::Reference< css::frame::XFrame >& xFrame)
304 : : {
305 [ + - ][ + - ]: 5159 : css::uno::Reference< css::frame::XController > xController = xFrame->getController ();
306 [ + - ][ + - ]: 5159 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
307 : :
308 [ + + ]: 8664 : if (
[ + + - + ]
309 : 5159 : ( ! xController.is() ) ||
310 : 3505 : ( ! xWindow.is() )
311 : : )
312 : 5159 : return;
313 : :
314 : : // a) set default value to an invalid one. So we can start further searches for right icon id, if
315 : : // first steps failed!
316 : 3505 : sal_Int32 nIcon = INVALID_ICON_ID;
317 : :
318 : : // b) try to find information on controller property set directly
319 : : // Don't forget to catch possible exceptions - because these property is an optional one!
320 [ + - ]: 3505 : css::uno::Reference< css::beans::XPropertySet > xSet( xController, css::uno::UNO_QUERY );
321 [ + + ]: 3505 : if ( xSet.is() )
322 : : {
323 : : try
324 : : {
325 [ + - ][ + - ]: 3283 : css::uno::Reference< css::beans::XPropertySetInfo > const xPSI( xSet->getPropertySetInfo(), css::uno::UNO_SET_THROW );
[ + - ]
326 [ + - ][ + - ]: 3283 : if ( xPSI->hasPropertyByName( DECLARE_ASCII("IconId") ) )
[ - + ][ + - ]
327 [ # # ][ # # ]: 3283 : xSet->getPropertyValue( DECLARE_ASCII("IconId") ) >>= nIcon;
[ # # ][ # # ]
328 : : }
329 [ # # ]: 0 : catch(const css::uno::Exception&)
330 : : {
331 : : DBG_UNHANDLED_EXCEPTION();
332 : : }
333 : : }
334 : :
335 : : // c) if b) failed ... identify the used module and retrieve set icon from module config.
336 : : // Tirck :-) Module was already specified outside and aInfo contains all needed informations.
337 [ + - ]: 3505 : if ( nIcon == INVALID_ICON_ID )
338 : : {
339 : 3505 : TModuleInfo aInfo;
340 [ + + ][ + - ]: 3505 : if (implst_getModuleInfo(xFrame, aInfo))
341 : 3505 : nIcon = aInfo.nIcon;
342 : : }
343 : :
344 : : // d) if all steps failed - use fallback :-)
345 : : // ... means using the global staroffice icon
346 [ + + ]: 3505 : if( nIcon == INVALID_ICON_ID )
347 : 64 : nIcon = DEFAULT_ICON_ID;
348 : :
349 : : // e) set icon on container window now
350 : : // Don't forget SolarMutex! We use vcl directly :-(
351 : : // Check window pointer for right WorkWindow class too!!!
352 : :
353 : : // VCL SYNCHRONIZED ->
354 [ + - ]: 3505 : SolarMutexGuard aSolarGuard;
355 : :
356 [ + - ]: 3505 : Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
357 [ + - ][ + + ]: 7010 : if (
[ + + ]
358 : : ( pWindow ) &&
359 [ + - ]: 3505 : ( pWindow->GetType() == WINDOW_WORKWINDOW )
360 : : )
361 : : {
362 : 3501 : WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
363 [ + - ]: 3501 : pWorkWindow->SetIcon( (sal_uInt16)nIcon );
364 : :
365 [ + - ][ + - ]: 3501 : css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
366 : 3501 : rtl::OUString aURL;
367 [ + + ]: 3501 : if( xModel.is() )
368 [ + - ][ + - ]: 3431 : aURL = xModel->getURL();
369 [ + - ]: 3501 : pWorkWindow->SetRepresentedURL( aURL );
370 [ + - ][ + + ]: 5159 : }
[ + + ]
371 : : // <- VCL SYNCHRONIZED
372 : : }
373 : :
374 : : //*****************************************************************************************************************
375 : 5159 : void TitleBarUpdate::impl_updateTitle(const css::uno::Reference< css::frame::XFrame >& xFrame)
376 : : {
377 : : // no window ... no chance to set any title -> return
378 [ + - ][ + - ]: 5159 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
379 [ - + ]: 5159 : if ( ! xWindow.is() )
380 : : return;
381 : :
382 [ + - ]: 5159 : css::uno::Reference< css::frame::XTitle > xTitle(xFrame, css::uno::UNO_QUERY);
383 [ - + ]: 5159 : if ( ! xTitle.is() )
384 : : return;
385 : :
386 [ + - ][ + - ]: 5159 : const ::rtl::OUString sTitle = xTitle->getTitle ();
387 : :
388 : : // VCL SYNCHRONIZED ->
389 [ + - ]: 5159 : SolarMutexGuard aSolarGuard;
390 : :
391 [ + - ]: 5159 : Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
392 [ + - ][ + + ]: 10318 : if (
[ + + ]
393 : : ( pWindow ) &&
394 [ + - ]: 5159 : ( pWindow->GetType() == WINDOW_WORKWINDOW )
395 : : )
396 : : {
397 : 5153 : WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
398 [ + - ][ + - ]: 5153 : pWorkWindow->SetText( sTitle );
[ + - ]
399 [ + - ][ - + ]: 5159 : }
[ + - ]
400 : : // <- VCL SYNCHRONIZED
401 : : }
402 : :
403 : : } // namespace framework
404 : :
405 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|