KiCad PCB EDA Suite
eda_reorderable_list_dialog.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <algorithm>
21#include <bitmaps.h>
22#include <macros.h>
24
25
26static int DEFAULT_SINGLE_COL_WIDTH = 260;
27
28
29EDA_REORDERABLE_LIST_DIALOG::EDA_REORDERABLE_LIST_DIALOG( wxWindow* aParent, const wxString& aTitle,
30 const std::vector<wxString>& aAllItems,
31 const std::vector<wxString>& aEnabledItems ) :
32 EDA_REORDERABLE_LIST_DIALOG_BASE( aParent, wxID_ANY, aTitle ),
33 m_availableItems( aAllItems ),
34 m_enabledItems( aEnabledItems ),
35 m_selectedAvailable( 0 ),
36 m_selectedEnabled( 0 )
37{
38 m_btnUp->SetBitmap( KiBitmap( BITMAPS::small_up ) );
39 m_btnDown->SetBitmap( KiBitmap( BITMAPS::small_down ) );
40
41 // DIALOG_SHIM needs a unique hash_key because classname is not sufficient
42 // because so many dialogs share this same class, with different numbers of
43 // columns, different column names, and column widths.
44 m_hash_key = TO_UTF8( aTitle );
45
46 m_availableListBox->InsertColumn( 0, wxEmptyString, wxLIST_FORMAT_LEFT,
48 m_enabledListBox->InsertColumn( 0, wxEmptyString, wxLIST_FORMAT_LEFT,
50
52
54
55 // this line fixes an issue on Linux Ubuntu using Unity (dialog not shown),
56 // and works fine on all systems
57 GetSizer()->Fit( this );
58
59 Centre();
60}
61
62
64{
65 m_availableListBox->DeleteAllItems();
66 m_enabledListBox->DeleteAllItems();
67
68 std::set<wxString> enabledSet;
69
70 for( size_t idx = 0; idx < m_enabledItems.size(); ++idx )
71 {
72 wxListItem info;
73 info.m_itemId = idx;
74 info.m_col = 0;
75 info.m_text = m_enabledItems[idx];
77 info.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_WIDTH;
78
79 m_enabledListBox->InsertItem( info );
80
81 if( m_selectedEnabled == static_cast<long>( idx ) )
82 m_enabledListBox->SetItemState( idx, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
83
84 enabledSet.insert( m_enabledItems[idx] );
85 }
86
87 m_availableItems.erase( std::remove_if( m_availableItems.begin(), m_availableItems.end(),
88 [&]( const wxString& aItem ) -> bool
89 {
90 return enabledSet.count( aItem );
91 } ),
92 m_availableItems.end() );
93
94 for( size_t idx = 0; idx < m_availableItems.size(); ++idx )
95 {
96 wxListItem info;
97 info.m_itemId = idx;
98 info.m_col = 0;
99 info.m_text = m_availableItems[idx];
101 info.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_WIDTH;
102
103 m_availableListBox->InsertItem( info );
104
105 if( m_selectedAvailable == static_cast<long>( idx ) )
106 m_availableListBox->SetItemState( idx, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
107 }
108
109 if( !m_availableItems.empty() )
110 m_availableListBox->EnsureVisible( m_selectedAvailable );
111
112 if( !m_enabledItems.empty() )
113 m_enabledListBox->EnsureVisible( m_selectedEnabled );
114
115 m_btnAdd->Enable( !m_availableItems.empty() );
116 m_btnRemove->Enable( !m_enabledItems.empty() );
117}
118
119
120void EDA_REORDERABLE_LIST_DIALOG::onAddItem( wxCommandEvent& aEvent )
121{
122 wxListItem info;
123
125 return;
126
127 m_availableItems.erase( m_availableItems.begin() + info.m_itemId );
129
130 long pos = std::min( m_selectedEnabled + 1, static_cast<long>( m_enabledItems.size() ) );
131
132 info.m_itemId = pos;
133 info.m_mask = wxLIST_MASK_TEXT;
134
135 m_enabledItems.insert( m_enabledItems.begin() + pos, info.m_text );
136 m_enabledListBox->InsertItem( info );
137
139}
140
141
142void EDA_REORDERABLE_LIST_DIALOG::onRemoveItem( wxCommandEvent& aEvent )
143{
144 wxListItem info;
145
146 if( !getSelectedItem( m_enabledListBox, info ) || info.m_itemId == 0 )
147 return;
148
149 m_enabledItems.erase( m_enabledItems.begin() + info.m_itemId );
150 m_enabledListBox->DeleteItem( m_selectedEnabled );
151
153 static_cast<long>( m_enabledItems.size() - 1 ) );
154
155 m_enabledListBox->SetItemState( m_selectedEnabled, wxLIST_STATE_SELECTED,
156 wxLIST_STATE_SELECTED );
157
158 long pos = std::max( long( 0 ), m_selectedAvailable );
159 info.m_itemId = pos;
160
161 m_availableItems.insert( m_availableItems.begin() + pos, info.m_text );
162 m_availableListBox->InsertItem( info );
163
165}
166
167
168void EDA_REORDERABLE_LIST_DIALOG::onMoveUp( wxCommandEvent& aEvent )
169{
170 wxListItem info;
171
172 if( !getSelectedItem( m_enabledListBox, info ) || info.m_itemId == 0 )
173 return;
174
175 auto current = m_enabledItems.begin() + info.m_itemId;
176 auto prev = m_enabledItems.begin() + info.m_itemId - 1;
177
178 std::iter_swap( current, prev );
179
181
183 updateItems();
184}
185
186
187void EDA_REORDERABLE_LIST_DIALOG::onMoveDown( wxCommandEvent& aEvent )
188{
189 wxListItem info;
190
192 || info.m_itemId == static_cast<long>( m_enabledItems.size() ) - 1 )
193 {
194 return;
195 }
196
197 auto current = m_enabledItems.begin() + info.m_itemId;
198 auto prev = m_enabledItems.begin() + info.m_itemId + 1;
199
200 std::iter_swap( current, prev );
201
203
205 updateItems();
206}
207
208
209bool EDA_REORDERABLE_LIST_DIALOG::getSelectedItem( wxListCtrl* aList, wxListItem& aInfo )
210{
211 long item = aList->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
212
213 if( item < 0 )
214 return false;
215
216 aInfo.m_mask = wxLIST_MASK_DATA | wxLIST_MASK_STATE | wxLIST_MASK_TEXT;
217 aInfo.m_itemId = item;
218 aInfo.m_col = 0;
219
220 if( !aList->GetItem( aInfo ) )
221 return false;
222
223 return true;
224}
225
226
228{
229 wxListItem info;
230
232 {
234 return;
235 }
236
237 m_selectedEnabled = info.m_itemId;
239}
240
241
243{
244 wxListItem info;
245
247 {
249 return;
250 }
251
252 m_selectedAvailable = info.m_itemId;
254}
255
256
258{
259 m_btnUp->Enable( !m_enabledItems.empty() && m_selectedEnabled > 0 );
260 m_btnDown->Enable( !m_enabledItems.empty() && m_selectedEnabled > 0 &&
261 m_selectedEnabled < static_cast<int>( m_enabledItems.size() ) - 1 );
262 m_btnAdd->Enable( !m_availableItems.empty() && m_selectedAvailable >= 0 );
263 m_btnRemove->Enable( !m_enabledItems.empty() && m_selectedEnabled > 0 );
264}
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
Definition: dialog_shim.h:203
Class EDA_REORDERABLE_LIST_DIALOG_BASE.
std::vector< wxString > m_availableItems
void onAvailableListItemSelected(wxListEvent &event) override
bool getSelectedItem(wxListCtrl *aList, wxListItem &aInfo)
void onMoveUp(wxCommandEvent &aEvent) override
void onMoveDown(wxCommandEvent &aEvent) override
void onEnabledListItemSelected(wxListEvent &event) override
EDA_REORDERABLE_LIST_DIALOG(wxWindow *aParent, const wxString &aTitle, const std::vector< wxString > &aAllItems, const std::vector< wxString > &aEnabledItems)
void onRemoveItem(wxCommandEvent &aEvent) override
void onAddItem(wxCommandEvent &aEvent) override
std::vector< wxString > m_enabledItems
static int DEFAULT_SINGLE_COL_WIDTH
This file contains miscellaneous commonly used macros and functions.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96