]> git.saurik.com Git - wxWidgets.git/blobdiff - samples/dialogs/dialogs.cpp
Reduce size of virtual list before sending out delete notification, fixes #10966...
[wxWidgets.git] / samples / dialogs / dialogs.cpp
index 754945495698005dcb8730922d3558a3e0df30a7..b33421162209fd8843881580ece6038bd6d4055f 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "../sample.xpm"
 
+#include "wx/apptrait.h"
 #include "wx/datetime.h"
 #include "wx/image.h"
 #include "wx/bookctrl.h"
@@ -39,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
     #include "wx/fdrepdlg.h"
 #endif // wxUSE_FINDREPLDLG
 
-#if wxUSE_SPINCTRL
 #include "wx/spinctrl.h"
-#endif
-
 #include "wx/propdlg.h"
 
 #include "dialogs.h"
@@ -148,6 +148,10 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
     EVT_MENU(DIALOGS_MULTI_CHOICE,                  MyFrame::MultiChoice)
 #endif // wxUSE_CHOICEDLG
 
+#if wxUSE_REARRANGECTRL
+    EVT_MENU(DIALOGS_REARRANGE,                     MyFrame::Rearrange)
+#endif // wxUSE_REARRANGECTRL
+
 #if wxUSE_FILEDLG
     EVT_MENU(DIALOGS_FILE_OPEN,                     MyFrame::FileOpen)
     EVT_MENU(DIALOGS_FILE_OPEN2,                    MyFrame::FileOpen2)
@@ -172,7 +176,9 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
     EVT_MENU(DIALOGS_MODELESS,                      MyFrame::ModelessDlg)
     EVT_MENU(DIALOGS_CENTRE_SCREEN,                 MyFrame::DlgCenteredScreen)
     EVT_MENU(DIALOGS_CENTRE_PARENT,                 MyFrame::DlgCenteredParent)
+#if wxUSE_MINIFRAME
     EVT_MENU(DIALOGS_MINIFRAME,                     MyFrame::MiniFrame)
+#endif // wxUSE_MINIFRAME
     EVT_MENU(DIALOGS_ONTOP,                         MyFrame::DlgOnTop)
 
 #if wxUSE_STARTUP_TIPS
@@ -297,6 +303,10 @@ bool MyApp::OnInit()
         choices_menu->Append(DIALOGS_MULTI_CHOICE,  _T("M&ultiple choice\tCtrl-U"));
     #endif // wxUSE_CHOICEDLG
 
+    #if wxUSE_REARRANGECTRL
+        choices_menu->Append(DIALOGS_REARRANGE,  _T("&Rearrange dialog\tCtrl-R"));
+    #endif // wxUSE_REARRANGECTRL
+
     #if USE_COLOURDLG_GENERIC || USE_FONTDLG_GENERIC
         choices_menu->AppendSeparator();
     #endif // USE_COLOURDLG_GENERIC || USE_FONTDLG_GENERIC
@@ -413,7 +423,9 @@ bool MyApp::OnInit()
     dialogs_menu->AppendCheckItem(DIALOGS_MODELESS, _T("Mode&less dialog\tCtrl-Z"));
     dialogs_menu->Append(DIALOGS_CENTRE_SCREEN, _T("Centered on &screen\tShift-Ctrl-1"));
     dialogs_menu->Append(DIALOGS_CENTRE_PARENT, _T("Centered on &parent\tShift-Ctrl-2"));
+#if wxUSE_MINIFRAME
     dialogs_menu->Append(DIALOGS_MINIFRAME, _T("&Mini frame"));
+#endif // wxUSE_MINIFRAME
     dialogs_menu->Append(DIALOGS_ONTOP, _T("Dialog staying on &top"));
     menuDlg->Append(wxID_ANY, _T("&Generic dialogs"), dialogs_menu);
 
@@ -433,7 +445,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");
@@ -656,10 +668,10 @@ void MyFrame::MessageBox(wxCommandEvent& WXUNUSED(event))
 {
     wxMessageDialog dialog(this,
                            "This is a message box\n"
-                           "A long, long string to test out the message box "
-                           "layout properly.",
+                           "This is a long, long string to test out if the message box "
+                           "is laid out properly.",
                            "Message box text",
-                           wxVSCROLL | wxCENTER |
+                           wxCENTER |
                            wxNO_DEFAULT | wxYES_NO | wxCANCEL |
                            wxICON_INFORMATION);
 
@@ -797,28 +809,262 @@ void MyFrame::MultiChoice(wxCommandEvent& WXUNUSED(event) )
     };
 
     wxArrayInt selections;
-    size_t count = wxGetMultipleChoices(selections,
+    const int count = wxGetSelectedChoices(selections,
                                         _T("This is a small sample\n")
                                         _T("A multi-choice convenience dialog"),
                                         _T("Please select a value"),
                                         WXSIZEOF(choices), choices,
                                         this);
-    if ( count )
+    if ( count >= 0 )
     {
         wxString msg;
-        msg.Printf(wxT("You selected %u items:\n"), (unsigned)count);
-        for ( size_t n = 0; n < count; n++ )
+        if ( count == 0 )
         {
-            msg += wxString::Format(wxT("\t%u: %u (%s)\n"),
-                                    (unsigned)n, (unsigned)selections[n],
-                                    choices[selections[n]].c_str());
+            msg = wxT("You did not select any items");
+        }
+        else
+        {
+            msg.Printf(wxT("You selected %u items:\n"), (unsigned)count);
+            for ( int n = 0; n < count; n++ )
+            {
+                msg += wxString::Format(wxT("\t%u: %u (%s)\n"),
+                                        (unsigned)n, (unsigned)selections[n],
+                                        choices[selections[n]].c_str());
+            }
         }
         wxLogMessage(msg);
     }
-    //else: cancelled or nothing selected
+    //else: cancelled
 }
 #endif // wxUSE_CHOICEDLG
 
+#if wxUSE_REARRANGECTRL
+// 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);
+
+
+        // another customization not directly supported by the dialog: add a
+        // custom button
+        wxWindow * const btnOk = FindWindow(wxID_OK);
+        wxCHECK_RET( btnOk, "no Ok button?" );
+
+        wxSizer * const sizerBtns = btnOk->GetContainingSizer();
+        wxCHECK_RET( sizerBtns, "no buttons sizer?" );
+
+        sizerBtns->Add(new wxButton(this, wxID_RESET, "&Reset all"),
+                       wxSizerFlags().Border(wxLEFT));
+    }
+
+    // call this instead of ShowModal() to update order and labels array in
+    // case the dialog was not cancelled
+    bool Rearrange()
+    {
+        switch ( ShowModal() )
+        {
+            case wxID_CANCEL:
+                return false;
+
+            case wxID_OK:
+                m_order = GetOrder();
+                break;
+
+            case wxID_RESET:
+                // order already reset
+                break;
+        }
+
+        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]);
+    }
+
+    void OnReset(wxCommandEvent& WXUNUSED(event))
+    {
+        // in a real program we should probably ask if the user really wants to
+        // do this but here we just go ahead and reset all columns labels and
+        // their order without confirmation
+        const unsigned count = m_order.size();
+        for ( unsigned n = 0; n < count; n++ )
+        {
+            m_order[n] = n;
+            m_labels[n] = m_labelsOrig[n];
+        }
+
+        EndModal(wxID_RESET);
+    }
+
+    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()
+    wxDECLARE_NO_COPY_CLASS(MyRearrangeDialog);
+};
+
+BEGIN_EVENT_TABLE(MyRearrangeDialog, wxRearrangeDialog)
+    EVT_LISTBOX(wxID_ANY, MyRearrangeDialog::OnSelChange)
+
+    EVT_UPDATE_UI(wxID_APPLY, MyRearrangeDialog::OnUpdateUIRename)
+
+    EVT_TEXT_ENTER(wxID_ANY, MyRearrangeDialog::OnRename)
+    EVT_BUTTON(wxID_APPLY, MyRearrangeDialog::OnRename)
+    EVT_BUTTON(wxID_RESET, MyRearrangeDialog::OnReset)
+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);
+}
+#endif // wxUSE_REARRANGECTRL
+
 #if wxUSE_FILEDLG
 
 // panel with custom controls for file dialog
@@ -879,8 +1125,7 @@ void MyFrame::FileOpen(wxCommandEvent& WXUNUSED(event) )
     if (dialog.ShowModal() == wxID_OK)
     {
         wxString info;
-        MyExtraPanel *extra_panel
-            = static_cast<MyExtraPanel*>(dialog.GetExtraControl());
+        wxWindow * const extra = dialog.GetExtraControl();
         info.Printf(_T("Full file name: %s\n")
                     _T("Path: %s\n")
                     _T("Name: %s\n")
@@ -888,7 +1133,8 @@ void MyFrame::FileOpen(wxCommandEvent& WXUNUSED(event) )
                     dialog.GetPath().c_str(),
                     dialog.GetDirectory().c_str(),
                     dialog.GetFilename().c_str(),
-                    extra_panel->GetInfo().c_str());
+                    extra ? static_cast<MyExtraPanel*>(extra)->GetInfo()
+                          : wxString("None"));
         wxMessageDialog dialog2(this, info, _T("Selected file"));
         dialog2.ShowModal();
     }
@@ -1165,6 +1411,7 @@ void MyFrame::DlgCenteredParent(wxCommandEvent& WXUNUSED(event))
     dlg.ShowModal();
 }
 
+#if wxUSE_MINIFRAME
 void MyFrame::MiniFrame(wxCommandEvent& WXUNUSED(event))
 {
     wxFrame *frame = new wxMiniFrame(this, wxID_ANY, _T("Mini frame"),
@@ -1182,6 +1429,7 @@ void MyFrame::MiniFrame(wxCommandEvent& WXUNUSED(event))
     frame->CentreOnParent();
     frame->Show();
 }
+#endif // wxUSE_MINIFRAME
 
 void MyFrame::DlgOnTop(wxCommandEvent& WXUNUSED(event))
 {
@@ -1307,12 +1555,14 @@ TestDefaultActionDialog::TestDefaultActionDialog( wxWindow *parent ) :
 
     wxFlexGridSizer *grid_sizer = new wxFlexGridSizer( 2, 5, 5 );
 
+#if wxUSE_LISTBOX
     wxListBox *listbox = new wxListBox( this, ID_LISTBOX );
     listbox->Append( "String 1" );
     listbox->Append( "String 2" );
     listbox->Append( "String 3" );
     listbox->Append( "String 4" );
     grid_sizer->Add( listbox );
+#endif // wxUSE_LISTBOX
 
     grid_sizer->Add( new wxCheckBox( this, ID_CATCH_LISTBOX_DCLICK, "Catch DoubleClick from wxListBox" ), 0, wxALIGN_CENTRE_VERTICAL );
 
@@ -1491,7 +1741,7 @@ void MyFrame::ShowSimpleAboutDialog(wxCommandEvent& WXUNUSED(event))
     wxAboutDialogInfo info;
     InitAboutInfoMinimal(info);
 
-    wxAboutBox(info);
+    wxAboutBox(info, this);
 }
 
 void MyFrame::ShowFancyAboutDialog(wxCommandEvent& WXUNUSED(event))
@@ -1499,7 +1749,7 @@ void MyFrame::ShowFancyAboutDialog(wxCommandEvent& WXUNUSED(event))
     wxAboutDialogInfo info;
     InitAboutInfoWebsite(info);
 
-    wxAboutBox(info);
+    wxAboutBox(info, this);
 }
 
 void MyFrame::ShowFullAboutDialog(wxCommandEvent& WXUNUSED(event))
@@ -1507,16 +1757,16 @@ void MyFrame::ShowFullAboutDialog(wxCommandEvent& WXUNUSED(event))
     wxAboutDialogInfo info;
     InitAboutInfoAll(info);
 
-    wxAboutBox(info);
+    wxAboutBox(info, this);
 }
 
 // a trivial example of a custom dialog class
 class MyAboutDialog : public wxGenericAboutDialog
 {
 public:
-    MyAboutDialog(const wxAboutDialogInfo& info)
+    MyAboutDialog(const wxAboutDialogInfo& info, wxWindow* parent)
     {
-        Create(info);
+        Create(info, parent);
     }
 
     // add some custom controls
@@ -1533,7 +1783,7 @@ void MyFrame::ShowCustomAboutDialog(wxCommandEvent& WXUNUSED(event))
     wxAboutDialogInfo info;
     InitAboutInfoAll(info);
 
-    MyAboutDialog dlg(info);
+    MyAboutDialog dlg(info, this);
     dlg.ShowModal();
 }
 
@@ -1549,7 +1799,7 @@ void MyFrame::ShowBusyInfo(wxCommandEvent& WXUNUSED(event))
 
     for ( int i = 0; i < 18; i++ )
     {
-        //wxUsleep(100);
+        wxMilliSleep(100);
         wxTheApp->Yield();
     }
 
@@ -1748,14 +1998,15 @@ MyModalDialog::MyModalDialog(wxWindow *parent)
     m_btnModeless = new wxButton(this, wxID_ANY, _T("Mode&less dialog"));
     m_btnDelete = new wxButton(this, wxID_ANY, _T("&Delete button"));
 
-    wxButton *btnOk = new wxButton(this, wxID_CANCEL, _T("&Close"));
     sizerTop->Add(m_btnModal, 0, wxALIGN_CENTER | wxALL, 5);
     sizerTop->Add(m_btnModeless, 0, wxALIGN_CENTER | wxALL, 5);
     sizerTop->Add(m_btnDelete, 0, wxALIGN_CENTER | wxALL, 5);
-    sizerTop->Add(btnOk, 0, wxALIGN_CENTER | wxALL, 5);
+    sizerTop->Add(new wxButton(this, wxID_CLOSE), 0, wxALIGN_CENTER | wxALL, 5);
 
     SetSizerAndFit(sizerTop);
 
+    SetEscapeId(wxID_CLOSE);
+
     m_btnModal->SetFocus();
     m_btnModal->SetDefault();
 }
@@ -2207,12 +2458,14 @@ TestMessageBoxDialog::TestMessageBoxDialog(wxWindow *parent)
 
     // icon choice
     const wxString icons[] = {
-        "&Information", "&Question", "&Warning", "&Error"
+        "&None", "&Information", "&Question", "&Warning", "&Error"
     };
 
-    m_icons = new wxRadioBox(this, wxID_ANY, "&Icon:",
+    m_icons = new wxRadioBox(this, wxID_ANY, "&Icons",
                              wxDefaultPosition, wxDefaultSize,
                              WXSIZEOF(icons), icons);
+    // Make the 'Information' icon the default one:
+    m_icons->SetSelection(1);
     sizerTop->Add(m_icons, wxSizerFlags().Expand().Border());
 
 
@@ -2273,10 +2526,11 @@ void TestMessageBoxDialog::OnApply(wxCommandEvent& WXUNUSED(event))
 
     switch ( m_icons->GetSelection() )
     {
-        case 0: style |= wxICON_INFORMATION; break;
-        case 1: style |= wxICON_QUESTION; break;
-        case 2: style |= wxICON_WARNING; break;
-        case 3: style |= wxICON_ERROR; break;
+        case 0: style |= wxICON_NONE; break;
+        case 1: style |= wxICON_INFORMATION; break;
+        case 2: style |= wxICON_QUESTION; break;
+        case 3: style |= wxICON_WARNING; break;
+        case 4: style |= wxICON_ERROR; break;
     }
 
     if ( m_chkCentre->IsChecked() )
@@ -2327,3 +2581,31 @@ void TestMessageBoxDialog::OnClose(wxCommandEvent& WXUNUSED(event))
 }
 
 #endif // USE_SETTINGS_DIALOG
+
+#if wxUSE_LOG
+
+// ----------------------------------------------------------------------------
+// custom log target
+// ----------------------------------------------------------------------------
+
+class MyLogGui : public wxLogGui
+{
+private:
+    virtual void DoShowSingleLogMessage(const wxString& message,
+                                        const wxString& title,
+                                        int style)
+    {
+        wxMessageDialog dlg(NULL, message, title,
+                            wxOK | wxCANCEL | wxCANCEL_DEFAULT | style);
+        dlg.SetOKCancelLabels(wxID_COPY, wxID_OK);
+        dlg.SetExtendedMessage("Note that this is a custom log dialog.");
+        dlg.ShowModal();
+    }
+};
+
+wxLog *MyAppTraits::CreateLogTarget()
+{
+    return new MyLogGui;
+}
+
+#endif // wxUSE_LOG