]> Creatis software - bbtk.git/blob - kernel/src/bbtkWxConsole.cxx
*** empty log message ***
[bbtk.git] / kernel / src / bbtkWxConsole.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   bbtk
4   Module:    $RCSfile: bbtkWxConsole.cxx,v $
5   Language:  C++
6   Date:      $Date: 2008/01/22 15:02:00 $
7   Version:   $Revision: 1.1 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*//**
18  * \brief Short description in one line
19  * 
20  * Long description which 
21  * can span multiple lines
22  */
23 /**
24  * \file 
25  * \brief 
26  */
27 /**
28  * \class bbtk::
29  * \brief 
30  */
31
32
33 #ifdef _USE_WXWIDGETS_
34
35 #include <iostream>     
36 #include "bbtkWxConsole.h"
37 #include "bbtkWxBlackBox.h"
38
39 namespace bbtk
40 {
41
42   WxConsole* WxConsole::mInstance = 0;
43 // On Windows when compiling a dll, wx prevents the compilation
44 // of the class wxStreamToTextRedirector (why ? it is a nightmare...)
45 // The blocking symbol is wxHAS_TEXT_WINDOW_STREAM.
46 // Note also that wxStreamToTextRedirector use the fact that wx is 
47 // compiled with the option WX_USE_STD_STREAMS in which case 
48 // wxTextCtrl inherits from std::streambuf and the redirection 
49 // can be done simply by setting the std::cout buffer to the 
50 // one of the wxTextCtrl. 
51 // So on windows, we have to redirect manually std::cout to mwxTextHistory.  
52 // Finally, on all systems we made our redirection class to redirect both to
53 // the WxConsole and to printf in order to get a console trace when 
54 // the appli crashes (we could also imagine to log in a file...)
55 // This is why we finally wrote our own redirection which is crossplatform
56 // (drawback : not optimal on Unix platform; we could think of 
57 // a particular implementation...).
58
59   //================================================================
60   /// Redirects std::cout to a wxTextCtrl and optionally to printf also
61   class WxTextCtrlStreamRedirector   : public std::streambuf
62   {       
63     
64   public:
65     
66  
67     WxTextCtrlStreamRedirector(std::ostream& redirect,
68                                  wxTextCtrl *text, 
69                                  const wxColour& colour = *wxBLACK,
70                                  bool doprintf=true,
71                                  int bufferSize=1000)
72       : mText(text),
73         mPrintf(doprintf),
74         m_ostr(redirect),
75         mColour(colour)
76     {
77       if (bufferSize)
78         {
79           char *ptr = new char[bufferSize];
80           setp(ptr, ptr + bufferSize);
81         }
82       else
83         setp(0, 0);
84       
85       m_sbufOld = m_ostr.rdbuf();
86       m_ostr.rdbuf(this);
87     }
88     
89     ~WxTextCtrlStreamRedirector()
90     {
91       sync();
92       delete[] pbase();
93       m_ostr.rdbuf(m_sbufOld);
94     }
95   
96    virtual void writeString(const std::string &str) 
97     {
98       const wxTextAttr& style = mText->GetDefaultStyle();
99       mText->SetDefaultStyle(mColour);
100       mText->AppendText(std2wx(str));
101       mText->SetDefaultStyle(style);
102      
103       if (mPrintf) 
104         {
105           printf("%s",str.c_str());
106         }
107     }
108     
109   
110   private:
111     wxTextCtrl* mText;
112     // 
113     bool mPrintf;
114     // the stream we're redirecting
115     std::ostream&   m_ostr;
116     // the old streambuf (before we changed it)
117     std::streambuf *m_sbufOld;
118     //
119     wxColour mColour;
120     
121   private:
122     int overflow(int c)
123     {
124       sync();
125       
126       if (c != EOF)
127         {
128           if (pbase() == epptr())
129             {
130               std::string temp;
131               temp += char(c);
132               writeString(temp);
133             }
134           else
135             sputc(c);
136         }
137       
138       return 0;
139     }
140     
141     int sync()
142     {
143       if (pbase() != pptr())
144         {
145           int len = int(pptr() - pbase());
146           std::string temp(pbase(), len);
147           writeString(temp);
148           setp(pbase(), epptr());
149         }
150       return 0;
151     }
152   };
153   //================================================================
154
155   
156   
157   //================================================================
158   WxConsole::WxConsole( wxWindow *parent, wxString title, wxSize size)
159     : wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size)
160   {     
161     mInstance = this;
162     mInterpreter = new bbtk::Interpreter();
163     mInterpreter->SetCommandLine(true);
164     //==============
165     // Menu
166     wxInitAllImageHandlers();
167     
168     wxMenu *menuFile = new wxMenu;
169     menuFile->Append( ID_Menu_Quit, _T("&Quit") );
170     
171     wxMenu *menuAbout = new wxMenu;
172     menuAbout->Append( ID_Menu_About, _T("&About...") );
173     
174     wxMenuBar *menuBar = new wxMenuBar;
175     menuBar->Append( menuFile, _T("&File") );
176     menuBar->Append( menuAbout, _T("About") );
177     
178     SetMenuBar( menuBar );
179     
180     CreateStatusBar();
181     SetStatusText( _T("Welcome to bbi !") );
182     
183     //==============
184     // Notebook
185     
186     //    wxFlexGridSizer *sizer = new wxFlexGridSizer(1);
187     wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
188     
189     mwxNotebook = new wxNotebook(this, -1, 
190                                  wxDefaultPosition, wxDefaultSize, 0);
191     mwxPageCommand = new wxPanel(mwxNotebook,-1);    
192     mwxNotebook->AddPage( mwxPageCommand, _T("Command"));
193
194     mwxPageHelp = new wxPanel(mwxNotebook,-1);    
195     mwxNotebook->AddPage( mwxPageHelp, _T("Help"));
196     
197     sizer->Add ( mwxNotebook, 1, wxGROW | wxALIGN_BOTTOM );
198     
199     wxBoxSizer *cmdsizer = new wxBoxSizer(wxVERTICAL);
200     
201     mwxPageCommand->SetAutoLayout(true);    
202     mwxPageCommand->SetSizer(cmdsizer);
203     cmdsizer->Fit(mwxPageCommand);
204     cmdsizer->SetSizeHints(mwxPageCommand);
205
206     wxBoxSizer *helpsizer = new wxBoxSizer(wxVERTICAL);
207     
208     mwxPageHelp->SetAutoLayout(true);    
209     mwxPageHelp->SetSizer(helpsizer);
210     helpsizer->Fit(mwxPageHelp);
211     helpsizer->SetSizeHints(mwxPageHelp);
212    
213     mwxHtmlWindow = new WxBrowser(mwxPageHelp,
214                                   wxSize(1200,0));
215
216     //    mwxHtmlWindow->SetSize(wxSize(800,1000));
217     helpsizer->Add (mwxHtmlWindow,  wxALL | wxGROW );
218   
219     //==============
220     // Command page 
221
222     mwxTextHistory = 
223       new wxTextCtrl(mwxPageCommand,0,_T(""),wxDefaultPosition,
224                      wxDefaultSize, //HistorySize,
225                      wxTE_READONLY |
226                      wxTE_MULTILINE );
227  
228     wxFont* FixedFont = new wxFont(10,
229                                    wxFONTFAMILY_MODERN,
230                                    wxFONTSTYLE_NORMAL,
231                                    wxFONTWEIGHT_NORMAL,
232                                    false);
233
234    mwxTextHistoryAttr = new wxTextAttr;
235    mwxTextHistoryAttr->SetFont(*FixedFont);
236    mwxTextCommand = 
237      new wxTextCtrl(mwxPageCommand,0,_T(""),wxDefaultPosition,
238                     wxDefaultSize,//CommandSize,
239                     
240                     wxTE_PROCESS_ENTER
241                         | 
242                     wxTE_PROCESS_TAB | wxWANTS_CHARS 
243 //                      |  wxTAB_TRAVERSAL
244                     );
245    
246
247     mwxTextCommandAttr = new wxTextAttr;   
248     mwxTextCommandAttr->SetFont(*FixedFont);
249     mwxTextCommand->SetDefaultStyle(*mwxTextCommandAttr);
250     mwxTextCommand->SetFocus();
251
252      
253     
254     cmdsizer->Add ( mwxTextHistory, 1, wxALL | wxGROW, 10);
255   
256     cmdsizer->Add ( mwxTextCommand, 0, wxLEFT | wxRIGHT | wxBOTTOM 
257                     | wxGROW, 10 );
258
259     //  cmdsizer->AddGrowableCol(0);
260     //  cmdsizer->AddGrowableRow(0);
261     // cmdsizer->AddGrowableRow(1);
262     //  cmdsizer->SetFlexibleDirection(wxBOTH);
263
264     //=============================
265     // Events connection
266     // COMMAND
267     // ENTER
268     Connect( mwxTextCommand->GetId(),
269              wxEVT_COMMAND_TEXT_ENTER,
270              (wxObjectEventFunction)& WxConsole::OnCommandEnter );
271     Connect( mwxTextCommand->GetId(),
272              wxEVT_CHAR,
273              //wxEVT_COMMAND_TEXT_UPDATED,
274              (wxObjectEventFunction)& WxConsole::OnCommandChar );
275     // MENU
276     //    Connect ( 
277
278     // Redirection of std::cout to mwxTextHistory and printf
279     mRedirect_cout = 
280       new WxTextCtrlStreamRedirector(std::cout,mwxTextHistory,*wxBLACK,true);
281     mRedirect_cerr = 
282       new WxTextCtrlStreamRedirector(std::cerr,mwxTextHistory,*wxGREEN,true); 
283         
284     // Sets the console as the parent window of all bbtk windows
285     WxBlackBox::bbGlobalSetTopWindow(this);
286
287
288     // Layout
289     SetSizer(sizer);
290     SetAutoLayout(true);
291     Layout();
292
293   }
294   //================================================================
295
296  //================================================================
297   WxConsole::~WxConsole()
298   {
299     delete mRedirect_cout;
300     delete mRedirect_cerr;
301   }
302   //================================================================
303
304   //================================================================
305   void WxConsole::OnCommandEnter(wxCommandEvent& event)
306   {
307     wxString line(mwxTextCommand->GetValue());
308     wxString s = _T("> ") + line + _T("\n");
309     mwxTextHistoryAttr->SetTextColour(*wxRED);
310     mwxTextHistory->SetDefaultStyle(*mwxTextHistoryAttr);
311     mwxTextHistory->AppendText(s);
312     // send to standard console also 
313     printf("%s",wx2std(s).c_str());
314     mwxTextCommand->Clear();
315     mwxTextCommand->SetDefaultStyle(*mwxTextCommandAttr);
316     mwxTextHistoryAttr->SetTextColour(*wxBLACK);
317     mwxTextHistory->SetDefaultStyle(*mwxTextHistoryAttr);
318
319     try 
320     {
321       bool insideComment = false;
322            mInterpreter->InterpretLine( wx2std(line), insideComment );
323     }
324     catch (bbtk::QuitException)
325     {
326            Close(true); 
327     }
328     catch (bbtk::Exception e) 
329     {
330            e.Print();
331     }
332     catch (std::exception& e) 
333     {
334            std::cout << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
335     }
336     catch (...)
337     {
338            std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"
339                           << std::endl;
340     }
341   }
342   //================================================================
343
344
345   //================================================================
346   void WxConsole::OnMenuQuit(wxCommandEvent& WXUNUSED(event))
347   {
348     Close(true);
349   }
350   //================================================================
351
352
353   //================================================================
354   void WxConsole::OnMenuAbout(wxCommandEvent& WXUNUSED(event))
355   {
356     
357     wxMessageBox(_T("  bbi\nThe Black Box Toolkit interpreter\n(c) CREATIS-LRMN 2007"),
358                  _T("About ..."), wxOK | wxICON_INFORMATION, 
359                  this);
360   }
361   //================================================================
362
363   //================================================================
364   void WxConsole::OnCommandChar(wxCommandEvent& event)
365   {
366     std::cout << "c";
367     /*
368     // Command completion  
369     std::vector<std::string> commands;
370     wxString sline( wx2std ( mwxTextCommand->GetValue() ) );
371     int ind = sline.size();
372     mInterpreter->FindCommandsWithPrefix( sline.c_str(),ind,commands);
373     if (commands.size()==1) 
374       {
375         std::string com = *commands.begin();
376         for (; ind<com.size(); ++ind) 
377           {
378             mwxTextCommand->TextAppend( std2wx ( com[ind]) ); 
379           }
380          mwxTextCommand->TextAppend(_T(" "));
381       }
382     else if (commands.size()>1) 
383       {
384         std::vector<std::string>::iterator i;
385         write(1,"\n",1);
386         for (i=commands.begin();i!=commands.end();++i) 
387           {
388             write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
389             PrintChar(' ');
390           }
391         write(STDOUT_FILENO,"\n> ",3);
392         //for (int j=0;j<ind;++j) 
393         //{
394         write(STDOUT_FILENO,line,ind); 
395         //  }
396       }
397     */
398   }
399   //================================================================
400
401   void WxConsole::ShowHtmlPage(std::string& page)
402   {
403     //  std::cout << "WxConsole::ShowHtmlPage('"<<page<<"')"<<std::endl;
404     if (!mwxHtmlWindow->GoTo(page)) 
405       {
406         //      std::cout << "ERROR html"<<std::endl;
407       }
408   } 
409
410   //================================================================  
411   BEGIN_EVENT_TABLE(WxConsole, wxFrame)
412     EVT_MENU(WxConsole::ID_Menu_Quit, WxConsole::OnMenuQuit)
413     EVT_MENU(WxConsole::ID_Menu_About, WxConsole::OnMenuAbout)
414     END_EVENT_TABLE()
415   //================================================================
416
417 } // namespace bbtk
418
419
420 #endif //_USE_WXWIDGETS_