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 7918 : 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 516 : TitleBarUpdate::TitleBarUpdate(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
76 516 : : ThreadHelpBase (&Application::GetSolarMutex())
77 : , m_xSMGR (xSMGR )
78 1032 : , m_xFrame ( )
79 : {
80 516 : }
81 :
82 : //*****************************************************************************************************************
83 108 : TitleBarUpdate::~TitleBarUpdate()
84 : {
85 108 : }
86 :
87 : //*****************************************************************************************************************
88 516 : 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 516 : css::uno::Reference< css::frame::XFrame > xFrame;
94 516 : 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 516 : lArguments[0] >>= xFrame;
101 516 : 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 516 : WriteGuard aWriteLock(m_aLock);
109 : // hold the frame as weak reference(!) so it can die everytimes :-)
110 516 : m_xFrame = xFrame;
111 516 : aWriteLock.unlock();
112 : // <- SYNCHRONIZED
113 :
114 : // start listening
115 516 : xFrame->addFrameActionListener(this);
116 :
117 516 : css::uno::Reference< css::frame::XTitleChangeBroadcaster > xBroadcaster(xFrame, css::uno::UNO_QUERY);
118 516 : if (xBroadcaster.is ())
119 516 : xBroadcaster->addTitleChangeListener (this);
120 516 : }
121 :
122 : //*****************************************************************************************************************
123 2366 : 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 2366 : 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 614 : impl_forceUpdate ();
135 : }
136 2366 : }
137 :
138 : //*****************************************************************************************************************
139 98 : void SAL_CALL TitleBarUpdate::titleChanged(const css::frame::TitleChangedEvent& /* aEvent */)
140 : throw (css::uno::RuntimeException)
141 : {
142 98 : impl_forceUpdate ();
143 98 : }
144 :
145 : //*****************************************************************************************************************
146 98 : 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 98 : }
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 712 : void TitleBarUpdate::impl_updateApplicationID(const css::uno::Reference< css::frame::XFrame >& xFrame)
156 : {
157 712 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
158 712 : if ( ! xWindow.is() )
159 712 : return;
160 :
161 712 : ::rtl::OUString sApplicationID;
162 : try
163 : {
164 : // SYNCHRONIZED ->
165 712 : ReadGuard aReadLock(m_aLock);
166 712 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
167 712 : aReadLock.unlock();
168 : // <- SYNCHRONIZED
169 :
170 : css::uno::Reference< css::frame::XModuleManager2 > xModuleManager =
171 712 : css::frame::ModuleManager::create( comphelper::getComponentContext(xSMGR) );
172 :
173 712 : rtl::OUString aModuleId = xModuleManager->identify(xFrame);
174 614 : rtl::OUString sDesktopName;
175 :
176 806 : if ( aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.TextDocument")) ||
177 64 : aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.GlobalDocument")) ||
178 64 : aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.WebDocument")) ||
179 64 : aModuleId.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.xforms.XMLFormDocument")) )
180 550 : sDesktopName = ::rtl::OUString("writer");
181 64 : else if ( aModuleId == "com.sun.star.sheet.SpreadsheetDocument" )
182 56 : sDesktopName = ::rtl::OUString("calc");
183 8 : else if ( aModuleId == "com.sun.star.presentation.PresentationDocument" )
184 0 : sDesktopName = ::rtl::OUString("impress");
185 8 : else if ( aModuleId == "com.sun.star.drawing.DrawingDocument" )
186 0 : sDesktopName = ::rtl::OUString("draw");
187 8 : else if ( aModuleId == "com.sun.star.formula.FormulaProperties" )
188 8 : 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 614 : sApplicationID = utl::ConfigManager::getProductName().toAsciiLowerCase();
199 614 : sApplicationID += ::rtl::OUString(sal_Unicode('-'));
200 614 : sApplicationID += sDesktopName;
201 : }
202 98 : catch(const css::uno::Exception&)
203 : {
204 : }
205 :
206 : // VCL SYNCHRONIZED ->
207 712 : SolarMutexGuard aSolarGuard;
208 :
209 712 : Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
210 1424 : if (
211 : ( pWindow ) &&
212 712 : ( pWindow->GetType() == WINDOW_WORKWINDOW )
213 : )
214 : {
215 712 : WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
216 712 : pWorkWindow->SetApplicationID( sApplicationID );
217 712 : }
218 : // <- VCL SYNCHRONIZED
219 : }
220 :
221 :
222 : //*****************************************************************************************************************
223 614 : ::sal_Bool TitleBarUpdate::implst_getModuleInfo(const css::uno::Reference< css::frame::XFrame >& xFrame,
224 : TModuleInfo& rInfo )
225 : {
226 614 : if ( ! xFrame.is ())
227 0 : return sal_False;
228 :
229 : // SYNCHRONIZED ->
230 614 : ReadGuard aReadLock(m_aLock);
231 614 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
232 614 : aReadLock.unlock();
233 : // <- SYNCHRONIZED
234 :
235 : try
236 : {
237 : css::uno::Reference< css::frame::XModuleManager2 > xModuleManager =
238 614 : css::frame::ModuleManager::create( comphelper::getComponentContext(xSMGR) );
239 :
240 614 : rInfo.sID = xModuleManager->identify(xFrame);
241 614 : ::comphelper::SequenceAsHashMap lProps = xModuleManager->getByName (rInfo.sID);
242 :
243 606 : rInfo.sUIName = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_UINAME, ::rtl::OUString());
244 606 : 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 606 : ::sal_Bool bSuccess = !rInfo.sID.isEmpty();
249 606 : return bSuccess;
250 : }
251 8 : catch(const css::uno::Exception&)
252 : {}
253 :
254 8 : return sal_False;
255 : }
256 :
257 : //*****************************************************************************************************************
258 712 : void TitleBarUpdate::impl_forceUpdate()
259 : {
260 : // SYNCHRONIZED ->
261 712 : ReadGuard aReadLock(m_aLock);
262 712 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR ;
263 712 : css::uno::Reference< css::frame::XFrame > xFrame(m_xFrame.get(), css::uno::UNO_QUERY);
264 712 : aReadLock.unlock();
265 : // <- SYNCHRONIZED
266 :
267 : // frame already gone ? We hold it weak only ...
268 712 : if ( ! xFrame.is())
269 : return;
270 :
271 : // no window -> no chance to set/update title and icon
272 712 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow();
273 712 : if ( ! xWindow.is())
274 : return;
275 :
276 712 : impl_updateIcon (xFrame);
277 712 : impl_updateTitle (xFrame);
278 : #if defined(UNX) && !defined(MACOSX)
279 712 : impl_updateApplicationID (xFrame);
280 : #endif
281 : }
282 :
283 : //*****************************************************************************************************************
284 712 : void TitleBarUpdate::impl_updateIcon(const css::uno::Reference< css::frame::XFrame >& xFrame)
285 : {
286 712 : css::uno::Reference< css::frame::XController > xController = xFrame->getController ();
287 712 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
288 :
289 1326 : if (
290 712 : ( ! xController.is() ) ||
291 614 : ( ! xWindow.is() )
292 : )
293 712 : 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 614 : 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 614 : css::uno::Reference< css::beans::XPropertySet > xSet( xController, css::uno::UNO_QUERY );
302 614 : if ( xSet.is() )
303 : {
304 : try
305 : {
306 606 : css::uno::Reference< css::beans::XPropertySetInfo > const xPSI( xSet->getPropertySetInfo(), css::uno::UNO_SET_THROW );
307 606 : 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 614 : if ( nIcon == INVALID_ICON_ID )
319 : {
320 614 : TModuleInfo aInfo;
321 614 : if (implst_getModuleInfo(xFrame, aInfo))
322 606 : nIcon = aInfo.nIcon;
323 : }
324 :
325 : // d) if all steps failed - use fallback :-)
326 : // ... means using the global staroffice icon
327 614 : if( nIcon == INVALID_ICON_ID )
328 8 : 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 614 : SolarMutexGuard aSolarGuard;
336 :
337 614 : Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
338 1228 : if (
339 : ( pWindow ) &&
340 614 : ( pWindow->GetType() == WINDOW_WORKWINDOW )
341 : )
342 : {
343 614 : WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
344 614 : pWorkWindow->SetIcon( (sal_uInt16)nIcon );
345 :
346 614 : css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
347 614 : rtl::OUString aURL;
348 614 : if( xModel.is() )
349 614 : aURL = xModel->getURL();
350 614 : pWorkWindow->SetRepresentedURL( aURL );
351 614 : }
352 : // <- VCL SYNCHRONIZED
353 : }
354 :
355 : //*****************************************************************************************************************
356 712 : void TitleBarUpdate::impl_updateTitle(const css::uno::Reference< css::frame::XFrame >& xFrame)
357 : {
358 : // no window ... no chance to set any title -> return
359 712 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
360 712 : if ( ! xWindow.is() )
361 : return;
362 :
363 712 : css::uno::Reference< css::frame::XTitle > xTitle(xFrame, css::uno::UNO_QUERY);
364 712 : if ( ! xTitle.is() )
365 : return;
366 :
367 712 : const ::rtl::OUString sTitle = xTitle->getTitle ();
368 :
369 : // VCL SYNCHRONIZED ->
370 712 : SolarMutexGuard aSolarGuard;
371 :
372 712 : Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
373 1424 : if (
374 : ( pWindow ) &&
375 712 : ( pWindow->GetType() == WINDOW_WORKWINDOW )
376 : )
377 : {
378 712 : WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
379 712 : pWorkWindow->SetText( sTitle );
380 712 : }
381 : // <- VCL SYNCHRONIZED
382 : }
383 :
384 : } // namespace framework
385 :
386 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|