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 0 : TitleBarUpdate::TitleBarUpdate(const css::uno::Reference< css::uno::XComponentContext >& xContext)
54 : : m_xContext (xContext )
55 0 : , m_xFrame ( )
56 : {
57 0 : }
58 :
59 0 : TitleBarUpdate::~TitleBarUpdate()
60 : {
61 0 : }
62 :
63 0 : 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 0 : css::uno::Reference< css::frame::XFrame > xFrame;
69 0 : if (lArguments.getLength() < 1)
70 : throw css::lang::IllegalArgumentException(
71 : "Empty argument list!",
72 : static_cast< ::cppu::OWeakObject* >(this),
73 0 : 1);
74 :
75 0 : lArguments[0] >>= xFrame;
76 0 : 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 0 : SolarMutexGuard g;
84 : // hold the frame as weak reference(!) so it can die everytimes :-)
85 0 : m_xFrame = xFrame;
86 : }
87 :
88 : // start listening
89 0 : xFrame->addFrameActionListener(this);
90 :
91 0 : css::uno::Reference< css::frame::XTitleChangeBroadcaster > xBroadcaster(xFrame, css::uno::UNO_QUERY);
92 0 : if (xBroadcaster.is ())
93 0 : xBroadcaster->addTitleChangeListener (this);
94 0 : }
95 :
96 0 : 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 0 : if (
102 0 : (aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED ) ||
103 0 : (aEvent.Action == css::frame::FrameAction_COMPONENT_REATTACHED) ||
104 0 : (aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING )
105 : )
106 : {
107 0 : impl_forceUpdate ();
108 : }
109 0 : }
110 :
111 0 : void SAL_CALL TitleBarUpdate::titleChanged(const css::frame::TitleChangedEvent& /* aEvent */)
112 : throw (css::uno::RuntimeException, std::exception)
113 : {
114 0 : impl_forceUpdate ();
115 0 : }
116 :
117 0 : 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 0 : }
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 0 : void TitleBarUpdate::impl_updateApplicationID(const css::uno::Reference< css::frame::XFrame >& xFrame)
127 : {
128 0 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
129 0 : if ( ! xWindow.is() )
130 0 : return;
131 :
132 0 : OUString sApplicationID;
133 :
134 : #if !defined(MACOSX)
135 : try
136 : {
137 : css::uno::Reference< css::frame::XModuleManager2 > xModuleManager =
138 0 : css::frame::ModuleManager::create( m_xContext );
139 :
140 0 : OUString sDesktopName;
141 0 : OUString aModuleId = xModuleManager->identify(xFrame);
142 0 : if ( aModuleId == "com.sun.star.text.TextDocument" ||
143 0 : aModuleId == "com.sun.star.text.GlobalDocument" ||
144 0 : aModuleId == "com.sun.star.text.WebDocument" ||
145 0 : aModuleId == "com.sun.star.xforms.XMLFormDocument" )
146 0 : sDesktopName = "Writer";
147 0 : else if ( aModuleId == "com.sun.star.sheet.SpreadsheetDocument" )
148 0 : sDesktopName = "Calc";
149 0 : else if ( aModuleId == "com.sun.star.presentation.PresentationDocument" )
150 0 : sDesktopName = "Impress";
151 0 : else if ( aModuleId == "com.sun.star.drawing.DrawingDocument" )
152 0 : sDesktopName = "Draw";
153 0 : else if ( aModuleId == "com.sun.star.formula.FormulaProperties" )
154 0 : sDesktopName = "Math";
155 0 : else if ( aModuleId == "com.sun.star.sdb.DatabaseDocument" ||
156 0 : aModuleId == "com.sun.star.sdb.OfficeDatabaseDocument" ||
157 0 : aModuleId == "com.sun.star.sdb.RelationDesign" ||
158 0 : aModuleId == "com.sun.star.sdb.QueryDesign" ||
159 0 : aModuleId == "com.sun.star.sdb.TableDesign" ||
160 0 : aModuleId == "com.sun.star.sdb.DataSourceBrowser" )
161 0 : sDesktopName = "Base";
162 : else
163 0 : sDesktopName = "Startcenter";
164 : #if defined(WNT)
165 : // We use a hardcoded product name matching the registry keys so applications can be associated with file types
166 : sApplicationID = "TheDocumentFoundation.LibreOffice.";
167 : sApplicationID += sDesktopName;
168 : #else
169 0 : sApplicationID = utl::ConfigManager::getProductName().toAsciiLowerCase();
170 0 : sApplicationID += "-";
171 0 : sApplicationID += sDesktopName.toAsciiLowerCase();
172 : #endif
173 : }
174 0 : catch(const css::uno::Exception&)
175 : {
176 : }
177 : #endif
178 :
179 : // VCL SYNCHRONIZED ->
180 0 : SolarMutexGuard aSolarGuard;
181 :
182 0 : Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
183 0 : if (
184 0 : ( pWindow ) &&
185 0 : ( pWindow->GetType() == WINDOW_WORKWINDOW )
186 : )
187 : {
188 0 : WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
189 0 : pWorkWindow->SetApplicationID( sApplicationID );
190 0 : }
191 : // <- VCL SYNCHRONIZED
192 : }
193 :
194 0 : bool TitleBarUpdate::implst_getModuleInfo(const css::uno::Reference< css::frame::XFrame >& xFrame,
195 : TModuleInfo& rInfo )
196 : {
197 0 : if ( ! xFrame.is ())
198 0 : return false;
199 :
200 : try
201 : {
202 : css::uno::Reference< css::frame::XModuleManager2 > xModuleManager =
203 0 : css::frame::ModuleManager::create( m_xContext );
204 :
205 0 : rInfo.sID = xModuleManager->identify(xFrame);
206 0 : ::comphelper::SequenceAsHashMap lProps = xModuleManager->getByName (rInfo.sID);
207 :
208 0 : rInfo.sUIName = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_UINAME, OUString());
209 0 : rInfo.nIcon = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_ICON , INVALID_ICON_ID );
210 :
211 : // Note: If we could retrieve a module id ... everything is OK.
212 : // UIName and Icon ID are optional values !
213 0 : bool bSuccess = !rInfo.sID.isEmpty();
214 0 : return bSuccess;
215 : }
216 0 : catch(const css::uno::Exception&)
217 : {}
218 :
219 0 : return false;
220 : }
221 :
222 0 : void TitleBarUpdate::impl_forceUpdate()
223 : {
224 0 : css::uno::Reference< css::frame::XFrame > xFrame;
225 : {
226 0 : SolarMutexGuard g;
227 0 : xFrame.set(m_xFrame.get(), css::uno::UNO_QUERY);
228 : }
229 :
230 : // frame already gone ? We hold it weak only ...
231 0 : if ( ! xFrame.is())
232 0 : return;
233 :
234 : // no window -> no chance to set/update title and icon
235 0 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow();
236 0 : if ( ! xWindow.is())
237 0 : return;
238 :
239 0 : impl_updateIcon (xFrame);
240 0 : impl_updateTitle (xFrame);
241 : #if !defined(MACOSX)
242 0 : impl_updateApplicationID (xFrame);
243 : #endif
244 : }
245 :
246 0 : void TitleBarUpdate::impl_updateIcon(const css::uno::Reference< css::frame::XFrame >& xFrame)
247 : {
248 0 : css::uno::Reference< css::frame::XController > xController = xFrame->getController ();
249 0 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
250 :
251 0 : if (
252 0 : ( ! xController.is() ) ||
253 0 : ( ! xWindow.is() )
254 : )
255 0 : return;
256 :
257 : // a) set default value to an invalid one. So we can start further searches for right icon id, if
258 : // first steps failed!
259 0 : sal_Int32 nIcon = INVALID_ICON_ID;
260 :
261 : // b) try to find information on controller property set directly
262 : // Don't forget to catch possible exceptions - because these property is an optional one!
263 0 : css::uno::Reference< css::beans::XPropertySet > xSet( xController, css::uno::UNO_QUERY );
264 0 : if ( xSet.is() )
265 : {
266 : try
267 : {
268 0 : css::uno::Reference< css::beans::XPropertySetInfo > const xPSI( xSet->getPropertySetInfo(), css::uno::UNO_SET_THROW );
269 0 : if ( xPSI->hasPropertyByName( "IconId" ) )
270 0 : xSet->getPropertyValue( "IconId" ) >>= nIcon;
271 : }
272 0 : catch(const css::uno::Exception&)
273 : {
274 : DBG_UNHANDLED_EXCEPTION();
275 : }
276 : }
277 :
278 : // c) if b) failed ... identify the used module and retrieve set icon from module config.
279 : // Tirck :-) Module was already specified outside and aInfo contains all needed information.
280 0 : if ( nIcon == INVALID_ICON_ID )
281 : {
282 0 : TModuleInfo aInfo;
283 0 : if (implst_getModuleInfo(xFrame, aInfo))
284 0 : nIcon = aInfo.nIcon;
285 : }
286 :
287 : // d) if all steps failed - use fallback :-)
288 : // ... means using the global staroffice icon
289 0 : if( nIcon == INVALID_ICON_ID )
290 0 : nIcon = DEFAULT_ICON_ID;
291 :
292 : // e) set icon on container window now
293 : // Don't forget SolarMutex! We use vcl directly :-(
294 : // Check window pointer for right WorkWindow class too!!!
295 :
296 : // VCL SYNCHRONIZED ->
297 0 : SolarMutexGuard aSolarGuard;
298 :
299 0 : Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
300 0 : if (
301 0 : ( pWindow ) &&
302 0 : ( pWindow->GetType() == WINDOW_WORKWINDOW )
303 : )
304 : {
305 0 : WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
306 0 : pWorkWindow->SetIcon( (sal_uInt16)nIcon );
307 :
308 0 : css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
309 0 : OUString aURL;
310 0 : if( xModel.is() )
311 0 : aURL = xModel->getURL();
312 0 : pWorkWindow->SetRepresentedURL( aURL );
313 0 : }
314 : // <- VCL SYNCHRONIZED
315 : }
316 :
317 0 : void TitleBarUpdate::impl_updateTitle(const css::uno::Reference< css::frame::XFrame >& xFrame)
318 : {
319 : // no window ... no chance to set any title -> return
320 0 : css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow ();
321 0 : if ( ! xWindow.is() )
322 0 : return;
323 :
324 0 : css::uno::Reference< css::frame::XTitle > xTitle(xFrame, css::uno::UNO_QUERY);
325 0 : if ( ! xTitle.is() )
326 0 : return;
327 :
328 0 : const OUString sTitle = xTitle->getTitle ();
329 :
330 : // VCL SYNCHRONIZED ->
331 0 : SolarMutexGuard aSolarGuard;
332 :
333 0 : Window* pWindow = (VCLUnoHelper::GetWindow( xWindow ));
334 0 : if (
335 0 : ( pWindow ) &&
336 0 : ( pWindow->GetType() == WINDOW_WORKWINDOW )
337 : )
338 : {
339 0 : WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
340 0 : pWorkWindow->SetText( sTitle );
341 0 : }
342 : // <- VCL SYNCHRONIZED
343 : }
344 :
345 : } // namespace framework
346 :
347 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|