]> git.saurik.com Git - wxWidgets.git/blame - src/common/rearrangectrl.cpp
fixing focus, fixes #11911
[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{
128 wxSwap(m_order[pos1], m_order[pos2]);
129
130 const wxString stringTmp = GetString(pos1);
131 const bool checkedTmp = IsChecked(pos1);
132
133 SetString(pos1, GetString(pos2));
134 Check(pos1, IsChecked(pos2));
135
136 SetString(pos2, stringTmp);
137 Check(pos2, checkedTmp);
138}
139
140void wxRearrangeList::OnCheck(wxCommandEvent& event)
141{
142 // update the internal state to match the new item state
143 const int n = event.GetInt();
144
af67f39d 145 m_order[n] = ~m_order[n];
d169fa6a
VZ
146
147 wxASSERT_MSG( (m_order[n] >= 0) == IsChecked(n),
148 "discrepancy between internal state and GUI" );
af67f39d
VZ
149}
150
151// ============================================================================
152// wxRearrangeCtrl implementation
153// ============================================================================
154
155BEGIN_EVENT_TABLE(wxRearrangeCtrl, wxPanel)
156 EVT_UPDATE_UI(wxID_UP, wxRearrangeCtrl::OnUpdateButtonUI)
157 EVT_UPDATE_UI(wxID_DOWN, wxRearrangeCtrl::OnUpdateButtonUI)
158
159 EVT_BUTTON(wxID_UP, wxRearrangeCtrl::OnButton)
160 EVT_BUTTON(wxID_DOWN, wxRearrangeCtrl::OnButton)
161END_EVENT_TABLE()
162
163void wxRearrangeCtrl::Init()
164{
165 m_list = NULL;
166}
167
168bool
169wxRearrangeCtrl::Create(wxWindow *parent,
170 wxWindowID id,
171 const wxPoint& pos,
172 const wxSize& size,
173 const wxArrayInt& order,
174 const wxArrayString& items,
175 long style,
176 const wxValidator& validator,
177 const wxString& name)
178{
179 // create all the windows
180 if ( !wxPanel::Create(parent, id, pos, size, wxTAB_TRAVERSAL, name) )
181 return false;
182
183 m_list = new wxRearrangeList(this, wxID_ANY,
184 wxDefaultPosition, wxDefaultSize,
185 order, items,
186 style, validator);
187 wxButton * const btnUp = new wxButton(this, wxID_UP);
188 wxButton * const btnDown = new wxButton(this, wxID_DOWN);
189
190 // arrange them in a sizer
191 wxSizer * const sizerBtns = new wxBoxSizer(wxVERTICAL);
192 sizerBtns->Add(btnUp, wxSizerFlags().Centre().Border(wxBOTTOM));
193 sizerBtns->Add(btnDown, wxSizerFlags().Centre().Border(wxTOP));
194
195 wxSizer * const sizerTop = new wxBoxSizer(wxHORIZONTAL);
196 sizerTop->Add(m_list, wxSizerFlags(1).Expand().Border(wxRIGHT));
197 sizerTop->Add(sizerBtns, wxSizerFlags(0).Centre().Border(wxLEFT));
198 SetSizer(sizerTop);
199
200 m_list->SetFocus();
201
202 return true;
203}
204
205void wxRearrangeCtrl::OnUpdateButtonUI(wxUpdateUIEvent& event)
206{
207 event.Enable( event.GetId() == wxID_UP ? m_list->CanMoveCurrentUp()
208 : m_list->CanMoveCurrentDown() );
209}
210
211void wxRearrangeCtrl::OnButton(wxCommandEvent& event)
212{
213 if ( event.GetId() == wxID_UP )
214 m_list->MoveCurrentUp();
215 else
216 m_list->MoveCurrentDown();
217}
218
219// ============================================================================
220// wxRearrangeDialog implementation
221// ============================================================================
222
223extern
224WXDLLIMPEXP_DATA_CORE(const char) wxRearrangeDialogNameStr[] = "wxRearrangeDlg";
225
5a5f305a 226namespace
af67f39d 227{
5a5f305a
VZ
228
229enum wxRearrangeDialogSizerPositions
230{
231 Pos_Label,
232 Pos_Ctrl,
233 Pos_Buttons,
234 Pos_Max
235};
236
237} // anonymous namespace
238
239bool wxRearrangeDialog::Create(wxWindow *parent,
240 const wxString& message,
241 const wxString& title,
242 const wxArrayInt& order,
243 const wxArrayString& items,
244 const wxPoint& pos,
245 const wxString& name)
246{
247 if ( !wxDialog::Create(parent, wxID_ANY, title,
248 pos, wxDefaultSize,
249 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER,
250 name) )
251 return false;
252
af67f39d
VZ
253 m_ctrl = new wxRearrangeCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
254 order, items);
255
5a5f305a
VZ
256 // notice that the items in this sizer should be inserted accordingly to
257 // wxRearrangeDialogSizerPositions order
af67f39d
VZ
258 wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL);
259 sizerTop->Add(new wxStaticText(this, wxID_ANY, message),
5a5f305a 260 wxSizerFlags().Border());
af67f39d
VZ
261 sizerTop->Add(m_ctrl,
262 wxSizerFlags(1).Expand().Border());
263 sizerTop->Add(CreateSeparatedButtonSizer(wxOK | wxCANCEL),
264 wxSizerFlags().Expand().Border());
265 SetSizerAndFit(sizerTop);
5a5f305a
VZ
266
267 return true;
268}
269
270void wxRearrangeDialog::AddExtraControls(wxWindow *win)
271{
272 wxSizer * const sizer = GetSizer();
273 wxCHECK_RET( sizer, "the dialog must be created first" );
274
275 wxASSERT_MSG( sizer->GetChildren().GetCount() == Pos_Max,
276 "calling AddExtraControls() twice?" );
277
278 sizer->Insert(Pos_Buttons, win, wxSizerFlags().Expand().Border());
279
280 win->MoveAfterInTabOrder(m_ctrl);
281
282 // we need to update the initial/minimal window size
283 sizer->SetSizeHints(this);
284}
285
286wxRearrangeList *wxRearrangeDialog::GetList() const
287{
288 wxCHECK_MSG( m_ctrl, NULL, "the dialog must be created first" );
289
290 return m_ctrl->GetList();
291}
292
293wxArrayInt wxRearrangeDialog::GetOrder() const
294{
295 wxCHECK_MSG( m_ctrl, wxArrayInt(), "the dialog must be created first" );
296
297 return m_ctrl->GetList()->GetCurrentOrder();
af67f39d 298}
f0bb342f
VZ
299
300#endif // wxUSE_REARRANGECTRL