/*========================================================================= Program: bbtk Module: $RCSfile: bbtkWxConsole.cxx,v $ Language: C++ Date: $Date: 2008/01/22 15:02:00 $ Version: $Revision: 1.1.1.1 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*//** * \brief Short description in one line * * Long description which * can span multiple lines */ /** * \file * \brief */ /** * \class bbtk:: * \brief */ #ifdef _USE_WXWIDGETS_ #include #include "bbtkWxConsole.h" #include "bbtkWxBlackBox.h" namespace bbtk { WxConsole* WxConsole::mInstance = 0; // On Windows when compiling a dll, wx prevents the compilation // of the class wxStreamToTextRedirector (why ? it is a nightmare...) // The blocking symbol is wxHAS_TEXT_WINDOW_STREAM. // Note also that wxStreamToTextRedirector use the fact that wx is // compiled with the option WX_USE_STD_STREAMS in which case // wxTextCtrl inherits from std::streambuf and the redirection // can be done simply by setting the std::cout buffer to the // one of the wxTextCtrl. // So on windows, we have to redirect manually std::cout to mwxTextHistory. // Finally, on all systems we made our redirection class to redirect both to // the WxConsole and to printf in order to get a console trace when // the appli crashes (we could also imagine to log in a file...) // This is why we finally wrote our own redirection which is crossplatform // (drawback : not optimal on Unix platform; we could think of // a particular implementation...). //================================================================ /// Redirects std::cout to a wxTextCtrl and optionally to printf also class WxTextCtrlStreamRedirector : public std::streambuf { public: WxTextCtrlStreamRedirector(std::ostream& redirect, wxTextCtrl *text, const wxColour& colour = *wxBLACK, bool doprintf=true, int bufferSize=1000) : mText(text), mPrintf(doprintf), m_ostr(redirect), mColour(colour) { if (bufferSize) { char *ptr = new char[bufferSize]; setp(ptr, ptr + bufferSize); } else setp(0, 0); m_sbufOld = m_ostr.rdbuf(); m_ostr.rdbuf(this); } ~WxTextCtrlStreamRedirector() { sync(); delete[] pbase(); m_ostr.rdbuf(m_sbufOld); } virtual void writeString(const std::string &str) { const wxTextAttr& style = mText->GetDefaultStyle(); mText->SetDefaultStyle(mColour); mText->AppendText(std2wx(str)); mText->SetDefaultStyle(style); if (mPrintf) { printf("%s",str.c_str()); } } private: wxTextCtrl* mText; // bool mPrintf; // the stream we're redirecting std::ostream& m_ostr; // the old streambuf (before we changed it) std::streambuf *m_sbufOld; // wxColour mColour; private: int overflow(int c) { sync(); if (c != EOF) { if (pbase() == epptr()) { std::string temp; temp += char(c); writeString(temp); } else sputc(c); } return 0; } int sync() { if (pbase() != pptr()) { int len = int(pptr() - pbase()); std::string temp(pbase(), len); writeString(temp); setp(pbase(), epptr()); } return 0; } }; //================================================================ //================================================================ WxConsole::WxConsole( wxWindow *parent, wxString title, wxSize size) : wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size) { mInstance = this; mInterpreter = new bbtk::Interpreter(); mInterpreter->SetCommandLine(true); //============== // Menu wxInitAllImageHandlers(); wxMenu *menuFile = new wxMenu; menuFile->Append( ID_Menu_Quit, _T("&Quit") ); wxMenu *menuAbout = new wxMenu; menuAbout->Append( ID_Menu_About, _T("&About...") ); wxMenuBar *menuBar = new wxMenuBar; menuBar->Append( menuFile, _T("&File") ); menuBar->Append( menuAbout, _T("About") ); SetMenuBar( menuBar ); CreateStatusBar(); SetStatusText( _T("Welcome to bbi !") ); //============== // Notebook // wxFlexGridSizer *sizer = new wxFlexGridSizer(1); wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); mwxNotebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, 0); mwxPageCommand = new wxPanel(mwxNotebook,-1); mwxNotebook->AddPage( mwxPageCommand, _T("Command")); mwxPageHelp = new wxPanel(mwxNotebook,-1); mwxNotebook->AddPage( mwxPageHelp, _T("Help")); sizer->Add ( mwxNotebook, 1, wxGROW | wxALIGN_BOTTOM ); wxBoxSizer *cmdsizer = new wxBoxSizer(wxVERTICAL); mwxPageCommand->SetAutoLayout(true); mwxPageCommand->SetSizer(cmdsizer); cmdsizer->Fit(mwxPageCommand); cmdsizer->SetSizeHints(mwxPageCommand); wxBoxSizer *helpsizer = new wxBoxSizer(wxVERTICAL); mwxPageHelp->SetAutoLayout(true); mwxPageHelp->SetSizer(helpsizer); helpsizer->Fit(mwxPageHelp); helpsizer->SetSizeHints(mwxPageHelp); mwxHtmlWindow = new WxBrowser(mwxPageHelp, wxSize(1200,0)); // mwxHtmlWindow->SetSize(wxSize(800,1000)); helpsizer->Add (mwxHtmlWindow, wxALL | wxGROW ); //============== // Command page mwxTextHistory = new wxTextCtrl(mwxPageCommand,0,_T(""),wxDefaultPosition, wxDefaultSize, //HistorySize, wxTE_READONLY | wxTE_MULTILINE ); wxFont* FixedFont = new wxFont(10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false); mwxTextHistoryAttr = new wxTextAttr; mwxTextHistoryAttr->SetFont(*FixedFont); mwxTextCommand = new wxTextCtrl(mwxPageCommand,0,_T(""),wxDefaultPosition, wxDefaultSize,//CommandSize, wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB | wxWANTS_CHARS // | wxTAB_TRAVERSAL ); mwxTextCommandAttr = new wxTextAttr; mwxTextCommandAttr->SetFont(*FixedFont); mwxTextCommand->SetDefaultStyle(*mwxTextCommandAttr); mwxTextCommand->SetFocus(); cmdsizer->Add ( mwxTextHistory, 1, wxALL | wxGROW, 10); cmdsizer->Add ( mwxTextCommand, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxGROW, 10 ); // cmdsizer->AddGrowableCol(0); // cmdsizer->AddGrowableRow(0); // cmdsizer->AddGrowableRow(1); // cmdsizer->SetFlexibleDirection(wxBOTH); //============================= // Events connection // COMMAND // ENTER Connect( mwxTextCommand->GetId(), wxEVT_COMMAND_TEXT_ENTER, (wxObjectEventFunction)& WxConsole::OnCommandEnter ); Connect( mwxTextCommand->GetId(), wxEVT_CHAR, //wxEVT_COMMAND_TEXT_UPDATED, (wxObjectEventFunction)& WxConsole::OnCommandChar ); // MENU // Connect ( // Redirection of std::cout to mwxTextHistory and printf mRedirect_cout = new WxTextCtrlStreamRedirector(std::cout,mwxTextHistory,*wxBLACK,true); mRedirect_cerr = new WxTextCtrlStreamRedirector(std::cerr,mwxTextHistory,*wxGREEN,true); // Sets the console as the parent window of all bbtk windows WxBlackBox::bbGlobalSetTopWindow(this); // Layout SetSizer(sizer); SetAutoLayout(true); Layout(); } //================================================================ //================================================================ WxConsole::~WxConsole() { delete mRedirect_cout; delete mRedirect_cerr; } //================================================================ //================================================================ void WxConsole::OnCommandEnter(wxCommandEvent& event) { wxString line(mwxTextCommand->GetValue()); wxString s = _T("> ") + line + _T("\n"); mwxTextHistoryAttr->SetTextColour(*wxRED); mwxTextHistory->SetDefaultStyle(*mwxTextHistoryAttr); mwxTextHistory->AppendText(s); // send to standard console also printf("%s",wx2std(s).c_str()); mwxTextCommand->Clear(); mwxTextCommand->SetDefaultStyle(*mwxTextCommandAttr); mwxTextHistoryAttr->SetTextColour(*wxBLACK); mwxTextHistory->SetDefaultStyle(*mwxTextHistoryAttr); try { bool insideComment = false; mInterpreter->InterpretLine( wx2std(line), insideComment ); } catch (bbtk::QuitException) { Close(true); } catch (bbtk::Exception e) { e.Print(); } catch (std::exception& e) { std::cout << "* ERROR : "< commands; wxString sline( wx2std ( mwxTextCommand->GetValue() ) ); int ind = sline.size(); mInterpreter->FindCommandsWithPrefix( sline.c_str(),ind,commands); if (commands.size()==1) { std::string com = *commands.begin(); for (; indTextAppend( std2wx ( com[ind]) ); } mwxTextCommand->TextAppend(_T(" ")); } else if (commands.size()>1) { std::vector::iterator i; write(1,"\n",1); for (i=commands.begin();i!=commands.end();++i) { write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str())); PrintChar(' '); } write(STDOUT_FILENO,"\n> ",3); //for (int j=0;jGoTo(page)) { // std::cout << "ERROR html"<