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