Line data Source code
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 :
21 : #include <tools/debug.hxx>
22 :
23 : #include <accel.h>
24 : #include <vcl/accel.hxx>
25 : #include <accmgr.hxx>
26 :
27 : // =======================================================================
28 :
29 : DBG_NAMEEX( Accelerator )
30 :
31 : // =======================================================================
32 :
33 0 : ImplAccelManager::~ImplAccelManager()
34 : {
35 0 : delete mpAccelList;
36 0 : delete mpSequenceList;
37 0 : }
38 :
39 : // -----------------------------------------------------------------------
40 :
41 0 : sal_Bool ImplAccelManager::InsertAccel( Accelerator* pAccel )
42 : {
43 0 : if ( !mpAccelList ) {
44 0 : mpAccelList = new ImplAccelList;
45 : } else {
46 0 : for ( size_t i = 0, n = mpAccelList->size(); i < n; ++i ) {
47 0 : if ( (*mpAccelList)[ i ] == pAccel ) {
48 0 : return sal_False;
49 : }
50 : }
51 : }
52 :
53 0 : mpAccelList->insert( mpAccelList->begin(), pAccel );
54 0 : return sal_True;
55 : }
56 :
57 : // -----------------------------------------------------------------------
58 :
59 0 : void ImplAccelManager::RemoveAccel( Accelerator* pAccel )
60 : {
61 : // do we have a list ?
62 0 : if ( !mpAccelList )
63 0 : return;
64 :
65 : //e.g. #i90599#. Someone starts typing a sequence in a dialog, but doesn't
66 : //end it, and then closes the dialog, deleting the accelerators. So if
67 : //we're removing an accelerator that a sub-accelerator which is in the
68 : //sequence list, throw away the entire sequence
69 0 : if ( mpSequenceList ) {
70 0 : for (sal_uInt16 i = 0; i < pAccel->GetItemCount(); ++i) {
71 0 : Accelerator* pSubAccel = pAccel->GetAccel( pAccel->GetItemId(i) );
72 0 : for ( size_t j = 0, n = mpSequenceList->size(); j < n; ++j ) {
73 0 : if ( (*mpSequenceList)[ j ] == pSubAccel ) {
74 0 : EndSequence( true );
75 0 : i = pAccel->GetItemCount();
76 0 : break;
77 : }
78 : }
79 : }
80 : }
81 :
82 : // throw it away
83 0 : for ( ImplAccelList::iterator it = mpAccelList->begin();
84 0 : it != mpAccelList->end();
85 : ++it
86 : ) {
87 0 : if ( *it == pAccel ) {
88 0 : mpAccelList->erase( it );
89 0 : break;
90 : }
91 : }
92 : }
93 :
94 : // -----------------------------------------------------------------------
95 :
96 0 : void ImplAccelManager::EndSequence( sal_Bool bCancel )
97 : {
98 : // are we in a list ?
99 0 : if ( !mpSequenceList )
100 0 : return;
101 :
102 : // call all deactivate-handler of the accelerators in the list
103 0 : for ( size_t i = 0, n = mpSequenceList->size(); i < n; ++i )
104 : {
105 0 : Accelerator* pTempAccel = (*mpSequenceList)[ i ];
106 0 : sal_Bool bDel = sal_False;
107 0 : pTempAccel->mbIsCancel = bCancel;
108 0 : pTempAccel->mpDel = &bDel;
109 0 : pTempAccel->Deactivate();
110 0 : if ( !bDel )
111 : {
112 0 : pTempAccel->mbIsCancel = sal_False;
113 0 : pTempAccel->mpDel = NULL;
114 : }
115 : }
116 :
117 : // delete sequence-list
118 0 : delete mpSequenceList;
119 0 : mpSequenceList = NULL;
120 : }
121 :
122 : // -----------------------------------------------------------------------
123 :
124 0 : sal_Bool ImplAccelManager::IsAccelKey( const KeyCode& rKeyCode, sal_uInt16 nRepeat )
125 : {
126 : Accelerator* pAccel;
127 :
128 : // do we have accelerators ??
129 0 : if ( !mpAccelList )
130 0 : return sal_False;
131 0 : if ( mpAccelList->empty() )
132 0 : return sal_False;
133 :
134 : // are we in a sequence ?
135 0 : if ( mpSequenceList )
136 : {
137 0 : pAccel = mpSequenceList->empty() ? NULL : (*mpSequenceList)[ 0 ];
138 : DBG_CHKOBJ( pAccel, Accelerator, NULL );
139 :
140 : // not found ?
141 0 : if ( !pAccel )
142 : {
143 : // abort sequence
144 0 : FlushAccel();
145 0 : return sal_False;
146 : }
147 :
148 : // can the entry be found ?
149 0 : ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode );
150 0 : if ( pEntry )
151 : {
152 0 : Accelerator* pNextAccel = pEntry->mpAccel;
153 :
154 : // is an accelerator coupled ?
155 0 : if ( pNextAccel )
156 : {
157 : DBG_CHKOBJ( pNextAccel, Accelerator, NULL );
158 :
159 0 : mpSequenceList->insert( mpSequenceList->begin(), pNextAccel );
160 :
161 : // call Activate-Handler of the new one
162 0 : pNextAccel->Activate();
163 0 : return sal_True;
164 : }
165 : else
166 : {
167 : // it is there already !
168 0 : if ( pEntry->mbEnabled )
169 : {
170 : // stop sequence (first call deactivate-handler)
171 0 : EndSequence();
172 :
173 : // set accelerator of the actuel item
174 : // and call the handler
175 0 : sal_Bool bDel = sal_False;
176 0 : pAccel->maCurKeyCode = rKeyCode;
177 0 : pAccel->mnCurId = pEntry->mnId;
178 0 : pAccel->mnCurRepeat = nRepeat;
179 0 : pAccel->mpDel = &bDel;
180 0 : pAccel->Select();
181 :
182 : // did the accelerator survive the call
183 0 : if ( !bDel )
184 : {
185 : DBG_CHKOBJ( pAccel, Accelerator, NULL );
186 0 : pAccel->maCurKeyCode = KeyCode();
187 0 : pAccel->mnCurId = 0;
188 0 : pAccel->mnCurRepeat = 0;
189 0 : pAccel->mpDel = NULL;
190 : }
191 :
192 0 : return sal_True;
193 : }
194 : else
195 : {
196 : // stop sequence as the accelerator was disbled
197 : // transfer the key (to the system)
198 0 : FlushAccel();
199 0 : return sal_False;
200 : }
201 : }
202 : }
203 : else
204 : {
205 : // wrong key => stop sequence
206 0 : FlushAccel();
207 0 : return sal_False;
208 : }
209 : }
210 :
211 : // step through the list of accelerators
212 0 : for ( size_t i = 0, n = mpAccelList->size(); i < n; ++i )
213 : {
214 0 : pAccel = (*mpAccelList)[ i ];
215 : DBG_CHKOBJ( pAccel, Accelerator, NULL );
216 :
217 : // is the entry contained ?
218 0 : ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode );
219 0 : if ( pEntry )
220 : {
221 0 : Accelerator* pNextAccel = pEntry->mpAccel;
222 :
223 : // is an accelerator assigned ?
224 0 : if ( pNextAccel )
225 : {
226 : DBG_CHKOBJ( pNextAccel, Accelerator, NULL );
227 :
228 : // create sequence list
229 0 : mpSequenceList = new ImplAccelList;
230 0 : mpSequenceList->insert( mpSequenceList->begin(), pAccel );
231 0 : mpSequenceList->insert( mpSequenceList->begin(), pNextAccel );
232 :
233 : // call activate-Handler of the new one
234 0 : pNextAccel->Activate();
235 :
236 0 : return sal_True;
237 : }
238 : else
239 : {
240 : // already assigned !
241 0 : if ( pEntry->mbEnabled )
242 : {
243 : // first call activate/aeactivate-Handler
244 0 : pAccel->Activate();
245 0 : pAccel->Deactivate();
246 :
247 : // define accelerator of the actual item
248 : // and call the handler
249 0 : sal_Bool bDel = sal_False;
250 0 : pAccel->maCurKeyCode = rKeyCode;
251 0 : pAccel->mnCurId = pEntry->mnId;
252 0 : pAccel->mnCurRepeat = nRepeat;
253 0 : pAccel->mpDel = &bDel;
254 0 : pAccel->Select();
255 :
256 : // if the accelerator did survive the call
257 0 : if ( !bDel )
258 : {
259 : DBG_CHKOBJ( pAccel, Accelerator, NULL );
260 0 : pAccel->maCurKeyCode = KeyCode();
261 0 : pAccel->mnCurId = 0;
262 0 : pAccel->mnCurRepeat = 0;
263 0 : pAccel->mpDel = NULL;
264 : }
265 :
266 0 : return sal_True;
267 : }
268 : else
269 0 : return sal_False;
270 : }
271 : }
272 : }
273 :
274 0 : return sal_False;
275 : }
276 :
277 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|