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