Fix processing of events for MRU entries #10 and more in docview.
[wxWidgets.git] / src / common / rearrangectrl.cpp
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
26 #if wxUSE_REARRANGECTRL
27
28 #ifndef WX_PRECOMP
29 #include "wx/button.h"
30 #include "wx/stattext.h"
31 #include "wx/sizer.h"
32 #endif // WX_PRECOMP
33
34 #include "wx/rearrangectrl.h"
35
36 // ============================================================================
37 // wxRearrangeList implementation
38 // ============================================================================
39
40 extern
41 WXDLLIMPEXP_DATA_CORE(const char) wxRearrangeListNameStr[] = "wxRearrangeList";
42
43 BEGIN_EVENT_TABLE(wxRearrangeList, wxCheckListBox)
44 EVT_CHECKLISTBOX(wxID_ANY, wxRearrangeList::OnCheck)
45 END_EVENT_TABLE()
46
47 bool 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
90 bool wxRearrangeList::CanMoveCurrentUp() const
91 {
92 const int sel = GetSelection();
93 return sel != wxNOT_FOUND && sel != 0;
94 }
95
96 bool wxRearrangeList::CanMoveCurrentDown() const
97 {
98 const int sel = GetSelection();
99 return sel != wxNOT_FOUND && static_cast<unsigned>(sel) != GetCount() - 1;
100 }
101
102 bool 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
114 bool 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
126 void 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
140 void wxRearrangeList::OnCheck(wxCommandEvent& event)
141 {
142 // update the internal state to match the new item state
143 const int n = event.GetInt();
144
145 m_order[n] = ~m_order[n];
146
147 wxASSERT_MSG( (m_order[n] >= 0) == IsChecked(n),
148 "discrepancy between internal state and GUI" );
149 }
150
151 // ============================================================================
152 // wxRearrangeCtrl implementation
153 // ============================================================================
154
155 BEGIN_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)
161 END_EVENT_TABLE()
162
163 void wxRearrangeCtrl::Init()
164 {
165 m_list = NULL;
166 }
167
168 bool
169 wxRearrangeCtrl::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
205 void wxRearrangeCtrl::OnUpdateButtonUI(wxUpdateUIEvent& event)
206 {
207 event.Enable( event.GetId() == wxID_UP ? m_list->CanMoveCurrentUp()
208 : m_list->CanMoveCurrentDown() );
209 }
210
211 void 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
223 extern
224 WXDLLIMPEXP_DATA_CORE(const char) wxRearrangeDialogNameStr[] = "wxRearrangeDlg";
225
226 namespace
227 {
228
229 enum wxRearrangeDialogSizerPositions
230 {
231 Pos_Label,
232 Pos_Ctrl,
233 Pos_Buttons,
234 Pos_Max
235 };
236
237 } // anonymous namespace
238
239 bool 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
253 m_ctrl = new wxRearrangeCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
254 order, items);
255
256 // notice that the items in this sizer should be inserted accordingly to
257 // wxRearrangeDialogSizerPositions order
258 wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL);
259 sizerTop->Add(new wxStaticText(this, wxID_ANY, message),
260 wxSizerFlags().Border());
261 sizerTop->Add(m_ctrl,
262 wxSizerFlags(1).Expand().Border());
263 sizerTop->Add(CreateSeparatedButtonSizer(wxOK | wxCANCEL),
264 wxSizerFlags().Expand().Border());
265 SetSizerAndFit(sizerTop);
266
267 return true;
268 }
269
270 void 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
286 wxRearrangeList *wxRearrangeDialog::GetList() const
287 {
288 wxCHECK_MSG( m_ctrl, NULL, "the dialog must be created first" );
289
290 return m_ctrl->GetList();
291 }
292
293 wxArrayInt wxRearrangeDialog::GetOrder() const
294 {
295 wxCHECK_MSG( m_ctrl, wxArrayInt(), "the dialog must be created first" );
296
297 return m_ctrl->GetList()->GetCurrentOrder();
298 }
299
300 #endif // wxUSE_REARRANGECTRL