1
///////////////////////////////////////////////////////////////////////////////
2
// Name: src/common/rearrangectrl.cpp
3
// Purpose: implementation of classes in wx/rearrangectrl.h
4
// Author: Vadim Zeitlin
6
// RCS-ID: $Id: rearrangectrl.cpp 65844 2010-10-18 23:43:09Z VZ $
7
// Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
8
// Licence: wxWindows licence
9
///////////////////////////////////////////////////////////////////////////////
11
// ============================================================================
13
// ============================================================================
15
// ----------------------------------------------------------------------------
17
// ----------------------------------------------------------------------------
19
// for compilers that support precompilation, includes "wx.h".
20
#include "wx/wxprec.h"
26
#if wxUSE_REARRANGECTRL
29
#include "wx/button.h"
30
#include "wx/stattext.h"
34
#include "wx/rearrangectrl.h"
36
// ============================================================================
37
// wxRearrangeList implementation
38
// ============================================================================
41
WXDLLIMPEXP_DATA_CORE(const char) wxRearrangeListNameStr[] = "wxRearrangeList";
43
BEGIN_EVENT_TABLE(wxRearrangeList, wxCheckListBox)
44
EVT_CHECKLISTBOX(wxID_ANY, wxRearrangeList::OnCheck)
47
bool wxRearrangeList::Create(wxWindow *parent,
51
const wxArrayInt& order,
52
const wxArrayString& items,
54
const wxValidator& validator,
57
// construct the array of items in the order in which they should appear in
59
const size_t count = items.size();
60
wxCHECK_MSG( order.size() == count, false, "arrays not in sync" );
62
wxArrayString itemsInOrder;
63
itemsInOrder.reserve(count);
65
for ( n = 0; n < count; n++ )
70
itemsInOrder.push_back(items[idx]);
73
// do create the real control
74
if ( !wxCheckListBox::Create(parent, id, pos, size, itemsInOrder,
75
style, validator, name) )
78
// and now check all the items which should be initially checked
79
for ( n = 0; n < count; n++ )
90
bool wxRearrangeList::CanMoveCurrentUp() const
92
const int sel = GetSelection();
93
return sel != wxNOT_FOUND && sel != 0;
96
bool wxRearrangeList::CanMoveCurrentDown() const
98
const int sel = GetSelection();
99
return sel != wxNOT_FOUND && static_cast<unsigned>(sel) != GetCount() - 1;
102
bool wxRearrangeList::MoveCurrentUp()
104
const int sel = GetSelection();
105
if ( sel == wxNOT_FOUND || sel == 0 )
109
SetSelection(sel - 1);
114
bool wxRearrangeList::MoveCurrentDown()
116
const int sel = GetSelection();
117
if ( sel == wxNOT_FOUND || static_cast<unsigned>(sel) == GetCount() - 1 )
121
SetSelection(sel + 1);
126
void wxRearrangeList::Swap(int pos1, int pos2)
128
// update the internally stored order
129
wxSwap(m_order[pos1], m_order[pos2]);
132
// and now also swap all the attributes of the items
135
const wxString stringTmp = GetString(pos1);
136
SetString(pos1, GetString(pos2));
137
SetString(pos2, stringTmp);
139
// then the checked state
140
const bool checkedTmp = IsChecked(pos1);
141
Check(pos1, IsChecked(pos2));
142
Check(pos2, checkedTmp);
144
// and finally the client data, if necessary
145
switch ( GetClientDataType() )
147
case wxClientData_None:
151
case wxClientData_Object:
153
wxClientData * const dataTmp = DetachClientObject(pos1);
154
SetClientObject(pos1, DetachClientObject(pos2));
155
SetClientObject(pos2, dataTmp);
159
case wxClientData_Void:
161
void * const dataTmp = GetClientData(pos1);
162
SetClientData(pos1, GetClientData(pos2));
163
SetClientData(pos2, dataTmp);
169
void wxRearrangeList::OnCheck(wxCommandEvent& event)
171
// update the internal state to match the new item state
172
const int n = event.GetInt();
174
m_order[n] = ~m_order[n];
176
wxASSERT_MSG( (m_order[n] >= 0) == IsChecked(n),
177
"discrepancy between internal state and GUI" );
180
// ============================================================================
181
// wxRearrangeCtrl implementation
182
// ============================================================================
184
BEGIN_EVENT_TABLE(wxRearrangeCtrl, wxPanel)
185
EVT_UPDATE_UI(wxID_UP, wxRearrangeCtrl::OnUpdateButtonUI)
186
EVT_UPDATE_UI(wxID_DOWN, wxRearrangeCtrl::OnUpdateButtonUI)
188
EVT_BUTTON(wxID_UP, wxRearrangeCtrl::OnButton)
189
EVT_BUTTON(wxID_DOWN, wxRearrangeCtrl::OnButton)
192
void wxRearrangeCtrl::Init()
198
wxRearrangeCtrl::Create(wxWindow *parent,
202
const wxArrayInt& order,
203
const wxArrayString& items,
205
const wxValidator& validator,
206
const wxString& name)
208
// create all the windows
209
if ( !wxPanel::Create(parent, id, pos, size, wxTAB_TRAVERSAL, name) )
212
m_list = new wxRearrangeList(this, wxID_ANY,
213
wxDefaultPosition, wxDefaultSize,
216
wxButton * const btnUp = new wxButton(this, wxID_UP);
217
wxButton * const btnDown = new wxButton(this, wxID_DOWN);
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));
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));
234
void wxRearrangeCtrl::OnUpdateButtonUI(wxUpdateUIEvent& event)
236
event.Enable( event.GetId() == wxID_UP ? m_list->CanMoveCurrentUp()
237
: m_list->CanMoveCurrentDown() );
240
void wxRearrangeCtrl::OnButton(wxCommandEvent& event)
242
if ( event.GetId() == wxID_UP )
243
m_list->MoveCurrentUp();
245
m_list->MoveCurrentDown();
248
// ============================================================================
249
// wxRearrangeDialog implementation
250
// ============================================================================
253
WXDLLIMPEXP_DATA_CORE(const char) wxRearrangeDialogNameStr[] = "wxRearrangeDlg";
258
enum wxRearrangeDialogSizerPositions
266
} // anonymous namespace
268
bool wxRearrangeDialog::Create(wxWindow *parent,
269
const wxString& message,
270
const wxString& title,
271
const wxArrayInt& order,
272
const wxArrayString& items,
274
const wxString& name)
276
if ( !wxDialog::Create(parent, wxID_ANY, title,
278
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER,
282
m_ctrl = new wxRearrangeCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
285
// notice that the items in this sizer should be inserted accordingly to
286
// wxRearrangeDialogSizerPositions order
287
wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL);
289
if ( !message.empty() )
291
sizerTop->Add(new wxStaticText(this, wxID_ANY, message),
292
wxSizerFlags().Border());
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);
301
sizerTop->Add(m_ctrl,
302
wxSizerFlags(1).Expand().Border());
303
sizerTop->Add(CreateSeparatedButtonSizer(wxOK | wxCANCEL),
304
wxSizerFlags().Expand().Border());
305
SetSizerAndFit(sizerTop);
310
void wxRearrangeDialog::AddExtraControls(wxWindow *win)
312
wxSizer * const sizer = GetSizer();
313
wxCHECK_RET( sizer, "the dialog must be created first" );
315
wxASSERT_MSG( sizer->GetChildren().GetCount() == Pos_Max,
316
"calling AddExtraControls() twice?" );
318
sizer->Insert(Pos_Buttons, win, wxSizerFlags().Expand().Border());
320
win->MoveAfterInTabOrder(m_ctrl);
322
// we need to update the initial/minimal window size
323
sizer->SetSizeHints(this);
326
wxRearrangeList *wxRearrangeDialog::GetList() const
328
wxCHECK_MSG( m_ctrl, NULL, "the dialog must be created first" );
330
return m_ctrl->GetList();
333
wxArrayInt wxRearrangeDialog::GetOrder() const
335
wxCHECK_MSG( m_ctrl, wxArrayInt(), "the dialog must be created first" );
337
return m_ctrl->GetList()->GetCurrentOrder();
340
#endif // wxUSE_REARRANGECTRL