~brian-sidebotham/wxwidgets-cmake/wxpython-2.9.4

« back to all changes in this revision

Viewing changes to src/common/rearrangectrl.cpp

  • Committer: Brian Sidebotham
  • Date: 2013-08-03 14:30:08 UTC
  • Revision ID: brian.sidebotham@gmail.com-20130803143008-c7806tkych1tp6fc
Initial import into Bazaar

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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: rearrangectrl.cpp 65844 2010-10-18 23:43:09Z VZ $
 
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
    // update the internally stored order
 
129
    wxSwap(m_order[pos1], m_order[pos2]);
 
130
 
 
131
 
 
132
    // and now also swap all the attributes of the items
 
133
 
 
134
    // first the label
 
135
    const wxString stringTmp = GetString(pos1);
 
136
    SetString(pos1, GetString(pos2));
 
137
    SetString(pos2, stringTmp);
 
138
 
 
139
    // then the checked state
 
140
    const bool checkedTmp = IsChecked(pos1);
 
141
    Check(pos1, IsChecked(pos2));
 
142
    Check(pos2, checkedTmp);
 
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
            {
 
153
                wxClientData * const dataTmp = DetachClientObject(pos1);
 
154
                SetClientObject(pos1, DetachClientObject(pos2));
 
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
    }
 
167
}
 
168
 
 
169
void wxRearrangeList::OnCheck(wxCommandEvent& event)
 
170
{
 
171
    // update the internal state to match the new item state
 
172
    const int n = event.GetInt();
 
173
 
 
174
    m_order[n] = ~m_order[n];
 
175
 
 
176
    wxASSERT_MSG( (m_order[n] >= 0) == IsChecked(n),
 
177
                  "discrepancy between internal state and GUI" );
 
178
}
 
179
 
 
180
// ============================================================================
 
181
// wxRearrangeCtrl implementation
 
182
// ============================================================================
 
183
 
 
184
BEGIN_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)
 
190
END_EVENT_TABLE()
 
191
 
 
192
void wxRearrangeCtrl::Init()
 
193
{
 
194
    m_list = NULL;
 
195
}
 
196
 
 
197
bool
 
198
wxRearrangeCtrl::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
 
 
234
void wxRearrangeCtrl::OnUpdateButtonUI(wxUpdateUIEvent& event)
 
235
{
 
236
    event.Enable( event.GetId() == wxID_UP ? m_list->CanMoveCurrentUp()
 
237
                                           : m_list->CanMoveCurrentDown() );
 
238
}
 
239
 
 
240
void 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
 
 
252
extern
 
253
WXDLLIMPEXP_DATA_CORE(const char) wxRearrangeDialogNameStr[] = "wxRearrangeDlg";
 
254
 
 
255
namespace
 
256
{
 
257
 
 
258
enum wxRearrangeDialogSizerPositions
 
259
{
 
260
    Pos_Label,
 
261
    Pos_Ctrl,
 
262
    Pos_Buttons,
 
263
    Pos_Max
 
264
};
 
265
 
 
266
} // anonymous namespace
 
267
 
 
268
bool 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
 
 
282
    m_ctrl = new wxRearrangeCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
 
283
                                 order, items);
 
284
 
 
285
    // notice that the items in this sizer should be inserted accordingly to
 
286
    // wxRearrangeDialogSizerPositions order
 
287
    wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL);
 
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
 
 
301
    sizerTop->Add(m_ctrl,
 
302
                  wxSizerFlags(1).Expand().Border());
 
303
    sizerTop->Add(CreateSeparatedButtonSizer(wxOK | wxCANCEL),
 
304
                  wxSizerFlags().Expand().Border());
 
305
    SetSizerAndFit(sizerTop);
 
306
 
 
307
    return true;
 
308
}
 
309
 
 
310
void 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
 
 
326
wxRearrangeList *wxRearrangeDialog::GetList() const
 
327
{
 
328
    wxCHECK_MSG( m_ctrl, NULL, "the dialog must be created first" );
 
329
 
 
330
    return m_ctrl->GetList();
 
331
}
 
332
 
 
333
wxArrayInt wxRearrangeDialog::GetOrder() const
 
334
{
 
335
    wxCHECK_MSG( m_ctrl, wxArrayInt(), "the dialog must be created first" );
 
336
 
 
337
    return m_ctrl->GetList()->GetCurrentOrder();
 
338
}
 
339
 
 
340
#endif // wxUSE_REARRANGECTRL