/apps/wx-common/CMyRedirector.h

http://github.com/gamman/MRPT · C Header · 179 lines · 119 code · 19 blank · 41 comment · 14 complexity · 1c05c22cfe79482602f302105e31b965 MD5 · raw file

  1. /* +---------------------------------------------------------------------------+
  2. | The Mobile Robot Programming Toolkit (MRPT) C++ library |
  3. | |
  4. | http://www.mrpt.org/ |
  5. | |
  6. | Copyright (C) 2005-2011 University of Malaga |
  7. | |
  8. | This software was written by the Machine Perception and Intelligent |
  9. | Robotics Lab, University of Malaga (Spain). |
  10. | Contact: Jose-Luis Blanco <jlblanco@ctima.uma.es> |
  11. | |
  12. | This file is part of the MRPT project. |
  13. | |
  14. | MRPT is free software: you can redistribute it and/or modify |
  15. | it under the terms of the GNU General Public License as published by |
  16. | the Free Software Foundation, either version 3 of the License, or |
  17. | (at your option) any later version. |
  18. | |
  19. | MRPT is distributed in the hope that it will be useful, |
  20. | but WITHOUT ANY WARRANTY; without even the implied warranty of |
  21. | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
  22. | GNU General Public License for more details. |
  23. | |
  24. | You should have received a copy of the GNU General Public License |
  25. | along with MRPT. If not, see <http://www.gnu.org/licenses/>. |
  26. | |
  27. +---------------------------------------------------------------------------+ */
  28. #ifndef CMyRedirector_H
  29. #define CMyRedirector_H
  30. #include <wx/string.h>
  31. #include <wx/textctrl.h>
  32. #include <wx/app.h>
  33. #include <wx/thread.h>
  34. #include <streambuf>
  35. #include <iostream>
  36. /** This auxiliary class redirects the output sent to a streambuf to a wxTextCtrl object.
  37. * Uses code from http://www.devmaster.net/forums/showthread.php?t=7037
  38. * Jose Luis Blanco - Dec 2007
  39. * NOTE (10-Aug-2009): Added thread-safe support:
  40. * We cannot write in a wxTextCtrl from a thread different than the main wx one,
  41. * so if this object will be used by several threads, set "m_threadSafe" to true.
  42. * In this mode, the object will NEVER write the text to the text control, unless
  43. * the method "dumpNow()" is explicitly called FROM THE MAIN THREAD.
  44. */
  45. class CMyRedirector : public std::streambuf
  46. {
  47. protected:
  48. wxTextCtrl *m_txt;
  49. std::streambuf *sbOld;
  50. std::streambuf *sbOldErr;
  51. const bool m_yieldApplication;
  52. const bool m_also_cerr;
  53. const bool m_threadSafe;
  54. const bool m_also_to_cout_cerr;
  55. wxCriticalSection m_cs;
  56. std::string m_strbuf;
  57. public:
  58. CMyRedirector(
  59. wxTextCtrl *obj,
  60. bool yieldApplication = false,
  61. int bufferSize = 3000,
  62. bool also_cerr = false,
  63. bool threadSafe = false,
  64. bool also_to_cout_cerr = false ) : m_txt(obj), m_yieldApplication(yieldApplication), m_also_cerr(also_cerr),m_threadSafe(threadSafe), m_also_to_cout_cerr(also_to_cout_cerr)
  65. {
  66. if (bufferSize)
  67. {
  68. char *ptr = new char[bufferSize];
  69. setp(ptr, ptr + bufferSize);
  70. }
  71. else
  72. setp(0, 0);
  73. // Redirect:
  74. sbOld = std::cout.rdbuf();
  75. std::cout.rdbuf( this );
  76. if (m_also_cerr)
  77. {
  78. sbOldErr = std::cerr.rdbuf();
  79. std::cerr.rdbuf( this );
  80. }
  81. }
  82. virtual ~CMyRedirector()
  83. {
  84. sync();
  85. // Restore normal output:
  86. std::cout.rdbuf(sbOld);
  87. if (m_also_cerr)
  88. std::cerr.rdbuf(sbOldErr);
  89. delete[] pbase();
  90. }
  91. void flush()
  92. {
  93. sync();
  94. }
  95. virtual void writeString(const std::string &str)
  96. {
  97. if(!m_threadSafe)
  98. {
  99. #ifdef wxUSE_UNICODE
  100. *m_txt << wxString( str.c_str(), wxConvUTF8 );
  101. #else
  102. *m_txt << _U( str.c_str() );
  103. #endif
  104. }
  105. else
  106. { // Critical section is already adquired.
  107. m_strbuf+=str;
  108. }
  109. if (m_also_to_cout_cerr) ::printf("%s",str.c_str());
  110. if (m_yieldApplication) wxTheApp->Yield(); // Let the app. process messages
  111. }
  112. /** Writes all the stored strings to the text control (only for threadSafe mode).
  113. CALL THIS METHOD FROM THE MAIN THREAD!
  114. */
  115. void dumpNow()
  116. {
  117. wxCriticalSectionLocker lock(m_cs);
  118. if (!m_strbuf.empty())
  119. {
  120. if (m_also_to_cout_cerr) ::printf("%s",m_strbuf.c_str());
  121. #ifdef wxUSE_UNICODE
  122. *m_txt << wxString( m_strbuf.c_str(), wxConvUTF8 );
  123. #else
  124. *m_txt << _U( m_strbuf.c_str() );
  125. #endif
  126. m_strbuf.clear();
  127. }
  128. }
  129. private:
  130. int overflow(int c)
  131. {
  132. sync();
  133. if (c != EOF)
  134. {
  135. wxCriticalSectionLocker lock(m_cs);
  136. if (pbase() == epptr())
  137. {
  138. std::string temp;
  139. temp += char(c);
  140. writeString(temp);
  141. }
  142. else
  143. sputc(c);
  144. }
  145. return 0;
  146. }
  147. int sync()
  148. {
  149. wxCriticalSectionLocker lock(m_cs);
  150. if (pbase() != pptr())
  151. {
  152. int len = int(pptr() - pbase());
  153. std::string temp(pbase(), len);
  154. writeString(temp);
  155. setp(pbase(), epptr());
  156. }
  157. return 0;
  158. }
  159. };
  160. #endif