X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e0a050e347b1ece07ad5f165ba1b1d16edbeae77..ad66316ffbcfd10a4fb448116371d27db3613d17:/src/generic/logg.cpp diff --git a/src/generic/logg.cpp b/src/generic/logg.cpp index 04656f2d6f..368cfe4d8b 100644 --- a/src/generic/logg.cpp +++ b/src/generic/logg.cpp @@ -48,12 +48,18 @@ #include "wx/statline.h" #include "wx/artprov.h" #include "wx/collpane.h" +#include "wx/arrstr.h" + +#if wxUSE_THREADS + #include "wx/thread.h" +#endif // wxUSE_THREADS #ifdef __WXMSW__ // for OutputDebugString() #include "wx/msw/private.h" #endif // Windows + #ifdef __WXPM__ #include #endif @@ -275,15 +281,9 @@ void wxLogGui::Flush() // do it right now to block any new calls to Flush() while we're here m_bHasMessages = false; - unsigned repeatCount = 0; - if ( wxLog::GetRepetitionCounting() ) - { - repeatCount = wxLog::DoLogNumberOfRepeats(); - } + const unsigned repeatCount = LogLastRepeatIfNeeded(); - wxString appName = wxTheApp->GetAppName(); - if ( !appName.empty() ) - appName[0u] = (wxChar)wxToupper(appName[0u]); + wxString appName = wxTheApp->GetAppDisplayName(); long style; wxString titleFormat; @@ -319,7 +319,11 @@ void wxLogGui::Flush() #if wxUSE_LOG_DIALOG if ( repeatCount > 0 ) - m_aMessages[nMsgCount-1] += wxString::Format(wxT(" (%s)"), m_aMessages[nMsgCount-2].c_str()); + { + m_aMessages[nMsgCount - 1] + << " (" << m_aMessages[nMsgCount - 2] << ")"; + } + wxLogDialog dlg(NULL, m_aMessages, m_aSeverity, m_aTimes, title, style); @@ -469,7 +473,7 @@ class wxLogFrame : public wxFrame { public: // ctor & dtor - wxLogFrame(wxWindow *pParent, wxLogWindow *log, const wxChar *szTitle); + wxLogFrame(wxWindow *pParent, wxLogWindow *log, const wxString& szTitle); virtual ~wxLogFrame(); // menu callbacks @@ -480,8 +484,14 @@ public: #endif // wxUSE_FILE void OnClear(wxCommandEvent& event); - // accessors - wxTextCtrl *TextCtrl() const { return m_pTextCtrl; } + // this function is safe to call from any thread (notice that it should be + // also called from the main thread to ensure that the messages logged from + // it appear in correct order with the messages from the other threads) + void AddLogMessage(const wxString& message); + + // actually append the messages logged from secondary threads to the text + // control during idle time in the main thread + virtual void OnInternalIdle(); private: // use standard ids for our commands! @@ -495,9 +505,24 @@ private: // common part of OnClose() and OnCloseWindow() void DoClose(); + // do show the message in the text control + void DoShowLogMessage(const wxString& message) + { + m_pTextCtrl->AppendText(message); + } + wxTextCtrl *m_pTextCtrl; wxLogWindow *m_log; + // queue of messages logged from other threads which need to be displayed + wxArrayString m_pendingMessages; + +#if wxUSE_THREADS + // critical section to protect access to m_pendingMessages + wxCriticalSection m_critSection; +#endif // wxUSE_THREADS + + DECLARE_EVENT_TABLE() DECLARE_NO_COPY_CLASS(wxLogFrame) }; @@ -513,7 +538,7 @@ BEGIN_EVENT_TABLE(wxLogFrame, wxFrame) EVT_CLOSE(wxLogFrame::OnCloseWindow) END_EVENT_TABLE() -wxLogFrame::wxLogFrame(wxWindow *pParent, wxLogWindow *log, const wxChar *szTitle) +wxLogFrame::wxLogFrame(wxWindow *pParent, wxLogWindow *log, const wxString& szTitle) : wxFrame(pParent, wxID_ANY, szTitle) { m_log = log; @@ -612,6 +637,43 @@ void wxLogFrame::OnClear(wxCommandEvent& WXUNUSED(event)) m_pTextCtrl->Clear(); } +void wxLogFrame::OnInternalIdle() +{ + { + wxCRIT_SECT_LOCKER(locker, m_critSection); + + const size_t count = m_pendingMessages.size(); + for ( size_t n = 0; n < count; n++ ) + { + DoShowLogMessage(m_pendingMessages[n]); + } + + m_pendingMessages.clear(); + } // release m_critSection + + wxFrame::OnInternalIdle(); +} + +void wxLogFrame::AddLogMessage(const wxString& message) +{ + wxCRIT_SECT_LOCKER(locker, m_critSection); + +#if wxUSE_THREADS + if ( !wxThread::IsMain() || !m_pendingMessages.empty() ) + { + // message needs to be queued for later showing + m_pendingMessages.Add(message); + + wxWakeUpIdle(); + } + else // we are the main thread and no messages are queued, so we can + // log the message directly +#endif // wxUSE_THREADS + { + DoShowLogMessage(message); + } +} + wxLogFrame::~wxLogFrame() { m_log->OnFrameDelete(this); @@ -621,7 +683,7 @@ wxLogFrame::~wxLogFrame() // ----------- wxLogWindow::wxLogWindow(wxWindow *pParent, - const wxChar *szTitle, + const wxString& szTitle, bool bShow, bool bDoPass) { @@ -672,22 +734,12 @@ void wxLogWindow::DoLog(wxLogLevel level, const wxString& szString, time_t t) void wxLogWindow::DoLogString(const wxString& szString, time_t WXUNUSED(t)) { - // put the text into our window - wxTextCtrl *pText = m_pLogFrame->TextCtrl(); - - // remove selection (WriteText is in fact ReplaceSelection) -#ifdef __WXMSW__ - wxTextPos nLen = pText->GetLastPosition(); - pText->SetSelection(nLen, nLen); -#endif // Windows - wxString msg; + TimeStamp(&msg); msg << szString << wxT('\n'); - pText->AppendText(msg); - - // TODO ensure that the line can be seen + m_pLogFrame->AddLogMessage(msg); } wxFrame *wxLogWindow::GetFrame() const @@ -795,38 +847,17 @@ wxLogDialog::wxLogDialog(wxWindow *parent, wxBoxSizer *sizerTop = new wxBoxSizer(wxVERTICAL); wxBoxSizer *sizerAll = new wxBoxSizer(isPda ? wxVERTICAL : wxHORIZONTAL); - wxBitmap bitmap; - switch ( style & wxICON_MASK ) + if (!isPda) { - case wxICON_ERROR: - bitmap = wxArtProvider::GetBitmap(wxART_ERROR, wxART_MESSAGE_BOX); -#ifdef __WXPM__ - bitmap.SetId(wxICON_SMALL_ERROR); -#endif - break; - - case wxICON_INFORMATION: - bitmap = wxArtProvider::GetBitmap(wxART_INFORMATION, wxART_MESSAGE_BOX); -#ifdef __WXPM__ - bitmap.SetId(wxICON_SMALL_INFO); -#endif - break; - - case wxICON_WARNING: - bitmap = wxArtProvider::GetBitmap(wxART_WARNING, wxART_MESSAGE_BOX); -#ifdef __WXPM__ - bitmap.SetId(wxICON_SMALL_WARNING); -#endif - break; - - default: - wxFAIL_MSG(_T("incorrect log style")); + wxStaticBitmap *icon = new wxStaticBitmap + ( + this, + wxID_ANY, + wxArtProvider::GetMessageBoxIcon(style) + ); + sizerAll->Add(icon, 0, wxALIGN_CENTRE_VERTICAL); } - if (!isPda) - sizerAll->Add(new wxStaticBitmap(this, wxID_ANY, bitmap), 0, - wxALIGN_CENTRE_VERTICAL); - // create the text sizer with a minimal size so that we are sure it won't be too small wxString message = EllipsizeString(messages.Last()); wxSizer *szText = CreateTextSizer(message); @@ -1021,7 +1052,7 @@ void wxLogDialog::OnListItemActivated(wxListEvent& event) // as there's a 260 chars limit on the items inside a wxListCtrl in wxMSW. wxString str = m_messages[event.GetIndex()]; - // wxMessageBox will nicely handle the '\n' in the string (if any) + // wxMessageBox will nicely handle the '\n' in the string (if any) // and supports long strings wxMessageBox(str, wxT("Log message"), wxOK, this); } @@ -1103,7 +1134,7 @@ static int OpenLogFile(wxFile& file, wxString *pFilename, wxWindow *parent) // open file // --------- - bool bOk wxDUMMY_INITIALIZE(false); + bool bOk = false; if ( wxFile::Exists(filename) ) { bool bAppend = false; wxString strMsg;