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 : #include "menuitemlist.hxx"
21 :
22 : #include <salframe.hxx>
23 : #include <salinst.hxx>
24 : #include <salmenu.hxx>
25 : #include <svdata.hxx>
26 : #include <vcl/i18nhelp.hxx>
27 : #include <vcl/settings.hxx>
28 : #include <vcl/window.hxx>
29 :
30 : using namespace css;
31 : using namespace vcl;
32 :
33 587196 : MenuItemData::~MenuItemData()
34 : {
35 293598 : if (aUserValueReleaseFunc)
36 14552 : aUserValueReleaseFunc(nUserValue);
37 293598 : if( pAutoSubMenu )
38 : {
39 4 : static_cast<PopupMenu*>(pAutoSubMenu)->pRefAutoSubMenu = NULL;
40 4 : delete pAutoSubMenu;
41 4 : pAutoSubMenu = NULL;
42 : }
43 293598 : if( pSalMenuItem )
44 136 : ImplGetSVData()->mpDefInst->DestroyMenuItem( pSalMenuItem );
45 293598 : }
46 :
47 155912 : MenuItemList::~MenuItemList()
48 : {
49 371493 : for( size_t i = 0, n = maItemList.size(); i < n; ++i )
50 293537 : delete maItemList[ i ];
51 77956 : }
52 :
53 246802 : MenuItemData* MenuItemList::Insert(
54 : sal_uInt16 nId,
55 : MenuItemType eType,
56 : MenuItemBits nBits,
57 : const OUString& rStr,
58 : const Image& rImage,
59 : Menu* pMenu,
60 : size_t nPos,
61 : const OString &rIdent
62 : )
63 : {
64 246802 : MenuItemData* pData = new MenuItemData( rStr, rImage );
65 246802 : pData->nId = nId;
66 246802 : pData->sIdent = rIdent;
67 246802 : pData->eType = eType;
68 246802 : pData->nBits = nBits;
69 246802 : pData->pSubMenu = NULL;
70 246802 : pData->pAutoSubMenu = NULL;
71 246802 : pData->nUserValue = 0;
72 246802 : pData->bChecked = false;
73 246802 : pData->bEnabled = true;
74 246802 : pData->bVisible = true;
75 246802 : pData->bIsTemporary = false;
76 246802 : pData->bMirrorMode = false;
77 246802 : pData->nItemImageAngle = 0;
78 :
79 246802 : SalItemParams aSalMIData;
80 246802 : aSalMIData.nId = nId;
81 246802 : aSalMIData.eType = eType;
82 246802 : aSalMIData.nBits = nBits;
83 246802 : aSalMIData.pMenu = pMenu;
84 246802 : aSalMIData.aText = rStr;
85 246802 : aSalMIData.aImage = rImage;
86 :
87 : // Native-support: returns NULL if not supported
88 246802 : pData->pSalMenuItem = ImplGetSVData()->mpDefInst->CreateMenuItem( &aSalMIData );
89 :
90 246802 : if( nPos < maItemList.size() ) {
91 1 : maItemList.insert( maItemList.begin() + nPos, pData );
92 : } else {
93 246801 : maItemList.push_back( pData );
94 : }
95 246802 : return pData;
96 : }
97 :
98 46810 : void MenuItemList::InsertSeparator(const OString &rIdent, size_t nPos)
99 : {
100 46810 : MenuItemData* pData = new MenuItemData;
101 46810 : pData->nId = 0;
102 46810 : pData->sIdent = rIdent;
103 46810 : pData->eType = MenuItemType::SEPARATOR;
104 46810 : pData->nBits = MenuItemBits::NONE;
105 46810 : pData->pSubMenu = NULL;
106 46810 : pData->pAutoSubMenu = NULL;
107 46810 : pData->nUserValue = 0;
108 46810 : pData->bChecked = false;
109 46810 : pData->bEnabled = true;
110 46810 : pData->bVisible = true;
111 46810 : pData->bIsTemporary = false;
112 46810 : pData->bMirrorMode = false;
113 46810 : pData->nItemImageAngle = 0;
114 :
115 46810 : SalItemParams aSalMIData;
116 46810 : aSalMIData.nId = 0;
117 46810 : aSalMIData.eType = MenuItemType::SEPARATOR;
118 46810 : aSalMIData.nBits = MenuItemBits::NONE;
119 46810 : aSalMIData.pMenu = NULL;
120 46810 : aSalMIData.aText.clear();
121 46810 : aSalMIData.aImage = Image();
122 :
123 : // Native-support: returns NULL if not supported
124 46810 : pData->pSalMenuItem = ImplGetSVData()->mpDefInst->CreateMenuItem( &aSalMIData );
125 :
126 46810 : if( nPos < maItemList.size() ) {
127 0 : maItemList.insert( maItemList.begin() + nPos, pData );
128 : } else {
129 46810 : maItemList.push_back( pData );
130 46810 : }
131 46810 : }
132 :
133 61 : void MenuItemList::Remove( size_t nPos )
134 : {
135 61 : if( nPos < maItemList.size() )
136 : {
137 61 : delete maItemList[ nPos ];
138 61 : maItemList.erase( maItemList.begin() + nPos );
139 : }
140 61 : }
141 :
142 1212319 : MenuItemData* MenuItemList::GetData( sal_uInt16 nSVId, size_t& rPos ) const
143 : {
144 10080956 : for( size_t i = 0, n = maItemList.size(); i < n; ++i )
145 : {
146 10061558 : if ( maItemList[ i ]->nId == nSVId )
147 : {
148 1192921 : rPos = i;
149 1192921 : return maItemList[ i ];
150 : }
151 : }
152 19398 : return NULL;
153 : }
154 :
155 0 : MenuItemData* MenuItemList::SearchItem(
156 : sal_Unicode cSelectChar,
157 : KeyCode aKeyCode,
158 : sal_uInt16& rPos,
159 : sal_uInt16& nDuplicates,
160 : sal_uInt16 nCurrentPos
161 : ) const
162 : {
163 0 : const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
164 :
165 0 : size_t nListCount = maItemList.size();
166 :
167 : // try character code first
168 0 : nDuplicates = GetItemCount( cSelectChar ); // return number of duplicates
169 0 : if( nDuplicates )
170 : {
171 0 : for ( rPos = 0; rPos < nListCount; rPos++)
172 : {
173 0 : MenuItemData* pData = maItemList[ rPos ];
174 0 : if ( pData->bEnabled && rI18nHelper.MatchMnemonic( pData->aText, cSelectChar ) )
175 : {
176 0 : if( nDuplicates > 1 && rPos == nCurrentPos )
177 0 : continue; // select next entry with the same mnemonic
178 : else
179 0 : return pData;
180 : }
181 : }
182 : }
183 :
184 : // nothing found, try keycode instead
185 0 : nDuplicates = GetItemCount( aKeyCode ); // return number of duplicates
186 :
187 0 : if( nDuplicates )
188 : {
189 0 : char ascii = 0;
190 0 : if( aKeyCode.GetCode() >= KEY_A && aKeyCode.GetCode() <= KEY_Z )
191 0 : ascii = sal::static_int_cast<char>('A' + (aKeyCode.GetCode() - KEY_A));
192 :
193 0 : for ( rPos = 0; rPos < nListCount; rPos++)
194 : {
195 0 : MenuItemData* pData = maItemList[ rPos ];
196 0 : if ( pData->bEnabled )
197 : {
198 0 : sal_Int32 n = pData->aText.indexOf('~');
199 0 : if ( n != -1 )
200 : {
201 0 : KeyCode mnKeyCode;
202 0 : sal_Unicode mnUnicode = pData->aText[n+1];
203 0 : vcl::Window* pDefWindow = ImplGetDefaultWindow();
204 0 : if( ( pDefWindow
205 0 : && pDefWindow->ImplGetFrame()->MapUnicodeToKeyCode( mnUnicode,
206 0 : Application::GetSettings().GetUILanguageTag().getLanguageType(), mnKeyCode )
207 0 : && aKeyCode.GetCode() == mnKeyCode.GetCode()
208 : )
209 0 : || ( ascii
210 0 : && rI18nHelper.MatchMnemonic( pData->aText, ascii )
211 : )
212 : )
213 : {
214 0 : if( nDuplicates > 1 && rPos == nCurrentPos )
215 0 : continue; // select next entry with the same mnemonic
216 : else
217 0 : return pData;
218 : }
219 : }
220 : }
221 : }
222 : }
223 :
224 0 : return NULL;
225 : }
226 :
227 0 : size_t MenuItemList::GetItemCount( sal_Unicode cSelectChar ) const
228 : {
229 : // returns number of entries with same mnemonic
230 0 : const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
231 :
232 0 : size_t nItems = 0;
233 0 : for ( size_t nPos = maItemList.size(); nPos; )
234 : {
235 0 : MenuItemData* pData = maItemList[ --nPos ];
236 0 : if ( pData->bEnabled && rI18nHelper.MatchMnemonic( pData->aText, cSelectChar ) )
237 0 : nItems++;
238 : }
239 :
240 0 : return nItems;
241 : }
242 :
243 0 : size_t MenuItemList::GetItemCount( KeyCode aKeyCode ) const
244 : {
245 : // returns number of entries with same mnemonic
246 : // uses key codes instead of character codes
247 0 : const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
248 0 : char ascii = 0;
249 0 : if( aKeyCode.GetCode() >= KEY_A && aKeyCode.GetCode() <= KEY_Z )
250 0 : ascii = sal::static_int_cast<char>('A' + (aKeyCode.GetCode() - KEY_A));
251 :
252 0 : size_t nItems = 0;
253 0 : for ( size_t nPos = maItemList.size(); nPos; )
254 : {
255 0 : MenuItemData* pData = maItemList[ --nPos ];
256 0 : if ( pData->bEnabled )
257 : {
258 0 : sal_Int32 n = pData->aText.indexOf('~');
259 0 : if (n != -1)
260 : {
261 0 : KeyCode mnKeyCode;
262 : // if MapUnicodeToKeyCode fails or is unsupported we try the pure ascii mapping of the keycodes
263 : // so we have working shortcuts when ascii mnemonics are used
264 0 : vcl::Window* pDefWindow = ImplGetDefaultWindow();
265 0 : if( ( pDefWindow
266 0 : && pDefWindow->ImplGetFrame()->MapUnicodeToKeyCode( pData->aText[n+1],
267 0 : Application::GetSettings().GetUILanguageTag().getLanguageType(), mnKeyCode )
268 0 : && aKeyCode.GetCode() == mnKeyCode.GetCode()
269 : )
270 0 : || ( ascii
271 0 : && rI18nHelper.MatchMnemonic( pData->aText, ascii )
272 : )
273 : )
274 0 : nItems++;
275 : }
276 : }
277 : }
278 :
279 0 : return nItems;
280 : }
281 :
282 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|