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