]> Creatis software - bbtk.git/blob - kernel/src/bbtkWxConsole.cxx
BUG HTML in windows + Cast float int
[bbtk.git] / kernel / src / bbtkWxConsole.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   bbtk
4   Module:    $RCSfile: bbtkWxConsole.cxx,v $
5   Language:  C++
6   Date:      $Date: 2008/02/21 09:37:23 $
7   Version:   $Revision: 1.5 $
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
190     mwxNotebook = new wxNotebook(this, -1, 
191                                  wxDefaultPosition, wxDefaultSize, 0);
192     mwxPageCommand = new wxPanel(mwxNotebook,-1);    
193     mwxNotebook->AddPage( mwxPageCommand, _T("Command"));
194
195     mwxPageHelp = new wxPanel(mwxNotebook,-1);    
196     mwxNotebook->AddPage( mwxPageHelp, _T("Help"));
197
198
199     sizer->Add ( mwxNotebook, 1, wxEXPAND /*| wxALIGN_BOTTOM*/ );
200     
201     wxBoxSizer *cmdsizer = new wxBoxSizer(wxVERTICAL);
202     
203     mwxPageCommand->SetAutoLayout(true);    
204     mwxPageCommand->SetSizer(cmdsizer);
205     cmdsizer->Fit(mwxPageCommand);
206     cmdsizer->SetSizeHints(mwxPageCommand);
207
208     wxBoxSizer *helpsizer = new wxBoxSizer(wxVERTICAL);
209     
210     mwxPageHelp->SetAutoLayout(true);    
211     mwxPageHelp->SetSizer(helpsizer);
212     helpsizer->Fit(mwxPageHelp);
213     helpsizer->SetSizeHints(mwxPageHelp);
214    
215     mwxHtmlWindow = new WxBrowser(mwxPageHelp,
216 //EED                             wxSize(1200,0));
217                                           wxSize(200,0));
218
219     //    mwxHtmlWindow->SetSize(wxSize(800,1000));
220     helpsizer->Add (mwxHtmlWindow,1,   wxGROW |wxLEFT | wxRIGHT | wxBOTTOM  );
221 //    helpsizer->Add ( new wxButton(mwxPageHelp,-1,"perro"), 0,  wxEXPAND  );
222   
223     //==============
224     // Command page 
225
226     mwxTextHistory = 
227       new wxTextCtrl(mwxPageCommand,
228                      ID_Text_History,
229                      _T(""),wxDefaultPosition,
230                      wxDefaultSize, //HistorySize,
231                      wxTE_READONLY |
232                      wxTE_MULTILINE );
233  
234     wxFont* FixedFont = new wxFont(10,
235                                    wxFONTFAMILY_MODERN,
236                                    wxFONTSTYLE_NORMAL,
237                                    wxFONTWEIGHT_NORMAL,
238                                    false);
239
240    mwxTextHistoryAttr = new wxTextAttr;
241    mwxTextHistoryAttr->SetFont(*FixedFont);
242    mwxTextCommand = 
243      new wxTextCtrl(mwxPageCommand,
244                     ID_Text_Command,
245                     _T(""),wxDefaultPosition,
246                     wxDefaultSize,
247                     wxTE_PROCESS_ENTER
248                     | wxTE_PROCESS_TAB 
249                     | wxWANTS_CHARS 
250                     //| wxTAB_TRAVERSAL
251                     );
252    
253
254     mwxTextCommandAttr = new wxTextAttr;   
255     mwxTextCommandAttr->SetFont(*FixedFont);
256     mwxTextCommand->SetDefaultStyle(*mwxTextCommandAttr);
257     mwxTextCommand->SetFocus();
258
259      
260     
261     cmdsizer->Add ( mwxTextHistory, 1, wxALL | wxGROW, 10);
262   
263     cmdsizer->Add ( mwxTextCommand, 0, wxLEFT | wxRIGHT | wxBOTTOM 
264                     | wxGROW, 10 );
265
266     //  cmdsizer->AddGrowableCol(0);
267     //  cmdsizer->AddGrowableRow(0);
268     // cmdsizer->AddGrowableRow(1);
269     //  cmdsizer->SetFlexibleDirection(wxBOTH);
270
271     //=============================
272     // Events connection
273     // COMMAND
274     // ENTER
275     /*
276     Connect( mwxTextCommand->GetId(),
277              wxEVT_COMMAND_TEXT_ENTER,
278              (wxObjectEventFunction)& WxConsole::OnCommandEnter );
279     Connect( mwxTextCommand->GetId(),
280              wxEVT_CHAR,
281              //wxEVT_COMMAND_TEXT_UPDATED,
282              (wxObjectEventFunction)& WxConsole::OnCommandChar );
283     */
284     // MENU
285     //    Connect ( 
286
287     // Redirection of std::cout to mwxTextHistory and printf
288     mRedirect_cout = 
289       new WxTextCtrlStreamRedirector(std::cout,mwxTextHistory,*wxBLACK,true);
290     mRedirect_cerr = 
291       new WxTextCtrlStreamRedirector(std::cerr,mwxTextHistory,*wxGREEN,true); 
292         
293     // Sets the console as the parent window of all bbtk windows
294     Wx::SetTopWindow(this);
295
296
297     // Layout
298     SetSizer(sizer);
299     SetAutoLayout(true);
300     Layout();
301
302   }
303   //================================================================
304
305  //================================================================
306   WxConsole::~WxConsole()
307   {
308     delete mRedirect_cout;
309     delete mRedirect_cerr;
310   }
311   //================================================================
312
313
314   //================================================================
315   void WxConsole::OnCommandEnter(wxCommandEvent& event)
316   {
317     wxString line(mwxTextCommand->GetValue());
318     wxString s = _T("> ") + line + _T("\n");
319     mwxTextHistoryAttr->SetTextColour(*wxRED);
320     mwxTextHistory->SetDefaultStyle(*mwxTextHistoryAttr);
321     mwxTextHistory->AppendText(s);
322     // send to standard console also 
323     printf("%s",wx2std(s).c_str());
324     mwxTextCommand->Clear();
325     mwxTextCommand->SetDefaultStyle(*mwxTextCommandAttr);
326     mwxTextHistoryAttr->SetTextColour(*wxBLACK);
327     mwxTextHistory->SetDefaultStyle(*mwxTextHistoryAttr);
328
329     try 
330     {
331       bool insideComment = false;
332            mInterpreter->InterpretLine( wx2std(line), insideComment );
333     }
334     catch (bbtk::QuitException)
335     {
336            Close(true); 
337     }
338     catch (bbtk::Exception e) 
339     {
340            e.Print();
341     }
342     catch (std::exception& e) 
343     {
344            std::cout << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
345     }
346     catch (...)
347     {
348            std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"
349                           << std::endl;
350     }
351   }
352   //================================================================
353
354
355   //================================================================
356   void WxConsole::OnMenuQuit(wxCommandEvent& WXUNUSED(event))
357   {
358     Close(true);
359   }
360   //================================================================
361
362
363   //================================================================
364   void WxConsole::OnMenuAbout(wxCommandEvent& WXUNUSED(event))
365   {
366     
367     wxMessageBox(_T("  bbi\nThe Black Box Toolkit interpreter\n(c) CREATIS-LRMN 2007"),
368                  _T("About ..."), wxOK | wxICON_INFORMATION, 
369                  this);
370   }
371   //================================================================
372
373   //================================================================
374   void WxConsole::OnCommandChar(wxCommandEvent& event)
375   {
376     std::cout << "c";
377     /*
378     // Command completion  
379     std::vector<std::string> commands;
380     wxString sline( wx2std ( mwxTextCommand->GetValue() ) );
381     int ind = sline.size();
382     mInterpreter->FindCommandsWithPrefix( sline.c_str(),ind,commands);
383     if (commands.size()==1) 
384       {
385         std::string com = *commands.begin();
386         for (; ind<com.size(); ++ind) 
387           {
388             mwxTextCommand->TextAppend( std2wx ( com[ind]) ); 
389           }
390          mwxTextCommand->TextAppend(_T(" "));
391       }
392     else if (commands.size()>1) 
393       {
394         std::vector<std::string>::iterator i;
395         write(1,"\n",1);
396         for (i=commands.begin();i!=commands.end();++i) 
397           {
398             write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
399             PrintChar(' ');
400           }
401         write(STDOUT_FILENO,"\n> ",3);
402         //for (int j=0;j<ind;++j) 
403         //{
404         write(STDOUT_FILENO,line,ind); 
405         //  }
406       }
407     */
408   }
409   //================================================================
410
411   void WxConsole::ShowHtmlPage(std::string& page)
412   {
413     //  std::cout << "WxConsole::ShowHtmlPage('"<<page<<"')"<<std::endl;
414     if (mwxHtmlWindow->GoTo(page)) 
415       {
416         mwxNotebook->ChangeSelection(1);
417       }
418     else 
419       {
420         //      std::cout << "ERROR html"<<std::endl;
421       }
422   } 
423
424   //================================================================  
425   BEGIN_EVENT_TABLE(WxConsole, wxFrame)
426     EVT_MENU(WxConsole::ID_Menu_Quit, WxConsole::OnMenuQuit)
427     EVT_MENU(WxConsole::ID_Menu_About, WxConsole::OnMenuAbout)
428     EVT_TEXT_ENTER(WxConsole::ID_Text_Command, WxConsole::OnCommandEnter)
429   //    EVT_CHAR(WxConsole::ID_Text_Command, WxConsole::OnCommandChar)
430     END_EVENT_TABLE()
431   //================================================================
432
433 } // namespace bbtk
434
435
436 #endif //_USE_WXWIDGETS_