1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 #include "precompiled_sfx2.hxx"
23 
24 #include "sfx2/sidebar/CommandInfoProvider.hxx"
25 
26 #include <comphelper/processfactory.hxx>
27 #include <svtools/acceleratorexecute.hxx>
28 #include <cppuhelper/compbase1.hxx>
29 #include <cppuhelper/basemutex.hxx>
30 
31 #include <com/sun/star/frame/XModuleManager.hpp>
32 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
33 #include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
34 
35 using namespace css;
36 using namespace cssu;
37 using ::rtl::OUString;
38 
39 
40 #define A2S(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
41 
42 
43 namespace
44 {
45     typedef ::cppu::WeakComponentImplHelper1 <
46         css::lang::XEventListener
47         > FrameListenerInterfaceBase;
48     class FrameListener
49         : public ::cppu::BaseMutex,
50           public FrameListenerInterfaceBase
51     {
52     public:
FrameListener(sfx2::sidebar::CommandInfoProvider & rInfoProvider,const Reference<frame::XFrame> & rxFrame)53         FrameListener (sfx2::sidebar::CommandInfoProvider& rInfoProvider, const Reference<frame::XFrame>& rxFrame)
54             : FrameListenerInterfaceBase(m_aMutex),
55               mrInfoProvider(rInfoProvider),
56               mxFrame(rxFrame)
57         {
58             if (mxFrame.is())
59                 mxFrame->addEventListener(this);
60         }
~FrameListener(void)61         virtual ~FrameListener (void)
62         {
63         }
disposing(void)64         virtual void SAL_CALL disposing (void)
65         {
66             if (mxFrame.is())
67                 mxFrame->removeEventListener(this);
68         }
disposing(const css::lang::EventObject & rEvent)69         virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent)
70             throw (cssu::RuntimeException)
71         {
72             (void)rEvent;
73             mrInfoProvider.SetFrame(NULL);
74             mxFrame = NULL;
75         }
76 
77     private:
78         sfx2::sidebar::CommandInfoProvider& mrInfoProvider;
79         Reference<frame::XFrame> mxFrame;
80     };
81 }
82 
83 
84 
85 namespace sfx2 { namespace sidebar {
86 
Instance(void)87 CommandInfoProvider& CommandInfoProvider::Instance (void)
88 {
89     static CommandInfoProvider aProvider;
90     return aProvider;
91 }
92 
93 
94 
95 
CommandInfoProvider(void)96 CommandInfoProvider::CommandInfoProvider (void)
97     : mxServiceFactory(comphelper::getProcessServiceFactory()),
98       mxCachedDataFrame(),
99       mxCachedDocumentAcceleratorConfiguration(),
100       mxCachedModuleAcceleratorConfiguration(),
101       mxCachedGlobalAcceleratorConfiguration(),
102       msCachedModuleIdentifier(),
103       mxFrameListener()
104 {
105 }
106 
107 
108 
109 
~CommandInfoProvider(void)110 CommandInfoProvider::~CommandInfoProvider (void)
111 {
112     if (mxFrameListener.is())
113     {
114         mxFrameListener->dispose();
115         mxFrameListener = NULL;
116     }
117 }
118 
119 
120 
121 
GetLabelForCommand(const OUString & rsCommandName,const Reference<frame::XFrame> & rxFrame)122 OUString CommandInfoProvider::GetLabelForCommand (
123     const OUString& rsCommandName,
124     const Reference<frame::XFrame>& rxFrame)
125 {
126     SetFrame(rxFrame);
127 
128     const OUString sLabel (GetCommandLabel(rsCommandName));
129     const OUString sShortCut (GetCommandShortcut(rsCommandName));
130     if (sShortCut.getLength() > 0)
131         return sLabel + A2S(" (") + sShortCut + A2S(")");
132     else
133         return sLabel;
134 }
135 
136 
137 
138 
SetFrame(const Reference<frame::XFrame> & rxFrame)139 void CommandInfoProvider::SetFrame (const Reference<frame::XFrame>& rxFrame)
140 {
141     if (rxFrame != mxCachedDataFrame)
142     {
143         // Detach from the old frame.
144         if (mxFrameListener.is())
145         {
146             mxFrameListener->dispose();
147             mxFrameListener = NULL;
148         }
149 
150         // Release objects that are tied to the old frame.
151         mxCachedDocumentAcceleratorConfiguration = NULL;
152         mxCachedModuleAcceleratorConfiguration = NULL;
153         msCachedModuleIdentifier = OUString();
154         mxCachedDataFrame = rxFrame;
155 
156         // Connect to the new frame.
157         if (rxFrame.is())
158             mxFrameListener = new FrameListener(*this, rxFrame);
159     }
160 }
161 
162 
163 
164 
GetDocumentAcceleratorConfiguration(void)165 Reference<ui::XAcceleratorConfiguration> CommandInfoProvider::GetDocumentAcceleratorConfiguration (void)
166 {
167     if ( ! mxCachedDocumentAcceleratorConfiguration.is())
168     {
169         // Get the accelerator configuration for the document.
170         if (mxCachedDataFrame.is())
171         {
172             Reference<frame::XController> xController = mxCachedDataFrame->getController();
173             if (xController.is())
174             {
175                 Reference<frame::XModel> xModel (xController->getModel());
176                 if (xModel.is())
177                 {
178                     Reference<ui::XUIConfigurationManagerSupplier> xSupplier (xModel, UNO_QUERY);
179                     if (xSupplier.is())
180                     {
181                         Reference<ui::XUIConfigurationManager> xConfigurationManager(
182                             xSupplier->getUIConfigurationManager(),
183                             UNO_QUERY);
184                         if (xConfigurationManager.is())
185                         {
186                             mxCachedDocumentAcceleratorConfiguration = Reference<ui::XAcceleratorConfiguration>(
187                                 xConfigurationManager->getShortCutManager(),
188                                 UNO_QUERY);
189                         }
190                     }
191                 }
192             }
193         }
194     }
195     return mxCachedDocumentAcceleratorConfiguration;
196 }
197 
198 
199 
200 
GetModuleAcceleratorConfiguration(void)201 Reference<ui::XAcceleratorConfiguration> CommandInfoProvider::GetModuleAcceleratorConfiguration (void)
202 {
203     if ( ! mxCachedModuleAcceleratorConfiguration.is())
204     {
205         try
206         {
207             Reference<ui::XModuleUIConfigurationManagerSupplier> xSupplier (
208                 mxServiceFactory->createInstance(A2S("com.sun.star.ui.ModuleUIConfigurationManagerSupplier")),
209                 UNO_QUERY);
210             Reference<ui::XUIConfigurationManager> xManager (
211                 xSupplier->getUIConfigurationManager(GetModuleIdentifier()));
212             if (xManager.is())
213             {
214                 mxCachedModuleAcceleratorConfiguration = Reference<ui::XAcceleratorConfiguration>(
215                     xManager->getShortCutManager(),
216                     UNO_QUERY);
217             }
218         }
219         catch (Exception&)
220         {
221         }
222     }
223     return mxCachedModuleAcceleratorConfiguration;
224 }
225 
226 
227 
228 
GetGlobalAcceleratorConfiguration(void)229 Reference<ui::XAcceleratorConfiguration> CommandInfoProvider::GetGlobalAcceleratorConfiguration (void)
230 {
231     // Get the global accelerator configuration.
232     if ( ! mxCachedGlobalAcceleratorConfiguration.is())
233     {
234         mxCachedGlobalAcceleratorConfiguration = Reference<ui::XAcceleratorConfiguration>(
235             mxServiceFactory->createInstance(A2S("com.sun.star.ui.GlobalAcceleratorConfiguration")),
236             UNO_QUERY);
237     }
238 
239     return mxCachedGlobalAcceleratorConfiguration;
240 }
241 
242 
243 
244 
GetModuleIdentifier(void)245 OUString CommandInfoProvider::GetModuleIdentifier (void)
246 {
247     if (msCachedModuleIdentifier.getLength() == 0)
248     {
249         Reference<frame::XModuleManager> xModuleManager (
250             mxServiceFactory->createInstance(A2S("com.sun.star.frame.ModuleManager")),
251             UNO_QUERY);
252         if (xModuleManager.is())
253             msCachedModuleIdentifier = xModuleManager->identify(mxCachedDataFrame);
254     }
255     return msCachedModuleIdentifier;
256 }
257 
258 
259 
260 
GetCommandShortcut(const OUString & rsCommandName)261 OUString CommandInfoProvider::GetCommandShortcut (const OUString& rsCommandName)
262 {
263     OUString sShortcut;
264 
265     sShortcut = RetrieveShortcutsFromConfiguration(GetDocumentAcceleratorConfiguration(), rsCommandName);
266     if (sShortcut.getLength() > 0)
267         return sShortcut;
268 
269     sShortcut = RetrieveShortcutsFromConfiguration(GetModuleAcceleratorConfiguration(), rsCommandName);
270     if (sShortcut.getLength() > 0)
271         return sShortcut;
272 
273     sShortcut = RetrieveShortcutsFromConfiguration(GetGlobalAcceleratorConfiguration(), rsCommandName);
274     if (sShortcut.getLength() > 0)
275         return sShortcut;
276 
277     return OUString();
278 }
279 
280 
281 
282 
RetrieveShortcutsFromConfiguration(const Reference<ui::XAcceleratorConfiguration> & rxConfiguration,const OUString & rsCommandName)283 OUString CommandInfoProvider::RetrieveShortcutsFromConfiguration(
284     const Reference<ui::XAcceleratorConfiguration>& rxConfiguration,
285     const OUString& rsCommandName)
286 {
287     if (rxConfiguration.is())
288     {
289         try
290         {
291             Sequence<OUString> aCommands(1);
292             aCommands[0] = rsCommandName;
293 
294             Sequence<Any> aKeyCodes (rxConfiguration->getPreferredKeyEventsForCommandList(aCommands));
295             if (aCommands.getLength() == 1)
296             {
297                 css::awt::KeyEvent aKeyEvent;
298                 if (aKeyCodes[0] >>= aKeyEvent)
299                 {
300                     return svt::AcceleratorExecute::st_AWTKey2VCLKey(aKeyEvent).GetName();
301                 }
302             }
303         }
304         catch (lang::IllegalArgumentException&)
305         {
306         }
307     }
308     return OUString();
309 }
310 
311 
312 
313 
GetCommandProperties(const OUString & rsCommandName)314 Sequence<beans::PropertyValue> CommandInfoProvider::GetCommandProperties (const OUString& rsCommandName)
315 {
316     Sequence<beans::PropertyValue> aProperties;
317 
318     try
319     {
320         const OUString sModuleIdentifier (GetModuleIdentifier());
321         if (sModuleIdentifier.getLength() > 0)
322         {
323             Reference<container::XNameAccess> xNameAccess (
324                 mxServiceFactory->createInstance(
325                     OUString::createFromAscii("com.sun.star.frame.UICommandDescription")),
326                 UNO_QUERY);
327             Reference<container::XNameAccess> xUICommandLabels;
328             if (xNameAccess.is())
329                 if (xNameAccess->getByName(sModuleIdentifier) >>= xUICommandLabels)
330                     xUICommandLabels->getByName(rsCommandName) >>= aProperties;
331         }
332     }
333     catch (Exception&)
334     {
335     }
336 
337     return aProperties;
338 }
339 
340 
341 
342 
GetCommandLabel(const OUString & rsCommandName)343 OUString CommandInfoProvider::GetCommandLabel (const OUString& rsCommandName)
344 {
345     const Sequence<beans::PropertyValue> aProperties (GetCommandProperties(rsCommandName));
346     for (sal_Int32 nIndex=0; nIndex<aProperties.getLength(); ++nIndex)
347     {
348         if (aProperties[nIndex].Name.equalsAscii("Name"))
349         {
350             OUString sLabel;
351             aProperties[nIndex].Value >>= sLabel;
352             return sLabel;
353         }
354     }
355     return OUString();
356 }
357 
358 
359 } } // end of namespace sfx2/framework
360