LibreOffice Module vcl (master)  1
menuitemlist.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 "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/vcllayout.hxx>
29 #include <vcl/window.hxx>
30 
31 using namespace css;
32 using namespace vcl;
33 
35 {
36  if (aUserValueReleaseFunc)
37  aUserValueReleaseFunc(nUserValue);
38  pSalMenuItem.reset();
39  pSubMenu.disposeAndClear();
40 }
41 
43 {
44  if (aTextGlyphs.IsValid())
45  // Use pre-calculated result.
46  return &aTextGlyphs;
47 
48  OUString aNonMnemonicString = OutputDevice::GetNonMnemonicString(aText);
49  std::unique_ptr<SalLayout> pLayout
50  = pOutputDevice->ImplLayout(aNonMnemonicString, 0, aNonMnemonicString.getLength(),
51  Point(0, 0), 0, nullptr, SalLayoutFlags::GlyphItemsOnly);
52  if (!pLayout)
53  return nullptr;
54 
55  const SalLayoutGlyphs* pGlyphs = pLayout->GetGlyphs();
56  if (!pGlyphs)
57  return nullptr;
58 
59  // Remember the calculation result.
60  aTextGlyphs = *pGlyphs;
61 
62  return &aTextGlyphs;
63 }
64 
66 {
67 }
68 
70  sal_uInt16 nId,
71  MenuItemType eType,
72  MenuItemBits nBits,
73  const OUString& rStr,
74  Menu* pMenu,
75  size_t nPos,
76  const OString &rIdent
77 )
78 {
79  MenuItemData* pData = new MenuItemData( rStr );
80  pData->nId = nId;
81  pData->sIdent = rIdent;
82  pData->eType = eType;
83  pData->nBits = nBits;
84  pData->pSubMenu = nullptr;
85  pData->nUserValue = nullptr;
86  pData->bChecked = false;
87  pData->bEnabled = true;
88  pData->bVisible = true;
89  pData->bIsTemporary = false;
90 
91  SalItemParams aSalMIData;
92  aSalMIData.nId = nId;
93  aSalMIData.eType = eType;
94  aSalMIData.nBits = nBits;
95  aSalMIData.pMenu = pMenu;
96  aSalMIData.aText = rStr;
97 
98  // Native-support: returns NULL if not supported
99  pData->pSalMenuItem = ImplGetSVData()->mpDefInst->CreateMenuItem( aSalMIData );
100 
101  if( nPos < maItemList.size() ) {
102  maItemList.insert( maItemList.begin() + nPos, std::unique_ptr<MenuItemData>(pData) );
103  } else {
104  maItemList.emplace_back( pData );
105  }
106  return pData;
107 }
108 
109 void MenuItemList::InsertSeparator(const OString &rIdent, size_t nPos)
110 {
111  MenuItemData* pData = new MenuItemData;
112  pData->nId = 0;
113  pData->sIdent = rIdent;
115  pData->nBits = MenuItemBits::NONE;
116  pData->pSubMenu = nullptr;
117  pData->nUserValue = nullptr;
118  pData->bChecked = false;
119  pData->bEnabled = true;
120  pData->bVisible = true;
121  pData->bIsTemporary = false;
122 
123  SalItemParams aSalMIData;
124  aSalMIData.nId = 0;
125  aSalMIData.eType = MenuItemType::SEPARATOR;
126  aSalMIData.nBits = MenuItemBits::NONE;
127  aSalMIData.pMenu = nullptr;
128  aSalMIData.aText.clear();
129  aSalMIData.aImage = Image();
130 
131  // Native-support: returns NULL if not supported
132  pData->pSalMenuItem = ImplGetSVData()->mpDefInst->CreateMenuItem( aSalMIData );
133 
134  if( nPos < maItemList.size() ) {
135  maItemList.insert( maItemList.begin() + nPos, std::unique_ptr<MenuItemData>(pData) );
136  } else {
137  maItemList.emplace_back( pData );
138  }
139 }
140 
141 void MenuItemList::Remove( size_t nPos )
142 {
143  if( nPos < maItemList.size() )
144  {
145  maItemList.erase( maItemList.begin() + nPos );
146  }
147 }
148 
150 {
151  maItemList.clear();
152 }
153 
154 MenuItemData* MenuItemList::GetData( sal_uInt16 nSVId, size_t& rPos ) const
155 {
156  for( size_t i = 0, n = maItemList.size(); i < n; ++i )
157  {
158  if ( maItemList[ i ]->nId == nSVId )
159  {
160  rPos = i;
161  return maItemList[ i ].get();
162  }
163  }
164  return nullptr;
165 }
166 
168  sal_Unicode cSelectChar,
169  KeyCode aKeyCode,
170  size_t& rPos,
171  size_t& nDuplicates,
172  size_t nCurrentPos
173 ) const
174 {
176 
177  size_t nListCount = maItemList.size();
178 
179  // try character code first
180  nDuplicates = GetItemCount( cSelectChar ); // return number of duplicates
181  if( nDuplicates )
182  {
183  for ( rPos = 0; rPos < nListCount; rPos++)
184  {
185  MenuItemData* pData = maItemList[ rPos ].get();
186  if ( pData->bEnabled && rI18nHelper.MatchMnemonic( pData->aText, cSelectChar ) )
187  {
188  if( nDuplicates > 1 && rPos == nCurrentPos )
189  continue; // select next entry with the same mnemonic
190  else
191  return pData;
192  }
193  }
194  }
195 
196  // nothing found, try keycode instead
197  nDuplicates = GetItemCount( aKeyCode ); // return number of duplicates
198 
199  if( nDuplicates )
200  {
201  char ascii = 0;
202  if( aKeyCode.GetCode() >= KEY_A && aKeyCode.GetCode() <= KEY_Z )
203  ascii = sal::static_int_cast<char>('A' + (aKeyCode.GetCode() - KEY_A));
204 
205  for ( rPos = 0; rPos < nListCount; rPos++)
206  {
207  MenuItemData* pData = maItemList[ rPos ].get();
208  if ( pData->bEnabled )
209  {
210  sal_Int32 n = pData->aText.indexOf('~');
211  if ( n != -1 )
212  {
213  KeyCode nKeyCode;
214  sal_Unicode nUnicode = pData->aText[n+1];
215  vcl::Window* pDefWindow = ImplGetDefaultWindow();
216  if( ( pDefWindow
217  && pDefWindow->ImplGetFrame()->MapUnicodeToKeyCode( nUnicode,
218  Application::GetSettings().GetUILanguageTag().getLanguageType(), nKeyCode )
219  && aKeyCode.GetCode() == nKeyCode.GetCode()
220  )
221  || ( ascii
222  && rI18nHelper.MatchMnemonic( pData->aText, ascii )
223  )
224  )
225  {
226  if( nDuplicates > 1 && rPos == nCurrentPos )
227  continue; // select next entry with the same mnemonic
228  else
229  return pData;
230  }
231  }
232  }
233  }
234  }
235 
236  return nullptr;
237 }
238 
239 size_t MenuItemList::GetItemCount( sal_Unicode cSelectChar ) const
240 {
241  // returns number of entries with same mnemonic
243 
244  size_t nItems = 0;
245  for ( size_t nPos = maItemList.size(); nPos; )
246  {
247  MenuItemData* pData = maItemList[ --nPos ].get();
248  if ( pData->bEnabled && rI18nHelper.MatchMnemonic( pData->aText, cSelectChar ) )
249  nItems++;
250  }
251 
252  return nItems;
253 }
254 
255 size_t MenuItemList::GetItemCount( KeyCode aKeyCode ) const
256 {
257  // returns number of entries with same mnemonic
258  // uses key codes instead of character codes
260  char ascii = 0;
261  if( aKeyCode.GetCode() >= KEY_A && aKeyCode.GetCode() <= KEY_Z )
262  ascii = sal::static_int_cast<char>('A' + (aKeyCode.GetCode() - KEY_A));
263 
264  size_t nItems = 0;
265  for ( size_t nPos = maItemList.size(); nPos; )
266  {
267  MenuItemData* pData = maItemList[ --nPos ].get();
268  if ( pData->bEnabled )
269  {
270  sal_Int32 n = pData->aText.indexOf('~');
271  if (n != -1)
272  {
273  KeyCode nKeyCode;
274  // if MapUnicodeToKeyCode fails or is unsupported we try the pure ascii mapping of the keycodes
275  // so we have working shortcuts when ascii mnemonics are used
276  vcl::Window* pDefWindow = ImplGetDefaultWindow();
277  if( ( pDefWindow
278  && pDefWindow->ImplGetFrame()->MapUnicodeToKeyCode( pData->aText[n+1],
280  && aKeyCode.GetCode() == nKeyCode.GetCode()
281  )
282  || ( ascii
283  && rI18nHelper.MatchMnemonic( pData->aText, ascii )
284  )
285  )
286  nItems++;
287  }
288  }
289  }
290 
291  return nItems;
292 }
293 
294 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
VclPtr< Menu > pSubMenu
OUString aText
Definition: salmenu.hxx:34
#define ascii(x)
MenuItemType
Definition: vclenum.hxx:30
const LanguageTag & GetUILanguageTag() const
MenuItemData * SearchItem(sal_Unicode cSelectChar, vcl::KeyCode aKeyCode, size_t &rPos, size_t &nDuplicates, size_t nCurrentPos) const
LanguageType getLanguageType(bool bResolveSystem=true) const
void Remove(size_t nPos)
static const AllSettings & GetSettings()
Gets the application's settings.
Definition: svapp.cxx:705
virtual std::unique_ptr< SalMenuItem > CreateMenuItem(const SalItemParams &pItemData)
Definition: salvtables.cxx:136
sal_Int16 nId
sal_uInt16 GetCode() const
Definition: keycod.hxx:53
size_t GetItemCount(sal_Unicode cSelectChar) const
const vcl::I18nHelper & GetUILocaleI18nHelper() const
MenuItemBits nBits
Definition: salmenu.hxx:37
MenuItemBits
Definition: vclenum.hxx:32
sal_uInt16 nId
Definition: salmenu.hxx:36
sal_uInt16 sal_Unicode
void InsertSeparator(const OString &rIdent, size_t nPos)
void * nUserValue
#define KEY_A
Definition: keycodes.hxx:56
MenuItemType eType
Definition: salmenu.hxx:35
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:67
sal_uInt16 nId
int i
MenuItemType eType
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:304
#define KEY_Z
Definition: keycodes.hxx:81
std::unique_ptr< SalMenuItem > pSalMenuItem
std::unique_ptr< SalLayout > ImplLayout(const OUString &, sal_Int32 nIndex, sal_Int32 nLen, const Point &rLogicPos=Point(0, 0), long nLogicWidth=0, const long *pLogicDXArray=nullptr, SalLayoutFlags flags=SalLayoutFlags::NONE, vcl::TextLayoutCache const *=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) const
Definition: text.cxx:1233
bool MatchMnemonic(const OUString &rString, sal_Unicode cMnemonicChar) const
Definition: i18nhelp.cxx:141
SalLayoutGlyphs * GetTextGlyphs(const OutputDevice *pOutputDevice)
Computes aText's text layout (glyphs), cached in aTextGlyphs.
VclPtr< Menu > pMenu
Definition: salmenu.hxx:33
SalFrame * ImplGetFrame() const
Definition: window2.cxx:853
Definition: menu.hxx:121
OString sIdent
Image aImage
Definition: salmenu.hxx:32
Definition: image.hxx:51
MenuItemData * GetData(sal_uInt16 nSVId, size_t &rPos) const
OUString aText
virtual bool MapUnicodeToKeyCode(sal_Unicode aUnicode, LanguageType aLangType, vcl::KeyCode &rKeyCode)=0
static OUString GetNonMnemonicString(const OUString &rStr, sal_Int32 &rMnemonicPos)
Definition: text.cxx:2213
vcl::Window * ImplGetDefaultWindow()
Returns either the application window, or the default GL context window.
Definition: svdata.cxx:202
sal_Int32 nPos
MenuItemData * Insert(sal_uInt16 nId, MenuItemType eType, MenuItemBits nBits, const OUString &rStr, Menu *pMenu, size_t nPos, const OString &rIdent)
SalInstance * mpDefInst
Definition: svdata.hxx:341
MenuItemBits nBits