]> git.saurik.com Git - wxWidgets.git/commitdiff
make wxRearrangeDialog more customizable and add an example of customizing it to...
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 31 Dec 2008 14:26:52 +0000 (14:26 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 31 Dec 2008 14:26:52 +0000 (14:26 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57690 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/rearrangectrl.h
interface/wx/rearrangectrl.h
samples/dialogs/dialogs.cpp
samples/dialogs/dialogs.h
src/common/rearrangectrl.cpp

index da1b0c1d69fed0d106600cb575655944992edc32..da809d5cbf97e0dad54d3a12a8f3aae0740edce8 100644 (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
index 9160b3efa7426da6e8dc1b09882702497ebbc708..4d5528251d1f438d02dbda0209a1a8455f71da10 100644 (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.
index 3b51eacee6f876b1b5d627ef45b468c3fb3c331f..d0c0c6a8d81cbbdb58da3840724078cf60f7038c 100644 (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
index ad8956acfb7041c8e5f0a6cc9411e146194790fa..19605e1a2c7189b57491c85bea6a28251e4e244e 100644 (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,
index cda19dd67fabf4f0d21968ce4d4e52c6f43e3b0c..33df826505db94dfdcb4bb55b06d5ca5fccd6bb4 100644 (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();
 }