make wxRearrangeDialog more customizable and add an example of customizing it to the dialogs sample

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57690 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2008-12-31 14:26:52 +00:00
parent 5b8b2c84f7
commit 5a5f305a0f
5 changed files with 317 additions and 15 deletions

View File

@@ -199,9 +199,21 @@ public:
const wxPoint& pos = wxDefaultPosition,
const wxString& name = wxRearrangeDialogNameStr);
// methods for the dialog customization
// add extra contents to the dialog below the wxRearrangeCtrl part: the
// given window (usually a wxPanel containing more control inside it) must
// have the dialog as its parent and will be inserted into it at the right
// place by this method
void AddExtraControls(wxWindow *win);
// return the wxRearrangeList control used by the dialog
wxRearrangeList *GetList() const;
// get the order of items after it was modified by the user
wxArrayInt GetOrder() const
{ return m_ctrl->GetList()->GetCurrentOrder(); }
wxArrayInt GetOrder() const;
private:
// common part of all ctors

View File

@@ -317,6 +317,52 @@ public:
const wxPoint& pos = wxDefaultPosition,
const wxString& name = wxRearrangeDialogNameStr);
/**
Customize the dialog by adding extra controls to it.
This function adds the given @a win to the dialog, putting it just
below the part occupied by wxRearrangeCtrl. It must be called after
creating the dialog and you will typically need to process the events
generated by the extra controls for them to do something useful.
For example:
@code
class MyRearrangeDialog : public wxRearrangeDialog
{
public:
MyRearrangeDialog(wxWindow *parent, ...)
: wxRearrangeDialog(parent, ...)
{
wxPanel *panel = new wxPanel(this);
wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(new wxStaticText(panel, wxID_ANY,
"Column width in pixels:"));
sizer->Add(new wxTextCtrl(panel, wxID_ANY, ""));
panel->SetSizer(sizer);
AddExtraControls(panel);
}
... code to update the text control with the currently selected
item width and to react to its changes omitted ...
};
@endcode
See also the complete example of a custom rearrange dialog in the
dialogs sample.
@param win
The window containing the extra controls. It must have this dialog
as its parent.
*/
void AddExtraControls(wxWindow *win);
/**
Return the list control used by the dialog.
@see wxRearrangeCtrl::GetList()
*/
wxRearrangeList *GetList() const;
/**
Return the array describing the order of items after it was modified by
the user.

View File

@@ -40,6 +40,8 @@
#include "wx/choicdlg.h"
#endif // wxUSE_CHOICEDLG
#include "wx/rearrangectrl.h"
#if wxUSE_STARTUP_TIPS
#include "wx/tipdlg.h"
#endif // wxUSE_STARTUP_TIPS
@@ -146,6 +148,8 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(DIALOGS_MULTI_CHOICE, MyFrame::MultiChoice)
#endif // wxUSE_CHOICEDLG
EVT_MENU(DIALOGS_REARRANGE, MyFrame::Rearrange)
#if wxUSE_FILEDLG
EVT_MENU(DIALOGS_FILE_OPEN, MyFrame::FileOpen)
EVT_MENU(DIALOGS_FILE_OPEN2, MyFrame::FileOpen2)
@@ -295,6 +299,8 @@ bool MyApp::OnInit()
choices_menu->Append(DIALOGS_MULTI_CHOICE, _T("M&ultiple choice\tCtrl-U"));
#endif // wxUSE_CHOICEDLG
choices_menu->Append(DIALOGS_REARRANGE, _T("&Rearrange dialog\tCtrl-R"));
#if USE_COLOURDLG_GENERIC || USE_FONTDLG_GENERIC
choices_menu->AppendSeparator();
#endif // USE_COLOURDLG_GENERIC || USE_FONTDLG_GENERIC
@@ -431,7 +437,7 @@ bool MyApp::OnInit()
#endif // USE_SETTINGS_DIALOG
wxMenu *menuNotif = new wxMenu;
menuNotif->Append(DIALOGS_REQUEST, _T("&Request user attention\tCtrl-R"));
menuNotif->Append(DIALOGS_REQUEST, _T("&Request user attention\tCtrl-Shift-R"));
#if wxUSE_NOTIFICATION_MESSAGE
menuNotif->Append(DIALOGS_NOTIFY_AUTO, "&Automatically hidden notification");
menuNotif->Append(DIALOGS_NOTIFY_SHOW, "&Show manual notification");
@@ -817,6 +823,192 @@ void MyFrame::MultiChoice(wxCommandEvent& WXUNUSED(event) )
}
#endif // wxUSE_CHOICEDLG
// custom rearrange dialog: it adds the possibility to rename an item to the
// base class functionality
class MyRearrangeDialog : public wxRearrangeDialog
{
public:
MyRearrangeDialog(wxWindow *parent,
wxArrayInt& order,
wxArrayString& labels,
wxArrayString& labelsOrig)
: wxRearrangeDialog
(
parent,
"Configure the columns shown:",
"wxRearrangeDialog example",
order,
labels
),
m_order(order),
m_labels(labels),
m_labelsOrig(labelsOrig)
{
m_sel = wxNOT_FOUND;
wxPanel * const panel = new wxPanel(this);
wxSizer * const sizer = new wxBoxSizer(wxHORIZONTAL);
m_labelOrig = new wxStaticText(panel, wxID_ANY, "");
sizer->Add(m_labelOrig, wxSizerFlags().Centre().Border(wxRIGHT));
m_text = new wxTextCtrl(panel, wxID_ANY, "",
wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER);
sizer->Add(m_text, wxSizerFlags().Centre().Border(wxRIGHT));
sizer->Add(new wxButton(panel, wxID_APPLY, "&Rename"),
wxSizerFlags().Centre());
panel->SetSizer(sizer);
// call this first to ensure that the controls have a reasonable best
// size before they're added
DoUpdateExtraControls(GetList()->GetSelection());
AddExtraControls(panel);
}
// call this instead of ShowModal() to update order and labels array in
// case the dialog was not cancelled
bool Rearrange()
{
if ( ShowModal() == wxID_CANCEL )
return false;
m_order = GetOrder();
return true;
}
private:
void OnSelChange(wxCommandEvent& event)
{
DoUpdateExtraControls(event.GetInt());
}
void OnUpdateUIRename(wxUpdateUIEvent& event)
{
event.Enable( CanRename() );
}
void OnRename(wxCommandEvent& WXUNUSED(event))
{
if ( !CanRename() )
return;
m_labels[m_sel] = m_text->GetValue();
GetList()->SetString(m_sel, m_labels[m_sel]);
}
bool CanRename() const
{
// only allow renaming if the user modified the currently selected item
// text (which presupposes that we do have a current item)
return m_sel != wxNOT_FOUND && m_text->GetValue() != m_labels[m_sel];
}
void DoUpdateExtraControls(int sel)
{
m_sel = sel;
if ( m_sel == wxNOT_FOUND )
{
m_labelOrig->SetLabel("<no selection>");
m_text->Clear();
m_text->Disable();
}
else // have valid item
{
m_labelOrig->SetLabelText(m_labelsOrig[m_sel]);
m_text->Enable();
m_text->SetValue(m_labels[m_sel]);
}
}
wxArrayInt& m_order;
wxArrayString& m_labels,
m_labelsOrig;
int m_sel;
wxStaticText *m_labelOrig;
wxTextCtrl *m_text;
DECLARE_EVENT_TABLE()
DECLARE_NO_COPY_CLASS(MyRearrangeDialog)
};
BEGIN_EVENT_TABLE(MyRearrangeDialog, wxRearrangeDialog)
EVT_LISTBOX(wxID_ANY, MyRearrangeDialog::OnSelChange)
EVT_UPDATE_UI(wxID_APPLY, MyRearrangeDialog::OnUpdateUIRename)
EVT_BUTTON(wxID_APPLY, MyRearrangeDialog::OnRename)
EVT_TEXT_ENTER(wxID_ANY, MyRearrangeDialog::OnRename)
END_EVENT_TABLE()
void MyFrame::Rearrange(wxCommandEvent& WXUNUSED(event))
{
// the arrays are static so that we preserve the items order between calls
// to this function
static wxArrayInt s_order;
static wxArrayString s_labels,
s_labelsOrig;
// initialize them on the first call
if ( s_labelsOrig.empty() )
{
static const struct ItemInfo
{
const char *label;
const char *labelOrig;
int order;
} items[] =
{
{ "File name", "Name", 0 },
{ "File type", "Ext", 1 },
{ "Size", "Size", 2 },
{ "Creation time", "Ctime", ~3 }, // negated so hidden
{ "Last accessed", "Atime", ~4 },
{ "Last modified", "Mtime", 5 },
};
s_order.reserve(WXSIZEOF(items));
s_labels.reserve(WXSIZEOF(items));
s_labelsOrig.reserve(WXSIZEOF(items));
for ( unsigned n = 0; n < WXSIZEOF(items); n++ )
{
const ItemInfo& item = items[n];
s_order.push_back(item.order);
s_labels.push_back(item.label);
s_labelsOrig.push_back(item.labelOrig);
}
}
MyRearrangeDialog dlg(this, s_order, s_labels, s_labelsOrig);
if ( !dlg.Rearrange() )
return;
wxString columns;
for ( unsigned n = 0; n < s_order.size(); n++ )
{
columns += wxString::Format("\n %u: ", n);
int idx = s_order[n];
if ( idx < 0 )
{
columns += "[hidden] ";
idx = ~idx;
}
columns += s_labels[idx];
if ( s_labels[idx] != s_labelsOrig[idx] )
{
columns += wxString::Format(" (original label: \"%s\")",
s_labelsOrig[idx]);
}
}
wxLogMessage("The columns order now is:%s", columns);
}
#if wxUSE_FILEDLG
// panel with custom controls for file dialog

View File

@@ -310,6 +310,8 @@ public:
void MultiChoice(wxCommandEvent& event);
#endif // wxUSE_CHOICEDLG
void Rearrange(wxCommandEvent& event);
#if wxUSE_TEXTDLG
void TextEntry(wxCommandEvent& event);
void PasswordEntry(wxCommandEvent& event);
@@ -448,6 +450,7 @@ enum
DIALOGS_MESSAGE_BOX_WXINFO,
DIALOGS_SINGLE_CHOICE,
DIALOGS_MULTI_CHOICE,
DIALOGS_REARRANGE,
DIALOGS_TEXT_ENTRY,
DIALOGS_PASSWORD_ENTRY,
DIALOGS_FILE_OPEN,

View File

@@ -221,27 +221,76 @@ void wxRearrangeCtrl::OnButton(wxCommandEvent& event)
extern
WXDLLIMPEXP_DATA_CORE(const char) wxRearrangeDialogNameStr[] = "wxRearrangeDlg";
wxRearrangeDialog::wxRearrangeDialog(wxWindow *parent,
const wxString& message,
const wxString& title,
const wxArrayInt& order,
const wxArrayString& items,
const wxPoint& pos,
const wxString& name)
: wxDialog(parent, wxID_ANY, title,
pos, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER,
name)
namespace
{
enum wxRearrangeDialogSizerPositions
{
Pos_Label,
Pos_Ctrl,
Pos_Buttons,
Pos_Max
};
} // anonymous namespace
bool wxRearrangeDialog::Create(wxWindow *parent,
const wxString& message,
const wxString& title,
const wxArrayInt& order,
const wxArrayString& items,
const wxPoint& pos,
const wxString& name)
{
if ( !wxDialog::Create(parent, wxID_ANY, title,
pos, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER,
name) )
return false;
m_ctrl = new wxRearrangeCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
order, items);
// notice that the items in this sizer should be inserted accordingly to
// wxRearrangeDialogSizerPositions order
wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL);
sizerTop->Add(new wxStaticText(this, wxID_ANY, message),
wxSizerFlags().DoubleBorder());
wxSizerFlags().Border());
sizerTop->Add(m_ctrl,
wxSizerFlags(1).Expand().Border());
sizerTop->Add(CreateSeparatedButtonSizer(wxOK | wxCANCEL),
wxSizerFlags().Expand().Border());
SetSizerAndFit(sizerTop);
return true;
}
void wxRearrangeDialog::AddExtraControls(wxWindow *win)
{
wxSizer * const sizer = GetSizer();
wxCHECK_RET( sizer, "the dialog must be created first" );
wxASSERT_MSG( sizer->GetChildren().GetCount() == Pos_Max,
"calling AddExtraControls() twice?" );
sizer->Insert(Pos_Buttons, win, wxSizerFlags().Expand().Border());
win->MoveAfterInTabOrder(m_ctrl);
// we need to update the initial/minimal window size
sizer->SetSizeHints(this);
}
wxRearrangeList *wxRearrangeDialog::GetList() const
{
wxCHECK_MSG( m_ctrl, NULL, "the dialog must be created first" );
return m_ctrl->GetList();
}
wxArrayInt wxRearrangeDialog::GetOrder() const
{
wxCHECK_MSG( m_ctrl, wxArrayInt(), "the dialog must be created first" );
return m_ctrl->GetList()->GetCurrentOrder();
}