LibreOffice Module vcl (master)  1
accel.cxx
Go to the documentation of this file.
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 <sal/log.hxx>
21 #include <osl/diagnose.h>
22 #include <tools/solar.h>
23 #include <accel.h>
24 #include <vcl/accel.hxx>
25 #include <map>
26 #include <vector>
27 
28 typedef ::std::map< sal_uLong, ImplAccelEntry* > ImplAccelMap;
29 typedef ::std::vector< std::unique_ptr<ImplAccelEntry> > ImplAccelList;
30 
31 #define ACCELENTRY_NOTFOUND (sal_uInt16(0xFFFF))
32 
34 {
35 public:
36  ImplAccelMap maKeyMap; // for keycodes, generated with a code
37  ImplAccelList maIdList; // Id-List
38 };
39 
40 static sal_uInt16 ImplAccelEntryGetIndex( ImplAccelList* pList, sal_uInt16 nId,
41  sal_uInt16* pIndex = nullptr )
42 {
43  size_t nLow;
44  size_t nHigh;
45  size_t nMid;
46  size_t nCount = pList->size();
47  sal_uInt16 nCompareId;
48 
49  // check if first key is larger then the key to compare
50  if ( !nCount || (nId < (*pList)[ 0 ]->mnId) )
51  {
52  if ( pIndex )
53  *pIndex = 0;
54  return ACCELENTRY_NOTFOUND;
55  }
56 
57  // Binary search
58  nLow = 0;
59  nHigh = nCount-1;
60  do
61  {
62  nMid = (nLow + nHigh) / 2;
63  nCompareId = (*pList)[ nMid ]->mnId;
64  if ( nId < nCompareId )
65  nHigh = nMid-1;
66  else
67  {
68  if ( nId > nCompareId )
69  nLow = nMid + 1;
70  else
71  return static_cast<sal_uInt16>(nMid);
72  }
73  }
74  while ( nLow <= nHigh );
75 
76  if ( pIndex )
77  {
78  if ( nId > nCompareId )
79  *pIndex = static_cast<sal_uInt16>(nMid+1);
80  else
81  *pIndex = static_cast<sal_uInt16>(nMid);
82  }
83 
84  return ACCELENTRY_NOTFOUND;
85 }
86 
87 static void ImplAccelEntryInsert( ImplAccelList* pList, std::unique_ptr<ImplAccelEntry> pEntry )
88 {
89  sal_uInt16 nInsIndex(0);
90  std::vector<ImplAccelEntry *>::size_type nIndex = ImplAccelEntryGetIndex( pList, pEntry->mnId, &nInsIndex );
91 
92  if ( nIndex != ACCELENTRY_NOTFOUND )
93  {
94  do
95  {
96  nIndex++;
97  ImplAccelEntry* pTempEntry = nullptr;
98  if ( nIndex < pList->size() )
99  pTempEntry = (*pList)[ nIndex ].get();
100  if ( !pTempEntry || (pTempEntry->mnId != pEntry->mnId) )
101  break;
102  }
103  while ( nIndex < pList->size() );
104 
105  if ( nIndex < pList->size() ) {
106  pList->insert( pList->begin() + nIndex, std::move(pEntry) );
107  } else {
108  pList->push_back( std::move(pEntry) );
109  }
110  }
111  else {
112  if ( nInsIndex < pList->size() ) {
113  pList->insert( pList->begin() + nInsIndex, std::move(pEntry) );
114  } else {
115  pList->push_back( std::move(pEntry) );
116  }
117  }
118 }
119 
121 {
122  mnCurId = 0;
123  mpDel = nullptr;
124 }
125 
127 {
128  ImplAccelMap::iterator it = mpData->maKeyMap.find( rKeyCode.GetFullCode() );
129  if( it != mpData->maKeyMap.end() )
130  return it->second;
131  else
132  return nullptr;
133 }
134 
136 {
137  // copy table
138  for (std::unique_ptr<ImplAccelEntry>& i : rAccelData.maIdList)
139  {
140  std::unique_ptr<ImplAccelEntry> pEntry(new ImplAccelEntry( *i ));
141 
142  // sequence accelerator, then copy also
143  if ( pEntry->mpAccel )
144  {
145  pEntry->mpAccel = new Accelerator( *(pEntry->mpAccel) );
146  pEntry->mpAutoAccel = pEntry->mpAccel;
147  }
148  else
149  pEntry->mpAutoAccel = nullptr;
150 
151  mpData->maKeyMap.insert( std::make_pair( pEntry->maKeyCode.GetFullCode(), pEntry.get() ) );
152  mpData->maIdList.push_back( std::move(pEntry) );
153  }
154 }
155 
157 {
158  // delete accelerator-entries using the id-table
159  for (const std::unique_ptr<ImplAccelEntry>& pEntry : mpData->maIdList) {
160  delete pEntry->mpAutoAccel;
161  }
162  mpData->maIdList.clear();
163 }
164 
165 void Accelerator::ImplInsertAccel( sal_uInt16 nItemId, const vcl::KeyCode& rKeyCode,
166  bool bEnable, Accelerator* pAutoAccel )
167 {
168  SAL_WARN_IF( !nItemId, "vcl", "Accelerator::InsertItem(): ItemId == 0" );
169 
170  if ( rKeyCode.IsFunction() )
171  {
172  sal_uInt16 nCode1;
173  sal_uInt16 nCode2;
174  sal_uInt16 nCode3;
175  sal_uInt16 nCode4;
176  ImplGetKeyCode( rKeyCode.GetFunction(), nCode1, nCode2, nCode3, nCode4 );
177  if ( nCode1 )
178  ImplInsertAccel( nItemId, vcl::KeyCode( nCode1, nCode1 ), bEnable, pAutoAccel );
179  if ( nCode2 )
180  {
181  if ( pAutoAccel )
182  pAutoAccel = new Accelerator( *pAutoAccel );
183  ImplInsertAccel( nItemId, vcl::KeyCode( nCode2, nCode2 ), bEnable, pAutoAccel );
184  if ( nCode3 )
185  {
186  if ( pAutoAccel )
187  pAutoAccel = new Accelerator( *pAutoAccel );
188  ImplInsertAccel( nItemId, vcl::KeyCode( nCode3, nCode3 ), bEnable, pAutoAccel );
189  }
190  }
191  return;
192  }
193 
194  // fetch and fill new entries
195  std::unique_ptr<ImplAccelEntry> pEntry(new ImplAccelEntry);
196  pEntry->mnId = nItemId;
197  pEntry->maKeyCode = rKeyCode;
198  pEntry->mpAccel = pAutoAccel;
199  pEntry->mpAutoAccel = pAutoAccel;
200  pEntry->mbEnabled = bEnable;
201 
202  // now into the tables
203  sal_uLong nCode = rKeyCode.GetFullCode();
204  if ( !nCode )
205  {
206  OSL_FAIL( "Accelerator::InsertItem(): KeyCode with KeyCode 0 not allowed" );
207  }
208  else if ( !mpData->maKeyMap.insert( std::make_pair( nCode, pEntry.get() ) ).second )
209  {
210  SAL_WARN( "vcl", "Accelerator::InsertItem(): KeyCode (Key: " << nCode << ") already exists" );
211  }
212  else
213  ImplAccelEntryInsert( &(mpData->maIdList), std::move(pEntry) );
214 }
215 
217 {
218  ImplInit();
219  mpData.reset(new ImplAccelData);
220 }
221 
223  : maCurKeyCode( rAccel.maCurKeyCode )
224 {
225  ImplInit();
226  mpData.reset(new ImplAccelData);
227  ImplCopyData(*rAccel.mpData);
228 }
229 
231 {
232 
233  // inform AccelManager about deleting the Accelerator
234  if ( mpDel )
235  *mpDel = true;
236 
237  ImplDeleteData();
238 }
239 
241 {
242  maActivateHdl.Call( *this );
243 }
244 
246 {
247  maSelectHdl.Call( *this );
248 }
249 
250 void Accelerator::InsertItem( sal_uInt16 nItemId, const vcl::KeyCode& rKeyCode )
251 {
252  ImplInsertAccel( nItemId, rKeyCode, true, nullptr );
253 }
254 
255 sal_uInt16 Accelerator::GetItemCount() const
256 {
257 
258  return static_cast<sal_uInt16>(mpData->maIdList.size());
259 }
260 
261 sal_uInt16 Accelerator::GetItemId( sal_uInt16 nPos ) const
262 {
263 
264  ImplAccelEntry* pEntry = ( nPos < mpData->maIdList.size() ) ? mpData->maIdList[ nPos ].get() : nullptr;
265  if ( pEntry )
266  return pEntry->mnId;
267  else
268  return 0;
269 }
270 
271 Accelerator* Accelerator::GetAccel( sal_uInt16 nItemId ) const
272 {
273 
274  sal_uInt16 nIndex = ImplAccelEntryGetIndex( &(mpData->maIdList), nItemId );
275  if ( nIndex != ACCELENTRY_NOTFOUND )
276  return mpData->maIdList[ nIndex ]->mpAccel;
277  else
278  return nullptr;
279 }
280 
282 {
283  if(this == &rAccel)
284  return *this;
285 
286  // assign new data
288  mnCurId = 0;
289 
290  // delete and copy tables
291  ImplDeleteData();
292  mpData->maKeyMap.clear();
293  ImplCopyData(*rAccel.mpData);
294 
295  return *this;
296 }
297 
298 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static sal_uInt16 ImplAccelEntryGetIndex(ImplAccelList *pList, sal_uInt16 nId, sal_uInt16 *pIndex=nullptr)
Definition: accel.cxx:40
sal_uInt16 mnId
Definition: accel.h:30
sal_uIntPtr sal_uLong
Accelerator()
Definition: accel.cxx:216
Link< Accelerator &, void > maSelectHdl
Definition: accel.hxx:39
SAL_DLLPRIVATE void ImplCopyData(ImplAccelData &rAccelData)
Definition: accel.cxx:135
static void ImplAccelEntryInsert(ImplAccelList *pList, std::unique_ptr< ImplAccelEntry > pEntry)
Definition: accel.cxx:87
SAL_DLLPRIVATE void ImplInit()
Definition: accel.cxx:120
sal_uInt16 mnCurId
Definition: accel.hxx:43
void Select()
Definition: accel.cxx:245
#define ACCELENTRY_NOTFOUND
Definition: accel.cxx:31
ImplAccelMap maKeyMap
Definition: accel.cxx:36
sal_uInt16 GetItemCount() const
Definition: accel.cxx:255
ImplAccelList maIdList
Definition: accel.cxx:37
int i
size
Accelerator * GetAccel(sal_uInt16 nItemId) const
Definition: accel.cxx:271
KeyFuncType GetFunction() const
Definition: keycod.cxx:85
bool ImplGetKeyCode(KeyFuncType eFunc, sal_uInt16 &rCode1, sal_uInt16 &rCode2, sal_uInt16 &rCode3, sal_uInt16 &rCode4)
Definition: keycod.cxx:52
vcl::KeyCode maCurKeyCode
Definition: accel.hxx:42
sal_uInt16 GetItemId(sal_uInt16 nPos) const
Definition: accel.cxx:261
Accelerator & operator=(const Accelerator &rAccel)
Definition: accel.cxx:281
::std::map< sal_uLong, ImplAccelEntry * > ImplAccelMap
Definition: accel.cxx:28
Link< Accelerator &, void > maActivateHdl
Definition: accel.hxx:38
SAL_DLLPRIVATE ImplAccelEntry * ImplGetAccelData(const vcl::KeyCode &rKeyCode) const
Definition: accel.cxx:126
#define SAL_WARN_IF(condition, area, stream)
sal_uInt16 const mnId
bool * mpDel
Definition: accel.hxx:44
std::unique_ptr< ImplAccelData > mpData
Definition: accel.hxx:37
SAL_DLLPRIVATE void ImplInsertAccel(sal_uInt16 nItemId, const vcl::KeyCode &rKeyCode, bool bEnable, Accelerator *pAutoAccel)
Definition: accel.cxx:165
~Accelerator()
Definition: accel.cxx:230
void Activate()
Definition: accel.cxx:240
::std::vector< std::unique_ptr< ImplAccelEntry > > ImplAccelList
Definition: accel.cxx:29
sal_uInt16 GetFullCode() const
Definition: keycod.hxx:50
#define SAL_WARN(area, stream)
bool IsFunction() const
Definition: keycod.hxx:71
SAL_DLLPRIVATE void ImplDeleteData()
Definition: accel.cxx:156
void InsertItem(sal_uInt16 nItemId, const vcl::KeyCode &rKeyCode)
Definition: accel.cxx:250