1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 #include <accelerators/acceleratorcache.hxx>
31 
32 //_______________________________________________
33 // own includes
34 
35 #ifndef __FRAMEWORK_XML_ACCELERATORCONFIGURATIONREADER_HXX_
36 #include <xml/acceleratorconfigurationreader.hxx>
37 #endif
38 #include <threadhelp/readguard.hxx>
39 #include <threadhelp/writeguard.hxx>
40 
41 //_______________________________________________
42 // interface includes
43 
44 #ifndef __COM_SUN_STAR_CONTAINER_ELEMENTEXISTEXCEPTION_HPP_
45 #include <com/sun/star/container/ElementExistException.hpp>
46 #endif
47 
48 #ifndef __COM_SUN_STAR_CONTAINER_NOSUCHELEMENTEXCEPTION_HPP_
49 #include <com/sun/star/container/NoSuchElementException.hpp>
50 #endif
51 
52 //_______________________________________________
53 // other includes
54 #include <vcl/svapp.hxx>
55 
56 namespace framework
57 {
58 
59 //-----------------------------------------------
60 AcceleratorCache::AcceleratorCache()
61     : ThreadHelpBase(&Application::GetSolarMutex())
62 {
63 }
64 
65 //-----------------------------------------------
66 AcceleratorCache::AcceleratorCache(const AcceleratorCache& rCopy)
67     : ThreadHelpBase(&Application::GetSolarMutex())
68 {
69     m_lCommand2Keys = rCopy.m_lCommand2Keys;
70     m_lKey2Commands = rCopy.m_lKey2Commands;
71 }
72 
73 //-----------------------------------------------
74 AcceleratorCache::~AcceleratorCache()
75 {
76     // Dont save anything automaticly here.
77     // The user has to do that explicitly!
78 }
79 
80 //-----------------------------------------------
81 void AcceleratorCache::takeOver(const AcceleratorCache& rCopy)
82 {
83     // SAFE -> ----------------------------------
84     WriteGuard aWriteLock(m_aLock);
85 
86     m_lCommand2Keys = rCopy.m_lCommand2Keys;
87     m_lKey2Commands = rCopy.m_lKey2Commands;
88 
89     aWriteLock.unlock();
90     // <- SAFE ----------------------------------
91 }
92 
93 //-----------------------------------------------
94 AcceleratorCache& AcceleratorCache::operator=(const AcceleratorCache& rCopy)
95 {
96     takeOver(rCopy);
97     return *this;
98 }
99 
100 //-----------------------------------------------
101 sal_Bool AcceleratorCache::hasKey(const css::awt::KeyEvent& aKey) const
102 {
103     // SAFE -> ----------------------------------
104     ReadGuard aReadLock(m_aLock);
105 
106     return (m_lKey2Commands.find(aKey) != m_lKey2Commands.end());
107     // <- SAFE ----------------------------------
108 }
109 
110 //-----------------------------------------------
111 sal_Bool AcceleratorCache::hasCommand(const ::rtl::OUString& sCommand) const
112 {
113     // SAFE -> ----------------------------------
114     ReadGuard aReadLock(m_aLock);
115 
116     return (m_lCommand2Keys.find(sCommand) != m_lCommand2Keys.end());
117     // <- SAFE ----------------------------------
118 }
119 
120 //-----------------------------------------------
121 AcceleratorCache::TKeyList AcceleratorCache::getAllKeys() const
122 {
123     TKeyList lKeys;
124 
125     // SAFE -> ----------------------------------
126     ReadGuard aReadLock(m_aLock);
127     lKeys.reserve(m_lKey2Commands.size());
128 
129     TKey2Commands::const_iterator pIt;
130     TKey2Commands::const_iterator pEnd = m_lKey2Commands.end();
131     for (  pIt  = m_lKey2Commands.begin();
132            pIt != pEnd  ;
133          ++pIt                           )
134     {
135         lKeys.push_back(pIt->first);
136     }
137 
138     aReadLock.unlock();
139     // <- SAFE ----------------------------------
140 
141     return lKeys;
142 }
143 
144 //-----------------------------------------------
145 void AcceleratorCache::setKeyCommandPair(const css::awt::KeyEvent& aKey    ,
146                                          const ::rtl::OUString&    sCommand)
147 {
148     // SAFE -> ----------------------------------
149     WriteGuard aWriteLock(m_aLock);
150 
151     // register command for the specified key
152     m_lKey2Commands[aKey] = sCommand;
153 
154     // update optimized structure to bind multiple keys to one command
155     TKeyList& rKeyList = m_lCommand2Keys[sCommand];
156     rKeyList.push_back(aKey);
157 
158     aWriteLock.unlock();
159     // <- SAFE ----------------------------------
160 }
161 
162 //-----------------------------------------------
163 AcceleratorCache::TKeyList AcceleratorCache::getKeysByCommand(const ::rtl::OUString& sCommand) const
164 {
165     TKeyList lKeys;
166 
167     // SAFE -> ----------------------------------
168     ReadGuard aReadLock(m_aLock);
169 
170     TCommand2Keys::const_iterator pCommand = m_lCommand2Keys.find(sCommand);
171     if (pCommand == m_lCommand2Keys.end())
172         throw css::container::NoSuchElementException(
173                 ::rtl::OUString(), css::uno::Reference< css::uno::XInterface >());
174     lKeys = pCommand->second;
175 
176     aReadLock.unlock();
177     // <- SAFE ----------------------------------
178 
179     return lKeys;
180 }
181 
182 //-----------------------------------------------
183 ::rtl::OUString AcceleratorCache::getCommandByKey(const css::awt::KeyEvent& aKey) const
184 {
185     ::rtl::OUString sCommand;
186 
187     // SAFE -> ----------------------------------
188     ReadGuard aReadLock(m_aLock);
189 
190     TKey2Commands::const_iterator pKey = m_lKey2Commands.find(aKey);
191     if (pKey == m_lKey2Commands.end())
192         throw css::container::NoSuchElementException(
193                 ::rtl::OUString(), css::uno::Reference< css::uno::XInterface >());
194     sCommand = pKey->second;
195 
196     aReadLock.unlock();
197     // <- SAFE ----------------------------------
198 
199     return sCommand;
200 }
201 
202 //-----------------------------------------------
203 void AcceleratorCache::removeKey(const css::awt::KeyEvent& aKey)
204 {
205     // SAFE -> ----------------------------------
206     WriteGuard aWriteLock(m_aLock);
207 
208     // check if key exists
209     TKey2Commands::const_iterator pKey = m_lKey2Commands.find(aKey);
210     if (pKey == m_lKey2Commands.end())
211         return;
212 
213     // get its registered command
214     // Because we must know its place inside the optimized
215     // structure, which bind keys to commands, too!
216     ::rtl::OUString sCommand = pKey->second;
217     pKey = m_lKey2Commands.end(); // nobody should use an undefined value .-)
218 
219     // remove key from primary list
220     m_lKey2Commands.erase(aKey);
221 
222     // remove key from optimized command list
223     m_lCommand2Keys.erase(sCommand);
224 
225     aWriteLock.unlock();
226     // <- SAFE ----------------------------------
227 }
228 
229 //-----------------------------------------------
230 void AcceleratorCache::removeCommand(const ::rtl::OUString& sCommand)
231 {
232     // SAFE -> ----------------------------------
233     WriteGuard aWriteLock(m_aLock);
234 
235     const TKeyList&                            lKeys = getKeysByCommand(sCommand);
236     AcceleratorCache::TKeyList::const_iterator pKey ;
237     for (  pKey  = lKeys.begin();
238            pKey != lKeys.end()  ;
239          ++pKey                 )
240     {
241         const css::awt::KeyEvent& rKey = *pKey;
242         removeKey(rKey);
243     }
244     m_lCommand2Keys.erase(sCommand);
245 
246     aWriteLock.unlock();
247     // <- SAFE ----------------------------------
248 }
249 
250 } // namespace framework
251