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 <macros/generic.hxx>
24 : #include <services.h>
25 : #include <properties.h>
26 :
27 : #include <com/sun/star/awt/XWindow.hpp>
28 : #include <com/sun/star/lang/XServiceInfo.hpp>
29 : #include <com/sun/star/lang/IllegalArgumentException.hpp>
30 : #include <com/sun/star/frame/ModuleManager.hpp>
31 : #include <com/sun/star/container/XNameAccess.hpp>
32 : #include <com/sun/star/beans/XPropertySet.hpp>
33 : #include <com/sun/star/beans/XMaterialHolder.hpp>
34 : #include <com/sun/star/frame/XTitleChangeBroadcaster.hpp>
35 : #include <com/sun/star/beans/NamedValue.hpp>
36 :
37 : #include <comphelper/processfactory.hxx>
38 : #include <comphelper/sequenceashashmap.hxx>
39 : #include <unotools/configmgr.hxx>
40 : #include <unotools/bootstrap.hxx>
41 : #include <vcl/window.hxx>
42 : #include <vcl/syswin.hxx>
43 : #include <toolkit/helper/vclunohelper.hxx>
44 : #include <vcl/svapp.hxx>
45 : #include <vcl/wrkwin.hxx>
46 : #include <tools/diagnose_ex.h>
47 :
48 : namespace framework{
49 :
50 : static const ::sal_Int32 INVALID_ICON_ID = -1;
51 : static const ::sal_Int32 DEFAULT_ICON_ID = 0;
52 :
53 3279 : TitleBarUpdate::TitleBarUpdate(const css::uno::Reference< css::uno::XComponentContext >& xContext)
54 : : m_xContext (xContext )
55 3279 : , m_xFrame ( )
56 : {
57 3279 : }
58 :
59 5106 : TitleBarUpdate::~TitleBarUpdate()
60 : {
61 5106 : }
62 :
63 3279 : void SAL_CALL TitleBarUpdate::initialize(const css::uno::Sequence< css::uno::Any >& lArguments)
64 : throw(css::uno::Exception ,
65 : css::uno::RuntimeException, std::exception)
66 : {
67 : // check arguments
68 3279 : css::uno::Reference< css::frame::XFrame > xFrame;
69 3279 : if (lArguments.getLength() < 1)
70 : throw css::lang::IllegalArgumentException(
71 : "Empty argument list!",
72 : static_cast< ::cppu::OWeakObject* >(this),
73 0 : 1);
74 :
75 3279 : lArguments[0] >>= xFrame;
76 3279 : if (!xFrame.is())
77 : throw css::lang::IllegalArgumentException(
78 : "No valid frame specified!",
79 : static_cast< ::cppu::OWeakObject* >(this),
80 0 : 1);
81 :
82 : {
83 3279 : SolarMutexGuard g;
84 : // hold the frame as weak reference(!) so it can die everytimes :-)
85 3279 : m_xFrame = xFrame;
86 : }
87 :
88 : // start listening
89 3279 : xFrame->addFrameActionListener(this);
90 :
91 6558 : css::uno::Reference< css::frame::XTitleChangeBroadcaster > xBroadcaster(xFrame, css::uno::UNO_QUERY);
92 3279 : if (xBroadcaster.is ())
93 6558 : xBroadcaster->addTitleChangeListener (this);
94 3279 : }
95 :
96 18251 : void SAL_CALL TitleBarUpdate::frameAction(const css::frame::FrameActionEvent& aEvent)
97 : throw(css::uno::RuntimeException, std::exception)
98 : {
99 : // we are interested on events only, which must trigger a title bar update
100 : // because component was changed.
101 18251 : if (
102 33228 : (aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED ) ||
103 29938 : (aEvent.Action == css::frame::FrameAction_COMPONENT_REATTACHED) ||
104 14961 : (aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING )
105 : )
106 : {
107 6571 : impl_forceUpdate ();
108 : }
109 18251 : }
110 :
111 3340 : void SAL_CALL TitleBarUpdate::titleChanged(const css::frame::TitleChangedEvent& /* aEvent */)
112 : throw (css::uno::RuntimeException, std::exception)
113 : {
114 3340 : impl_forceUpdate ();
115 3340 : }
116 :
117 3270 : void SAL_CALL TitleBarUpdate::disposing(const css::lang::EventObject&)
118 : throw(css::uno::RuntimeException, std::exception)
119 : {
120 : // nothing todo here - because we hold the frame as weak reference only
121 3270 : }
122 :
123 : //http://live.gnome.org/GnomeShell/ApplicationBased
124 : //See http://msdn.microsoft.com/en-us/library/dd378459(v=VS.85).aspx for future
125 : //Windows 7 equivalent support
126 9911 : void TitleBarUpdate::impl_updateApplicationID(const css::uno::Reference< css::frame::XFrame >& xFrame)
127 : {
128 9911 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
129 9911 : if ( ! xWindow.is() )
130 9911 : return;
131 :
132 19822 : OUString sApplicationID;
133 :
134 : #if !defined(MACOSX)
135 : try
136 : {
137 : css::uno::Reference< css::frame::XModuleManager2 > xModuleManager =
138 9911 : css::frame::ModuleManager::create( m_xContext );
139 :
140 19822 : OUString sDesktopName;
141 16520 : OUString aModuleId = xModuleManager->identify(xFrame);
142 6609 : if ( aModuleId.startsWith("com.sun.star.text.") || aModuleId.startsWith("com.sun.star.xforms.") )
143 5551 : sDesktopName = "Writer";
144 1058 : else if ( aModuleId.startsWith("com.sun.star.sheet.") )
145 720 : sDesktopName = "Calc";
146 338 : else if ( aModuleId.startsWith("com.sun.star.presentation.") )
147 90 : sDesktopName = "Impress";
148 248 : else if ( aModuleId.startsWith("com.sun.star.drawing." ) )
149 173 : sDesktopName = "Draw";
150 75 : else if ( aModuleId.startsWith("com.sun.star.formula." ) )
151 42 : sDesktopName = "Math";
152 33 : else if ( aModuleId.startsWith("com.sun.star.sdb.") )
153 12 : sDesktopName = "Base";
154 : else
155 21 : sDesktopName = "Startcenter";
156 : #if defined(WNT)
157 : // We use a hardcoded product name matching the registry keys so applications can be associated with file types
158 : sApplicationID = "TheDocumentFoundation.LibreOffice.";
159 : sApplicationID += sDesktopName;
160 : #else
161 6609 : sApplicationID = utl::ConfigManager::getProductName().toAsciiLowerCase();
162 6609 : sApplicationID += "-";
163 16520 : sApplicationID += sDesktopName.toAsciiLowerCase();
164 : #endif
165 : }
166 3302 : catch(const css::uno::Exception&)
167 : {
168 : }
169 : #endif
170 :
171 : // VCL SYNCHRONIZED ->
172 19822 : SolarMutexGuard aSolarGuard;
173 :
174 9911 : vcl::Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
175 9911 : if (
176 19822 : ( pWindow ) &&
177 9911 : ( pWindow->GetType() == WINDOW_WORKWINDOW )
178 : )
179 : {
180 9908 : WorkWindow* pWorkWindow = static_cast<WorkWindow*>(pWindow);
181 9908 : pWorkWindow->SetApplicationID( sApplicationID );
182 9911 : }
183 : // <- VCL SYNCHRONIZED
184 : }
185 :
186 6641 : bool TitleBarUpdate::implst_getModuleInfo(const css::uno::Reference< css::frame::XFrame >& xFrame,
187 : TModuleInfo& rInfo )
188 : {
189 6641 : if ( ! xFrame.is ())
190 0 : return false;
191 :
192 : try
193 : {
194 : css::uno::Reference< css::frame::XModuleManager2 > xModuleManager =
195 6641 : css::frame::ModuleManager::create( m_xContext );
196 :
197 6641 : rInfo.sID = xModuleManager->identify(xFrame);
198 13218 : ::comphelper::SequenceAsHashMap lProps = xModuleManager->getByName (rInfo.sID);
199 :
200 6609 : rInfo.sUIName = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_UINAME, OUString());
201 6609 : rInfo.nIcon = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_ICON , INVALID_ICON_ID );
202 :
203 : // Note: If we could retrieve a module id ... everything is OK.
204 : // UIName and Icon ID are optional values !
205 6609 : bool bSuccess = !rInfo.sID.isEmpty();
206 13250 : return bSuccess;
207 : }
208 32 : catch(const css::uno::Exception&)
209 : {}
210 :
211 32 : return false;
212 : }
213 :
214 9911 : void TitleBarUpdate::impl_forceUpdate()
215 : {
216 9911 : css::uno::Reference< css::frame::XFrame > xFrame;
217 : {
218 9911 : SolarMutexGuard g;
219 9911 : xFrame.set(m_xFrame.get(), css::uno::UNO_QUERY);
220 : }
221 :
222 : // frame already gone ? We hold it weak only ...
223 9911 : if ( ! xFrame.is())
224 0 : return;
225 :
226 : // no window -> no chance to set/update title and icon
227 19822 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow();
228 9911 : if ( ! xWindow.is())
229 0 : return;
230 :
231 9911 : impl_updateIcon (xFrame);
232 9911 : impl_updateTitle (xFrame);
233 : #if !defined(MACOSX)
234 19822 : impl_updateApplicationID (xFrame);
235 : #endif
236 : }
237 :
238 9911 : void TitleBarUpdate::impl_updateIcon(const css::uno::Reference< css::frame::XFrame >& xFrame)
239 : {
240 9911 : css::uno::Reference< css::frame::XController > xController = xFrame->getController ();
241 16552 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
242 :
243 9911 : if (
244 16552 : ( ! xController.is() ) ||
245 6641 : ( ! xWindow.is() )
246 : )
247 13181 : return;
248 :
249 : // a) set default value to an invalid one. So we can start further searches for right icon id, if
250 : // first steps failed!
251 6641 : sal_Int32 nIcon = INVALID_ICON_ID;
252 :
253 : // b) try to find information on controller property set directly
254 : // Don't forget to catch possible exceptions - because these property is an optional one!
255 13282 : css::uno::Reference< css::beans::XPropertySet > xSet( xController, css::uno::UNO_QUERY );
256 6641 : if ( xSet.is() )
257 : {
258 : try
259 : {
260 6510 : css::uno::Reference< css::beans::XPropertySetInfo > const xPSI( xSet->getPropertySetInfo(), css::uno::UNO_SET_THROW );
261 6510 : if ( xPSI->hasPropertyByName( "IconId" ) )
262 0 : xSet->getPropertyValue( "IconId" ) >>= nIcon;
263 : }
264 0 : catch(const css::uno::Exception&)
265 : {
266 : DBG_UNHANDLED_EXCEPTION();
267 : }
268 : }
269 :
270 : // c) if b) failed ... identify the used module and retrieve set icon from module config.
271 : // Tirck :-) Module was already specified outside and aInfo contains all needed information.
272 6641 : if ( nIcon == INVALID_ICON_ID )
273 : {
274 6641 : TModuleInfo aInfo;
275 6641 : if (implst_getModuleInfo(xFrame, aInfo))
276 6609 : nIcon = aInfo.nIcon;
277 : }
278 :
279 : // d) if all steps failed - use fallback :-)
280 : // ... means using the global staroffice icon
281 6641 : if( nIcon == INVALID_ICON_ID )
282 32 : nIcon = DEFAULT_ICON_ID;
283 :
284 : // e) set icon on container window now
285 : // Don't forget SolarMutex! We use vcl directly :-(
286 : // Check window pointer for right WorkWindow class too!!!
287 :
288 : // VCL SYNCHRONIZED ->
289 13282 : SolarMutexGuard aSolarGuard;
290 :
291 6641 : vcl::Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
292 6641 : if (
293 13282 : ( pWindow ) &&
294 6641 : ( pWindow->GetType() == WINDOW_WORKWINDOW )
295 : )
296 : {
297 6639 : WorkWindow* pWorkWindow = static_cast<WorkWindow*>(pWindow);
298 6639 : pWorkWindow->SetIcon( (sal_uInt16)nIcon );
299 :
300 6639 : css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
301 13278 : OUString aURL;
302 6639 : if( xModel.is() )
303 6604 : aURL = xModel->getURL();
304 13278 : pWorkWindow->SetRepresentedURL( aURL );
305 6641 : }
306 : // <- VCL SYNCHRONIZED
307 : }
308 :
309 9911 : void TitleBarUpdate::impl_updateTitle(const css::uno::Reference< css::frame::XFrame >& xFrame)
310 : {
311 : // no window ... no chance to set any title -> return
312 9911 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
313 9911 : if ( ! xWindow.is() )
314 0 : return;
315 :
316 19822 : css::uno::Reference< css::frame::XTitle > xTitle(xFrame, css::uno::UNO_QUERY);
317 9911 : if ( ! xTitle.is() )
318 0 : return;
319 :
320 19822 : const OUString sTitle = xTitle->getTitle ();
321 :
322 : // VCL SYNCHRONIZED ->
323 19822 : SolarMutexGuard aSolarGuard;
324 :
325 9911 : vcl::Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
326 9911 : if (
327 19822 : ( pWindow ) &&
328 9911 : ( pWindow->GetType() == WINDOW_WORKWINDOW )
329 : )
330 : {
331 9908 : WorkWindow* pWorkWindow = static_cast<WorkWindow*>(pWindow);
332 9908 : pWorkWindow->SetText( sTitle );
333 9911 : }
334 : // <- VCL SYNCHRONIZED
335 : }
336 :
337 : } // namespace framework
338 :
339 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|