Avoid potential negative array index access to cached text.
[LibreOffice.git] / framework / source / uielement / togglebuttontoolbarcontroller.cxx
blobc17b08efeeb7d3da4a4da44740a6729fd48ed4a0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <uielement/togglebuttontoolbarcontroller.hxx>
22 #include <comphelper/propertyvalue.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/toolbox.hxx>
25 #include <vcl/menu.hxx>
27 using namespace ::com::sun::star;
28 using namespace ::com::sun::star::awt;
29 using namespace ::com::sun::star::uno;
30 using namespace ::com::sun::star::beans;
31 using namespace ::com::sun::star::lang;
32 using namespace ::com::sun::star::frame;
33 using namespace ::com::sun::star::util;
35 namespace framework
38 ToggleButtonToolbarController::ToggleButtonToolbarController(
39 const Reference< XComponentContext >& rxContext,
40 const Reference< XFrame >& rFrame,
41 ToolBox* pToolbar,
42 ToolBoxItemId nID,
43 Style eStyle,
44 const OUString& aCommand ) :
45 ComplexToolbarController( rxContext, rFrame, pToolbar, nID, aCommand )
47 if ( eStyle == Style::DropDownButton )
48 m_xToolbar->SetItemBits( m_nID, ToolBoxItemBits::DROPDOWNONLY | m_xToolbar->GetItemBits( m_nID ) );
49 else // Style::ToggleDropDownButton
50 m_xToolbar->SetItemBits( m_nID, ToolBoxItemBits::DROPDOWN | m_xToolbar->GetItemBits( m_nID ) );
53 ToggleButtonToolbarController::~ToggleButtonToolbarController()
57 void SAL_CALL ToggleButtonToolbarController::dispose()
59 SolarMutexGuard aSolarMutexGuard;
60 ComplexToolbarController::dispose();
63 Sequence<PropertyValue> ToggleButtonToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const
65 Sequence<PropertyValue> aArgs{ // Add key modifier to argument list
66 comphelper::makePropertyValue("KeyModifier", KeyModifier),
67 comphelper::makePropertyValue("Text", m_aCurrentSelection) };
68 return aArgs;
71 uno::Reference< awt::XWindow > SAL_CALL ToggleButtonToolbarController::createPopupWindow()
73 uno::Reference< awt::XWindow > xWindow;
75 SolarMutexGuard aSolarMutexGuard;
77 // create popup menu
78 ScopedVclPtrInstance<::PopupMenu> aPopup;
79 const sal_uInt32 nCount = m_aDropdownMenuList.size();
80 for ( sal_uInt32 i = 0; i < nCount; i++ )
82 const OUString & rLabel = m_aDropdownMenuList[i].mLabel;
83 aPopup->InsertItem( sal_uInt16( i+1 ), rLabel );
84 if ( rLabel == m_aCurrentSelection )
85 aPopup->CheckItem( sal_uInt16( i+1 ) );
86 else
87 aPopup->CheckItem( sal_uInt16( i+1 ), false );
89 if ( !m_aDropdownMenuList[i].mTipHelpText.isEmpty() )
90 aPopup->SetTipHelpText( sal_uInt16( i+1 ), m_aDropdownMenuList[i].mTipHelpText );
93 m_xToolbar->SetItemDown( m_nID, true );
94 aPopup->SetSelectHdl( LINK( this, ToggleButtonToolbarController, MenuSelectHdl ));
95 aPopup->Execute( m_xToolbar, m_xToolbar->GetItemRect( m_nID ));
96 m_xToolbar->SetItemDown( m_nID, false );
98 return xWindow;
101 void ToggleButtonToolbarController::executeControlCommand( const css::frame::ControlCommand& rControlCommand )
103 SolarMutexGuard aSolarMutexGuard;
105 if ( rControlCommand.Command == "SetList" )
107 for ( auto const & arg : rControlCommand.Arguments )
109 if ( arg.Name == "List" )
111 Sequence< OUString > aList;
112 m_aDropdownMenuList.clear();
113 m_aCurrentSelection.clear();
115 arg.Value >>= aList;
116 for ( OUString const & label : std::as_const(aList) )
118 m_aDropdownMenuList.push_back( DropdownMenuItem() );
119 m_aDropdownMenuList.back().mLabel = label;
122 // send notification
123 uno::Sequence< beans::NamedValue > aInfo { { "List", css::uno::Any(aList) } };
124 addNotifyInfo( "ListChanged",
125 getDispatchFromCommand( m_aCommandURL ),
126 aInfo );
128 break;
132 else if ( rControlCommand.Command == "CheckItemPos" )
134 for ( auto const & arg : rControlCommand.Arguments )
136 if ( arg.Name == "Pos" )
138 sal_Int32 nPos( -1 );
140 arg.Value >>= nPos;
141 if ( nPos >= 0 &&
142 ( sal::static_int_cast< sal_uInt32 >(nPos)
143 < m_aDropdownMenuList.size() ) )
145 m_aCurrentSelection = m_aDropdownMenuList[nPos].mLabel;
147 // send notification
148 uno::Sequence< beans::NamedValue > aInfo { { "ItemChecked", css::uno::Any(nPos) } };
149 addNotifyInfo( "Pos",
150 getDispatchFromCommand( m_aCommandURL ),
151 aInfo );
153 break;
157 else if ( rControlCommand.Command == "AddEntry" )
159 OUString aText;
160 OUString aTipHelpText;
162 for ( auto const & arg : rControlCommand.Arguments )
164 if ( arg.Name == "Text" )
166 arg.Value >>= aText;
168 else if ( arg.Name == "TipHelpText" )
170 arg.Value >>= aTipHelpText;
174 if (!aText.isEmpty())
176 m_aDropdownMenuList.push_back( DropdownMenuItem() );
177 m_aDropdownMenuList.back().mLabel = aText;
178 m_aDropdownMenuList.back().mTipHelpText = aTipHelpText;
181 else if ( rControlCommand.Command == "InsertEntry" )
183 sal_Int32 nPos(0);
184 sal_Int32 nSize = sal_Int32( m_aDropdownMenuList.size() );
185 OUString aText;
186 for ( auto const & arg : rControlCommand.Arguments )
188 if ( arg.Name == "Pos" )
190 sal_Int32 nTmpPos = 0;
191 if ( arg.Value >>= nTmpPos )
193 if (( nTmpPos >= 0 ) && ( nTmpPos < nSize ))
194 nPos = nTmpPos;
197 else if ( arg.Name == "Text" )
198 arg.Value >>= aText;
201 std::vector< DropdownMenuItem >::iterator aIter = m_aDropdownMenuList.begin();
202 aIter += nPos;
203 aIter = m_aDropdownMenuList.insert(aIter, DropdownMenuItem());
204 if (aIter != m_aDropdownMenuList.end())
205 aIter->mLabel = aText;
207 else if ( rControlCommand.Command == "RemoveEntryPos" )
209 for ( auto const & arg : rControlCommand.Arguments )
211 if ( arg.Name == "Pos" )
213 sal_Int32 nPos( -1 );
214 if ( arg.Value >>= nPos )
216 if ( nPos < sal_Int32( m_aDropdownMenuList.size() ))
218 m_aDropdownMenuList.erase(m_aDropdownMenuList.begin() + nPos);
221 break;
225 else if ( rControlCommand.Command == "RemoveEntryText" )
227 for ( auto const & arg : rControlCommand.Arguments )
229 if ( arg.Name == "Text" )
231 OUString aText;
232 if ( arg.Value >>= aText )
234 sal_Int32 nSize = sal_Int32( m_aDropdownMenuList.size() );
235 for ( sal_Int32 j = 0; j < nSize; j++ )
237 if ( m_aDropdownMenuList[j].mLabel == aText )
239 m_aDropdownMenuList.erase(m_aDropdownMenuList.begin() + j);
240 break;
244 break;
248 else if ( rControlCommand.Command == "createPopupMenu" )
250 createPopupWindow();
254 IMPL_LINK( ToggleButtonToolbarController, MenuSelectHdl, Menu *, pMenu, bool )
256 SolarMutexGuard aGuard;
258 sal_uInt16 nItemId = pMenu->GetCurItemId();
259 if ( nItemId > 0 && nItemId <= m_aDropdownMenuList.size() )
261 m_aCurrentSelection = m_aDropdownMenuList[nItemId-1].mLabel;
263 execute( 0 );
265 return false;
268 } // namespace
270 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */