]> git.saurik.com Git - wxWidgets.git/blame - src/common/rearrangectrl.cpp
Implement incremental search in wxGenericListCtrl.
[wxWidgets.git] / src / common / rearrangectrl.cpp
CommitLineData
af67f39d
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/common/rearrangectrl.cpp
3// Purpose: implementation of classes in wx/rearrangectrl.h
4// Author: Vadim Zeitlin
5// Created: 2008-12-15
6// RCS-ID: $Id$
7// Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// for compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
f0bb342f
VZ
26#if wxUSE_REARRANGECTRL
27
af67f39d 28#ifndef WX_PRECOMP
3a492e5c 29 #include "wx/button.h"
627e6ccd 30 #include "wx/stattext.h"
3a492e5c 31 #include "wx/sizer.h"
af67f39d
VZ
32#endif // WX_PRECOMP
33
34#include "wx/rearrangectrl.h"
35
36// ============================================================================
37// wxRearrangeList implementation
38// ============================================================================
39
40extern
41WXDLLIMPEXP_DATA_CORE(const char) wxRearrangeListNameStr[] = "wxRearrangeList";
42
43BEGIN_EVENT_TABLE(wxRearrangeList, wxCheckListBox)
44 EVT_CHECKLISTBOX(wxID_ANY, wxRearrangeList::OnCheck)
45END_EVENT_TABLE()
46
47bool wxRearrangeList::Create(wxWindow *parent,
48 wxWindowID id,
49 const wxPoint& pos,
50 const wxSize& size,
51 const wxArrayInt& order,
52 const wxArrayString& items,
53 long style,
54 const wxValidator& validator,
55 const wxString& name)
56{
57 // construct the array of items in the order in which they should appear in
58 // the control
59 const size_t count = items.size();
60 wxCHECK_MSG( order.size() == count, false, "arrays not in sync" );
61
62 wxArrayString itemsInOrder;
63 itemsInOrder.reserve(count);
64 size_t n;
65 for ( n = 0; n < count; n++ )
66 {
67 int idx = order[n];
68 if ( idx < 0 )
69 idx = -idx - 1;
70 itemsInOrder.push_back(items[idx]);
71 }
72
73 // do create the real control
74 if ( !wxCheckListBox::Create(parent, id, pos, size, itemsInOrder,
75 style, validator, name) )
76 return false;
77
78 // and now check all the items which should be initially checked
79 for ( n = 0; n < count; n++ )
80 {
81 if ( order[n] >= 0 )
82 Check(n);
83 }
84
85 m_order = order;
86
87 return true;
88}
89
90bool wxRearrangeList::CanMoveCurrentUp() const
91{
92 const int sel = GetSelection();
93 return sel != wxNOT_FOUND && sel != 0;
94}
95
96bool wxRearrangeList::CanMoveCurrentDown() const
97{
98 const int sel = GetSelection();
99 return sel != wxNOT_FOUND && static_cast<unsigned>(sel) != GetCount() - 1;
100}
101
102bool wxRearrangeList::MoveCurrentUp()
103{
104 const int sel = GetSelection();
105 if ( sel == wxNOT_FOUND || sel == 0 )
106 return false;
107
108 Swap(sel, sel - 1);
109 SetSelection(sel - 1);
110
111 return true;
112}
113
114bool wxRearrangeList::MoveCurrentDown()
115{
116 const int sel = GetSelection();
117 if ( sel == wxNOT_FOUND || static_cast<unsigned>(sel) == GetCount() - 1 )
118 return false;
119
120 Swap(sel, sel + 1);
121 SetSelection(sel + 1);
122
123 return true;
124}
125
126void wxRearrangeList::Swap(int pos1, int pos2)
127{
5778dedc 128 // update the internally stored order
af67f39d
VZ
129 wxSwap(m_order[pos1], m_order[pos2]);
130
af67f39d 131
5778dedc
VZ
132 // and now also swap all the attributes of the items
133
134 // first the label
135 const wxString stringTmp = GetString(pos1);
af67f39d 136 SetString(pos1, GetString(pos2));
a8b3cea3 137 SetString(pos2, stringTmp);
af67f39d 138
5778dedc
VZ
139 // then the checked state
140 const bool checkedTmp = IsChecked(pos1);
a8b3cea3 141 Check(pos1, IsChecked(pos2));
af67f39d 142 Check(pos2, checkedTmp);
5778dedc
VZ
143
144 // and finally the client data, if necessary
145 switch ( GetClientDataType() )
146 {
147 case wxClientData_None:
148 // nothing to do
149 break;
150
151 case wxClientData_Object:
152 {
ab989357
VZ
153 wxClientData * const dataTmp = DetachClientObject(pos1);
154 SetClientObject(pos1, DetachClientObject(pos2));
5778dedc
VZ
155 SetClientObject(pos2, dataTmp);
156 }
157 break;
158
159 case wxClientData_Void:
160 {
161 void * const dataTmp = GetClientData(pos1);
162 SetClientData(pos1, GetClientData(pos2));
163 SetClientData(pos2, dataTmp);
164 }
165 break;
166 }
af67f39d
VZ
167}
168
169void wxRearrangeList::OnCheck(wxCommandEvent& event)
170{
171 // update the internal state to match the new item state
172 const int n = event.GetInt();
173
af67f39d 174 m_order[n] = ~m_order[n];
d169fa6a
VZ
175
176 wxASSERT_MSG( (m_order[n] >= 0) == IsChecked(n),
177 "discrepancy between internal state and GUI" );
af67f39d
VZ
178}
179
180// ============================================================================
181// wxRearrangeCtrl implementation
182// ============================================================================
183
184BEGIN_EVENT_TABLE(wxRearrangeCtrl, wxPanel)
185 EVT_UPDATE_UI(wxID_UP, wxRearrangeCtrl::OnUpdateButtonUI)
186 EVT_UPDATE_UI(wxID_DOWN, wxRearrangeCtrl::OnUpdateButtonUI)
187
188 EVT_BUTTON(wxID_UP, wxRearrangeCtrl::OnButton)
189 EVT_BUTTON(wxID_DOWN, wxRearrangeCtrl::OnButton)
190END_EVENT_TABLE()
191
192void wxRearrangeCtrl::Init()
193{
194 m_list = NULL;
195}
196
197bool
198wxRearrangeCtrl::Create(wxWindow *parent,
199 wxWindowID id,
200 const wxPoint& pos,
201 const wxSize& size,
202 const wxArrayInt& order,
203 const wxArrayString& items,
204 long style,
205 const wxValidator& validator,
206 const wxString& name)
207{
208 // create all the windows
209 if ( !wxPanel::Create(parent, id, pos, size, wxTAB_TRAVERSAL, name) )
210 return false;
211
212 m_list = new wxRearrangeList(this, wxID_ANY,
213 wxDefaultPosition, wxDefaultSize,
214 order, items,
215 style, validator);
216 wxButton * const btnUp = new wxButton(this, wxID_UP);
217 wxButton * const btnDown = new wxButton(this, wxID_DOWN);
218
219 // arrange them in a sizer
220 wxSizer * const sizerBtns = new wxBoxSizer(wxVERTICAL);
221 sizerBtns->Add(btnUp, wxSizerFlags().Centre().Border(wxBOTTOM));
222 sizerBtns->Add(btnDown, wxSizerFlags().Centre().Border(wxTOP));
223
224 wxSizer * const sizerTop = new wxBoxSizer(wxHORIZONTAL);
225 sizerTop->Add(m_list, wxSizerFlags(1).Expand().Border(wxRIGHT));
226 sizerTop->Add(sizerBtns, wxSizerFlags(0).Centre().Border(wxLEFT));
227 SetSizer(sizerTop);
228
229 m_list->SetFocus();
230
231 return true;
232}
233
234void wxRearrangeCtrl::OnUpdateButtonUI(wxUpdateUIEvent& event)
235{
236 event.Enable( event.GetId() == wxID_UP ? m_list->CanMoveCurrentUp()
237 : m_list->CanMoveCurrentDown() );
238}
239
240void wxRearrangeCtrl::OnButton(wxCommandEvent& event)
241{
242 if ( event.GetId() == wxID_UP )
243 m_list->MoveCurrentUp();
244 else
245 m_list->MoveCurrentDown();
246}
247
248// ============================================================================
249// wxRearrangeDialog implementation
250// ============================================================================
251
252extern
253WXDLLIMPEXP_DATA_CORE(const char) wxRearrangeDialogNameStr[] = "wxRearrangeDlg";
254
5a5f305a 255namespace
af67f39d 256{
5a5f305a
VZ
257
258enum wxRearrangeDialogSizerPositions
259{
260 Pos_Label,
261 Pos_Ctrl,
262 Pos_Buttons,
263 Pos_Max
264};
265
266} // anonymous namespace
267
268bool wxRearrangeDialog::Create(wxWindow *parent,
269 const wxString& message,
270 const wxString& title,
271 const wxArrayInt& order,
272 const wxArrayString& items,
273 const wxPoint& pos,
274 const wxString& name)
275{
276 if ( !wxDialog::Create(parent, wxID_ANY, title,
277 pos, wxDefaultSize,
278 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER,
279 name) )
280 return false;
281
af67f39d
VZ
282 m_ctrl = new wxRearrangeCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
283 order, items);
284
5a5f305a
VZ
285 // notice that the items in this sizer should be inserted accordingly to
286 // wxRearrangeDialogSizerPositions order
af67f39d 287 wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL);
b390729f
VS
288
289 if ( !message.empty() )
290 {
291 sizerTop->Add(new wxStaticText(this, wxID_ANY, message),
292 wxSizerFlags().Border());
293 }
294 else
295 {
296 // for convenience of other wxRearrangeDialog code that depends on
297 // positions of sizer items, insert a dummy zero-sized item
298 sizerTop->AddSpacer(0);
299 }
300
af67f39d
VZ
301 sizerTop->Add(m_ctrl,
302 wxSizerFlags(1).Expand().Border());
303 sizerTop->Add(CreateSeparatedButtonSizer(wxOK | wxCANCEL),
304 wxSizerFlags().Expand().Border());
305 SetSizerAndFit(sizerTop);
5a5f305a
VZ
306
307 return true;
308}
309
310void wxRearrangeDialog::AddExtraControls(wxWindow *win)
311{
312 wxSizer * const sizer = GetSizer();
313 wxCHECK_RET( sizer, "the dialog must be created first" );
314
315 wxASSERT_MSG( sizer->GetChildren().GetCount() == Pos_Max,
316 "calling AddExtraControls() twice?" );
317
318 sizer->Insert(Pos_Buttons, win, wxSizerFlags().Expand().Border());
319
320 win->MoveAfterInTabOrder(m_ctrl);
321
322 // we need to update the initial/minimal window size
323 sizer->SetSizeHints(this);
324}
325
326wxRearrangeList *wxRearrangeDialog::GetList() const
327{
328 wxCHECK_MSG( m_ctrl, NULL, "the dialog must be created first" );
329
330 return m_ctrl->GetList();
331}
332
333wxArrayInt wxRearrangeDialog::GetOrder() const
334{
335 wxCHECK_MSG( m_ctrl, wxArrayInt(), "the dialog must be created first" );
336
337 return m_ctrl->GetList()->GetCurrentOrder();
af67f39d 338}
f0bb342f
VZ
339
340#endif // wxUSE_REARRANGECTRL