1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <tools/debug.hxx>
23 #include <vcl/window.hxx>
24 #include <vcl/svapp.hxx>
26 #include <vcl/accel.hxx>
30 typedef ::std::map
< sal_uLong
, ImplAccelEntry
* > ImplAccelMap
;
31 typedef ::std::vector
< ImplAccelEntry
* > ImplAccelList
;
33 #define ACCELENTRY_NOTFOUND ((sal_uInt16)0xFFFF)
38 ImplAccelMap maKeyMap
; // for keycodes, generated with a code
39 ImplAccelList maIdList
; // Id-List
42 sal_uInt16
ImplAccelEntryGetIndex( ImplAccelList
* pList
, sal_uInt16 nId
,
43 sal_uInt16
* pIndex
= nullptr )
48 size_t nCount
= pList
->size();
49 sal_uInt16 nCompareId
;
51 // check if first key is larger then the key to compare
52 if ( !nCount
|| (nId
< (*pList
)[ 0 ]->mnId
) )
56 return ACCELENTRY_NOTFOUND
;
64 nMid
= (nLow
+ nHigh
) / 2;
65 nCompareId
= (*pList
)[ nMid
]->mnId
;
66 if ( nId
< nCompareId
)
70 if ( nId
> nCompareId
)
73 return (sal_uInt16
)nMid
;
76 while ( nLow
<= nHigh
);
80 if ( nId
> nCompareId
)
81 *pIndex
= (sal_uInt16
)(nMid
+1);
83 *pIndex
= (sal_uInt16
)nMid
;
86 return ACCELENTRY_NOTFOUND
;
89 static void ImplAccelEntryInsert( ImplAccelList
* pList
, ImplAccelEntry
* pEntry
)
91 sal_uInt16
nInsIndex(0);
92 sal_uInt16 nIndex
= ImplAccelEntryGetIndex( pList
, pEntry
->mnId
, &nInsIndex
);
94 if ( nIndex
!= ACCELENTRY_NOTFOUND
)
99 ImplAccelEntry
* pTempEntry
= nullptr;
100 if ( nIndex
< pList
->size() )
101 pTempEntry
= (*pList
)[ nIndex
];
102 if ( !pTempEntry
|| (pTempEntry
->mnId
!= pEntry
->mnId
) )
105 while ( nIndex
< pList
->size() );
107 if ( nIndex
< pList
->size() ) {
108 ImplAccelList::iterator it
= pList
->begin();
109 ::std::advance( it
, nIndex
);
110 pList
->insert( it
, pEntry
);
112 pList
->push_back( pEntry
);
116 if ( nInsIndex
< pList
->size() ) {
117 ImplAccelList::iterator it
= pList
->begin();
118 ::std::advance( it
, nInsIndex
);
119 pList
->insert( it
, pEntry
);
121 pList
->push_back( pEntry
);
126 void Accelerator::ImplInit()
133 ImplAccelEntry
* Accelerator::ImplGetAccelData( const vcl::KeyCode
& rKeyCode
) const
135 ImplAccelMap::iterator it
= mpData
->maKeyMap
.find( rKeyCode
.GetFullCode() );
136 if( it
!= mpData
->maKeyMap
.end() )
142 void Accelerator::ImplCopyData( ImplAccelData
& rAccelData
)
145 for (ImplAccelEntry
* i
: rAccelData
.maIdList
)
147 ImplAccelEntry
* pEntry
= new ImplAccelEntry( *i
);
149 // sequence accelerator, then copy also
150 if ( pEntry
->mpAccel
)
152 pEntry
->mpAccel
= new Accelerator( *(pEntry
->mpAccel
) );
153 pEntry
->mpAutoAccel
= pEntry
->mpAccel
;
156 pEntry
->mpAutoAccel
= nullptr;
158 mpData
->maKeyMap
.insert( std::make_pair( pEntry
->maKeyCode
.GetFullCode(), pEntry
) );
159 mpData
->maIdList
.push_back( pEntry
);
163 void Accelerator::ImplDeleteData()
165 // delete accelerator-entries using the id-table
166 for (ImplAccelEntry
* pEntry
: mpData
->maIdList
) {
167 if ( pEntry
->mpAutoAccel
) {
168 delete pEntry
->mpAutoAccel
;
172 mpData
->maIdList
.clear();
175 void Accelerator::ImplInsertAccel( sal_uInt16 nItemId
, const vcl::KeyCode
& rKeyCode
,
176 bool bEnable
, Accelerator
* pAutoAccel
)
178 SAL_WARN_IF( !nItemId
, "vcl", "Accelerator::InsertItem(): ItemId == 0" );
180 if ( rKeyCode
.IsFunction() )
186 ImplGetKeyCode( rKeyCode
.GetFunction(), nCode1
, nCode2
, nCode3
, nCode4
);
188 ImplInsertAccel( nItemId
, vcl::KeyCode( nCode1
, nCode1
), bEnable
, pAutoAccel
);
192 pAutoAccel
= new Accelerator( *pAutoAccel
);
193 ImplInsertAccel( nItemId
, vcl::KeyCode( nCode2
, nCode2
), bEnable
, pAutoAccel
);
197 pAutoAccel
= new Accelerator( *pAutoAccel
);
198 ImplInsertAccel( nItemId
, vcl::KeyCode( nCode3
, nCode3
), bEnable
, pAutoAccel
);
204 // fetch and fill new entries
205 ImplAccelEntry
* pEntry
= new ImplAccelEntry
;
206 pEntry
->mnId
= nItemId
;
207 pEntry
->maKeyCode
= rKeyCode
;
208 pEntry
->mpAccel
= pAutoAccel
;
209 pEntry
->mpAutoAccel
= pAutoAccel
;
210 pEntry
->mbEnabled
= bEnable
;
212 // now into the tables
213 sal_uLong nCode
= rKeyCode
.GetFullCode();
216 OSL_FAIL( "Accelerator::InsertItem(): KeyCode with KeyCode 0 not allowed" );
219 else if ( !mpData
->maKeyMap
.insert( std::make_pair( nCode
, pEntry
) ).second
)
221 SAL_WARN( "vcl.layout", "Accelerator::InsertItem(): KeyCode (Key: " << nCode
<< ") already exists" );
225 ImplAccelEntryInsert( &(mpData
->maIdList
), pEntry
);
228 Accelerator::Accelerator()
232 mpData
= new ImplAccelData
;
235 Accelerator::Accelerator( const Accelerator
& rAccel
) :
237 maCurKeyCode( rAccel
.maCurKeyCode
)
241 mpData
= new ImplAccelData
;
242 ImplCopyData(*rAccel
.mpData
);
245 Accelerator::~Accelerator()
248 // inform AccelManager about deleting the Accelerator
256 void Accelerator::Activate()
258 maActivateHdl
.Call( *this );
261 void Accelerator::Select()
263 maSelectHdl
.Call( *this );
266 void Accelerator::InsertItem( sal_uInt16 nItemId
, const vcl::KeyCode
& rKeyCode
)
268 ImplInsertAccel( nItemId
, rKeyCode
, true, nullptr );
271 sal_uInt16
Accelerator::GetItemCount() const
274 return (sal_uInt16
)mpData
->maIdList
.size();
277 sal_uInt16
Accelerator::GetItemId( sal_uInt16 nPos
) const
280 ImplAccelEntry
* pEntry
= ( nPos
< mpData
->maIdList
.size() ) ? mpData
->maIdList
[ nPos
] : nullptr;
287 Accelerator
* Accelerator::GetAccel( sal_uInt16 nItemId
) const
290 sal_uInt16 nIndex
= ImplAccelEntryGetIndex( &(mpData
->maIdList
), nItemId
);
291 if ( nIndex
!= ACCELENTRY_NOTFOUND
)
292 return mpData
->maIdList
[ nIndex
]->mpAccel
;
297 Accelerator
& Accelerator::operator=( const Accelerator
& rAccel
)
301 maCurKeyCode
= vcl::KeyCode();
305 // delete and copy tables
307 mpData
->maKeyMap
.clear();
308 ImplCopyData(*rAccel
.mpData
);
313 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */