xref: /AOO41X/main/vcl/source/window/accmgr.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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_vcl.hxx"
30 #include <tools/list.hxx>
31 #include <tools/debug.hxx>
32 
33 #include <accel.h>
34 #include <vcl/accel.hxx>
35 #include <accmgr.hxx>
36 
37 
38 
39 // =======================================================================
40 
41 DECLARE_LIST( ImplAccelList, Accelerator* )
42 
43 // =======================================================================
44 
45 DBG_NAMEEX( Accelerator )
46 
47 // =======================================================================
48 
49 ImplAccelManager::~ImplAccelManager()
50 {
51     if ( mpAccelList )
52         delete mpAccelList;
53     if ( mpSequenceList )
54         delete mpSequenceList;
55 }
56 
57 // -----------------------------------------------------------------------
58 
59 sal_Bool ImplAccelManager::InsertAccel( Accelerator* pAccel )
60 {
61     if ( !mpAccelList )
62         mpAccelList = new ImplAccelList;
63     else
64     {
65         // Gibts den schon ?
66         if ( mpAccelList->GetPos( pAccel ) != LIST_ENTRY_NOTFOUND )
67             return sal_False;
68     }
69 
70     // Am Anfang der Liste einfuegen
71     mpAccelList->Insert( pAccel, (sal_uLong)0 );
72 
73     return sal_True;
74 }
75 
76 // -----------------------------------------------------------------------
77 
78 void ImplAccelManager::RemoveAccel( Accelerator* pAccel )
79 {
80     // Haben wir ueberhaupt eine Liste ?
81     if ( !mpAccelList )
82         return;
83 
84     //e.g. #i90599#. Someone starts typing a sequence in a dialog, but doesn't
85     //end it, and then closes the dialog, deleting the accelerators. So if
86     //we're removing an accelerator that a sub-accelerator which is in the
87     //sequence list, throw away the entire sequence
88     if ( mpSequenceList )
89     {
90         for (sal_uInt16 i = 0; i < pAccel->GetItemCount(); ++i)
91         {
92             Accelerator* pSubAccel = pAccel->GetAccel(pAccel->GetItemId(i));
93             if ( mpSequenceList->GetPos( pSubAccel ) != LIST_ENTRY_NOTFOUND )
94             {
95                 EndSequence( true );
96                 break;
97             }
98         }
99     }
100 
101     // Raus damit
102     mpAccelList->Remove( pAccel );
103 }
104 
105 // -----------------------------------------------------------------------
106 
107 void ImplAccelManager::EndSequence( sal_Bool bCancel )
108 {
109     // Sind wir ueberhaupt in einer Sequenz ?
110     if ( !mpSequenceList )
111         return;
112 
113     // Alle Deactivate-Handler der Acceleratoren in der Sequenz rufen
114     Accelerator* pTempAccel = mpSequenceList->First();
115     while( pTempAccel )
116     {
117         sal_Bool bDel = sal_False;
118         pTempAccel->mbIsCancel = bCancel;
119         pTempAccel->mpDel = &bDel;
120         pTempAccel->Deactivate();
121         if ( !bDel )
122         {
123             pTempAccel->mbIsCancel = sal_False;
124             pTempAccel->mpDel = NULL;
125         }
126 
127         pTempAccel = mpSequenceList->Next();
128     }
129 
130     // Sequenz-Liste loeschen
131     delete mpSequenceList;
132     mpSequenceList = NULL;
133 }
134 
135 // -----------------------------------------------------------------------
136 
137 sal_Bool ImplAccelManager::IsAccelKey( const KeyCode& rKeyCode, sal_uInt16 nRepeat )
138 {
139     Accelerator* pAccel;
140 
141     // Haben wir ueberhaupt Acceleratoren ??
142     if ( !mpAccelList )
143         return sal_False;
144     if ( !mpAccelList->Count() )
145         return sal_False;
146 
147     // Sind wir in einer Sequenz ?
148     if ( mpSequenceList )
149     {
150         pAccel = mpSequenceList->GetObject( 0 );
151         DBG_CHKOBJ( pAccel, Accelerator, NULL );
152 
153         // Nicht Gefunden ?
154         if ( !pAccel )
155         {
156             // Sequenz abbrechen
157             FlushAccel();
158             return sal_False;
159         }
160 
161         // Ist der Eintrag da drin ?
162         ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode );
163         if ( pEntry )
164         {
165             Accelerator* pNextAccel = pEntry->mpAccel;
166 
167             // Ist da ein Accelerator hinter ?
168             if ( pNextAccel )
169             {
170                 DBG_CHKOBJ( pNextAccel, Accelerator, NULL );
171 
172                 mpSequenceList->Insert( pNextAccel, (sal_uLong)0 );
173 
174                 // Activate-Handler vom Neuen rufen
175                 pNextAccel->Activate();
176                 return sal_True;
177             }
178             else
179             {
180                 // Hat ihn schon !
181                 if ( pEntry->mbEnabled )
182                 {
183                     // Sequence beenden (Deactivate-Handler vorher rufen)
184                     EndSequence();
185 
186                     // Dem Accelerator das aktuelle Item setzen
187                     // und Handler rufen
188                     sal_Bool bDel = sal_False;
189                     pAccel->maCurKeyCode    = rKeyCode;
190                     pAccel->mnCurId         = pEntry->mnId;
191                     pAccel->mnCurRepeat     = nRepeat;
192                     pAccel->mpDel           = &bDel;
193                     pAccel->Select();
194 
195                     // Hat Accel den Aufruf ueberlebt
196                     if ( !bDel )
197                     {
198                         DBG_CHKOBJ( pAccel, Accelerator, NULL );
199                         pAccel->maCurKeyCode    = KeyCode();
200                         pAccel->mnCurId         = 0;
201                         pAccel->mnCurRepeat     = 0;
202                         pAccel->mpDel           = NULL;
203                     }
204 
205                     return sal_True;
206                 }
207                 else
208                 {
209                     // Sequenz abbrechen, weil Acceleraor disabled
210                     // Taste wird weitergeleitet (ans System)
211                     FlushAccel();
212                     return sal_False;
213                 }
214             }
215         }
216         else
217         {
218             // Sequenz abbrechen wegen falscher Taste
219             FlushAccel();
220             return sal_False;
221         }
222     }
223 
224     // Durch die Liste der Acceleratoren wuehlen
225     pAccel = mpAccelList->First();
226     while ( pAccel )
227     {
228         DBG_CHKOBJ( pAccel, Accelerator, NULL );
229 
230         // Ist der Eintrag da drin ?
231         ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode );
232         if ( pEntry )
233         {
234             Accelerator* pNextAccel = pEntry->mpAccel;
235 
236             // Ist da ein Accelerator hinter ?
237             if ( pNextAccel )
238             {
239                 DBG_CHKOBJ( pNextAccel, Accelerator, NULL );
240 
241                 // Sequenz-Liste erzeugen
242                 mpSequenceList = new ImplAccelList;
243                 mpSequenceList->Insert( pAccel, (sal_uLong)0 );
244                 mpSequenceList->Insert( pNextAccel, (sal_uLong)0 );
245 
246                 // Activate-Handler vom Neuen rufen
247                 pNextAccel->Activate();
248 
249                 return sal_True;
250             }
251             else
252             {
253                 // Hat ihn schon !
254                 if ( pEntry->mbEnabled )
255                 {
256                     // Activate/Deactivate-Handler vorher rufen
257                     pAccel->Activate();
258                     pAccel->Deactivate();
259 
260                     // Dem Accelerator das aktuelle Item setzen
261                     // und Handler rufen
262                     sal_Bool bDel = sal_False;
263                     pAccel->maCurKeyCode    = rKeyCode;
264                     pAccel->mnCurId         = pEntry->mnId;
265                     pAccel->mnCurRepeat     = nRepeat;
266                     pAccel->mpDel           = &bDel;
267                     pAccel->Select();
268 
269                     // Hat Accel den Aufruf ueberlebt
270                     if ( !bDel )
271                     {
272                         DBG_CHKOBJ( pAccel, Accelerator, NULL );
273                         pAccel->maCurKeyCode    = KeyCode();
274                         pAccel->mnCurId         = 0;
275                         pAccel->mnCurRepeat     = 0;
276                         pAccel->mpDel           = NULL;
277                     }
278 
279                     return sal_True;
280                 }
281                 else
282                     return sal_False;
283             }
284         }
285 
286         // Nicht gefunden, vielleicht im naechsten Accelerator
287         pAccel = mpAccelList->Next();
288     }
289 
290     return sal_False;
291 }
292