5 * Nicolas Boichat, July 2004
10 Copyright (C) 2004 Kern Sibbald and John Walker
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 as published by the Free Software Foundation; either version 2
15 of the License, or (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #include "wxbmainframe.h" // class's header file
29 #include "wxbrestorepanel.h"
31 #include "wxbconfigfileeditor.h"
35 #include "wxwin16x16.xpm"
37 #include <wx/arrimpl.cpp>
39 #include <wx/stattext.h>
40 #include <wx/statline.h>
41 #include <wx/config.h>
43 #include <wx/filename.h>
45 #undef Yield /* MinGW defines Yield */
47 // ----------------------------------------------------------------------------
48 // event tables and other macros for wxWindows
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 // ----------------------------------------------------------------------------
55 // IDs for the controls and the menu commands
61 // it is important for the id corresponding to the "About" command to have
62 // this standard value as otherwise it won't be handled properly under Mac
63 // (where it is special and put into the "Apple" menu)
64 Minimal_About = wxID_ABOUT,
76 * wxbTHREAD_EVENT declaration, used by csprint
78 BEGIN_DECLARE_EVENT_TYPES()
79 DECLARE_EVENT_TYPE(wxbTHREAD_EVENT, 1)
80 END_DECLARE_EVENT_TYPES()
82 DEFINE_EVENT_TYPE(wxbTHREAD_EVENT)
84 typedef void (wxEvtHandler::*wxThreadEventFunction)(wxbThreadEvent&);
86 #define EVT_THREAD_EVENT(id, fn) \
87 DECLARE_EVENT_TABLE_ENTRY( \
88 wxbTHREAD_EVENT, id, wxID_ANY, \
89 (wxObjectEventFunction)(wxEventFunction)(wxThreadEventFunction)&fn, \
93 // the event tables connect the wxWindows events with the functions (event
94 // handlers) which process them. It can be also done at run-time, but for the
95 // simple menu events like this the static method is much simpler.
96 BEGIN_EVENT_TABLE(wxbMainFrame, wxFrame)
97 EVT_MENU(Minimal_Quit, wxbMainFrame::OnQuit)
98 EVT_MENU(Minimal_About, wxbMainFrame::OnAbout)
99 EVT_MENU(ChangeConfigFile, wxbMainFrame::OnChangeConfig)
100 EVT_MENU(EditConfigFile, wxbMainFrame::OnEditConfig)
101 EVT_MENU(MenuConnect, wxbMainFrame::OnConnect)
102 EVT_MENU(MenuDisconnect, wxbMainFrame::OnDisconnect)
103 EVT_TEXT_ENTER(TypeText, wxbMainFrame::OnEnter)
104 EVT_THREAD_EVENT(Thread, wxbMainFrame::OnPrint)
105 EVT_BUTTON(SendButton, wxbMainFrame::OnEnter)
108 // ----------------------------------------------------------------------------
110 // ----------------------------------------------------------------------------
113 * wxbThreadEvent constructor
115 wxbThreadEvent::wxbThreadEvent(int id): wxEvent(id, wxbTHREAD_EVENT) {
116 m_eventObject = NULL;
120 * wxbThreadEvent destructor
122 wxbThreadEvent::~wxbThreadEvent()
124 if (m_eventObject != NULL) {
125 delete m_eventObject;
130 * wxbThreadEvent copy constructor
132 wxbThreadEvent::wxbThreadEvent(const wxbThreadEvent& te)
134 this->m_eventType = te.m_eventType;
135 this->m_id = te.m_id;
136 if (te.m_eventObject != NULL) {
137 this->m_eventObject = new wxbPrintObject(*((wxbPrintObject*)te.m_eventObject));
140 this->m_eventObject = NULL;
142 this->m_skipped = te.m_skipped;
143 this->m_timeStamp = te.m_timeStamp;
147 * Must be implemented (abstract in wxEvent)
149 wxEvent* wxbThreadEvent::Clone() const
151 return new wxbThreadEvent(*this);
155 * Gets the wxbPrintObject attached to this event, containing data sent by director
157 wxbPrintObject* wxbThreadEvent::GetEventPrintObject()
159 return (wxbPrintObject*)m_eventObject;
163 * Sets the wxbPrintObject attached to this event
165 void wxbThreadEvent::SetEventPrintObject(wxbPrintObject* object)
167 m_eventObject = (wxObject*)object;
170 // ----------------------------------------------------------------------------
172 // ----------------------------------------------------------------------------
174 wxbMainFrame *wxbMainFrame::frame = NULL;
177 * Singleton constructor
179 wxbMainFrame* wxbMainFrame::CreateInstance(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
181 frame = new wxbMainFrame(title, pos, size, style);
186 * Returns singleton instance
188 wxbMainFrame* wxbMainFrame::GetInstance()
196 wxbMainFrame::~wxbMainFrame()
198 wxConfig::Get()->Write(wxT("/Position/X"), (long)GetPosition().x);
199 wxConfig::Get()->Write(wxT("/Position/Y"), (long)GetPosition().y);
200 wxConfig::Get()->Write(wxT("/Size/Width"), (long)GetSize().GetWidth());
201 wxConfig::Get()->Write(wxT("/Size/Height"), (long)GetSize().GetHeight());
203 if (ct != NULL) { // && (!ct->IsRunning())
210 * Private constructor
212 wxbMainFrame::wxbMainFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
213 : wxFrame(NULL, -1, title, pos, size, style)
215 lockedbyconsole = false;
221 // set the frame icon
222 SetIcon(wxIcon(wxwin16x16_xpm));
226 menuFile = new wxMenu;
228 // the "About" item should be in the help menu
229 wxMenu *helpMenu = new wxMenu;
230 helpMenu->Append(Minimal_About, _T("&About...\tF1"), _T("Show about dialog"));
232 menuFile->Append(MenuConnect, _T("Connect"), _T("Connect to the director"));
233 menuFile->Append(MenuDisconnect, _T("Disconnect"), _T("Disconnect of the director"));
234 menuFile->AppendSeparator();
235 menuFile->Append(ChangeConfigFile, _T("Change of configuration file"), _T("Change your default configuration file"));
236 menuFile->Append(EditConfigFile, _T("Edit your configuration file"), _T("Edit your configuration file"));
237 menuFile->AppendSeparator();
238 menuFile->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
240 // now append the freshly created menu to the menu bar...
241 wxMenuBar *menuBar = new wxMenuBar();
242 menuBar->Append(menuFile, _T("&File"));
243 menuBar->Append(helpMenu, _T("&Help"));
245 // ... and attach this menu bar to the frame
247 #endif // wxUSE_MENUS
251 SetStatusText(wxString(wxT("Welcome to bacula wx-console ")) << wxString(wxT(VERSION)) << wxString (wxT(" (")) << wxString(wxT(BDATE)) << wxString(wxT(")!\n")));
253 wxPanel* global = new wxPanel(this, -1);
255 notebook = new wxNotebook(global, -1);
259 wxPanel* consolePanel = new wxPanel(notebook, -1);
260 notebook->AddPage(consolePanel, wxT("Console"));
262 consoleCtrl = new wxTextCtrl(consolePanel,-1,wxT(""),wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH);
263 wxFont font(10, wxMODERN, wxNORMAL, wxNORMAL);
264 #if defined __WXGTK12__ && !defined __WXGTK20__ // Fix for "chinese" fonts under gtk+ 1.2
265 font.SetDefaultEncoding(wxFONTENCODING_ISO8859_1);
266 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
267 Print(wxT("Warning : Unicode is disabled because you are using wxWidgets for GTK+ 1.2.\n"), CS_DEBUG);
269 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
270 #if (wxUSE_UNICODE == 0) && __WXGTK20__
271 Print(wxT("Warning : There is a problem with wxWidgets for GTK+ 2.0 without Unicode support when handling non-ASCII filenames: Every non-ASCII character in such filenames will be replaced by an interrogation mark.\nIf this behaviour disturbs you, please build wx-console against a Unicode version of wxWidgets for GTK+ 2.0.\n---\n"), CS_DEBUG);
275 helpCtrl = new wxStaticText(consolePanel, -1, wxT("Type your command below:"));
277 wxFlexGridSizer *consoleSizer = new wxFlexGridSizer(4, 1, 0, 0);
278 consoleSizer->AddGrowableCol(0);
279 consoleSizer->AddGrowableRow(0);
281 typeCtrl = new wxbHistoryTextCtrl(helpCtrl, consolePanel,TypeText,wxT(""),wxDefaultPosition,wxSize(200,20));
282 sendButton = new wxButton(consolePanel, SendButton, wxT("Send"));
284 wxFlexGridSizer *typeSizer = new wxFlexGridSizer(1, 2, 0, 0);
285 typeSizer->AddGrowableCol(0);
286 typeSizer->AddGrowableRow(0);
288 //typeSizer->Add(new wxStaticText(consolePanel, -1, "Command: "), 0, wxALIGN_CENTER | wxALL, 0);
289 typeSizer->Add(typeCtrl, 1, wxEXPAND | wxALL, 0);
290 typeSizer->Add(sendButton, 1, wxEXPAND | wxLEFT, 5);
292 consoleSizer->Add(consoleCtrl, 1, wxEXPAND | wxALL, 0);
293 consoleSizer->Add(new wxStaticLine(consolePanel, -1), 0, wxEXPAND | wxALL, 0);
294 consoleSizer->Add(helpCtrl, 1, wxEXPAND | wxALL, 2);
295 consoleSizer->Add(typeSizer, 0, wxEXPAND | wxALL, 2);
297 consolePanel->SetAutoLayout( TRUE );
298 consolePanel->SetSizer( consoleSizer );
299 consoleSizer->SetSizeHints( consolePanel );
301 // Creates the list of panels which are included in notebook, and that need to receive director information
303 panels = new wxbPanel* [2];
304 panels[0] = new wxbRestorePanel(notebook);
307 for (int i = 0; panels[i] != NULL; i++) {
308 notebook->AddPage(panels[i], panels[i]->GetTitle());
311 wxBoxSizer* globalSizer = new wxBoxSizer(wxHORIZONTAL);
313 #if wxCHECK_VERSION(2, 6, 0)
314 globalSizer->Add(notebook, 1, wxEXPAND, 0);
316 globalSizer->Add(new wxNotebookSizer(notebook), 1, wxEXPAND, 0);
319 global->SetSizer( globalSizer );
320 globalSizer->SetSizeHints( global );
322 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
324 sizer->Add(global, 1, wxEXPAND | wxALL, 0);
327 sizer->SetSizeHints( this );
329 EnableConsole(false);
331 consoleBuffer = wxT("");
333 configfile = wxT("");
337 * Starts the thread interacting with the director
338 * If config is not empty, uses this config file.
340 void wxbMainFrame::StartConsoleThread(const wxString& config) {
341 menuFile->Enable(MenuConnect, false);
342 menuFile->Enable(MenuDisconnect, false);
343 menuFile->Enable(ChangeConfigFile, false);
344 menuFile->Enable(EditConfigFile, false);
351 if (promptparser == NULL) {
352 promptparser = new wxbPromptParser();
355 if (config == wxT("")) {
356 configfile = wxT("");
358 if (((wxTheApp->argc % 2) != 1)) {
359 Print(wxT("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
360 Print(wxT("Usage: wx-console [-c configfile] [-w tmp]\n"), CS_DEBUG);
363 for (int c = 1; c < wxTheApp->argc; c += 2) {
364 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-c"))) {
365 configfile = wxTheApp->argv[c+1];
367 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-w"))) {
368 console_thread::SetWorkingDirectory(wxTheApp->argv[c+1]);
370 if (wxTheApp->argv[c][0] != '-') {
371 Print(wxT("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
372 Print(wxT("Usage: wx-console [-c configfile] [-w tmp]\n"), CS_DEBUG);
378 if (configfile == wxT("")) {
379 wxConfig::Set(new wxConfig(wxT("wx-console"), wxT("bacula")));
380 if (!wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile)) {
382 wxFileName filename(::wxGetHomeDir());
383 filename.MakeAbsolute();
384 configfile = filename.GetLongPath();
385 if (configfile.Last() != '/')
387 configfile += "Library/Preferences/org.bacula.wxconsole.conf";
389 wxFileName filename(::wxGetCwd(), wxT("wx-console.conf"));
390 filename.MakeAbsolute();
391 configfile = filename.GetLongPath();
393 configfile.Replace(wxT("\\"), wxT("/"));
396 wxConfig::Get()->Write(wxT("/ConfigFile"), configfile);
398 int answer = wxMessageBox(
399 wxString(wxT("It seems that it is the first time you run wx-console.\n")) <<
400 wxString(wxT("This file (")) << configfile << wxString(wxT(") has been choosen as default configuration file.\n")) <<
401 wxString(wxT("Do you want to edit it? (if you click No you will have to select another file)")),
403 wxYES_NO | wxICON_QUESTION, this);
404 if (answer == wxYES) {
405 wxbConfigFileEditor(this, configfile).ShowModal();
414 wxString err = console_thread::LoadConfig(configfile);
416 while (err != wxT("")) {
417 int answer = wxMessageBox(
418 wxString(wxT("Unable to read ")) << configfile << wxString(wxT("\n")) <<
419 err << wxString(wxT("\nDo you want to choose another one? (Press no to edit this file)")),
420 wxT("Unable to read configuration file"),
421 wxYES_NO | wxCANCEL | wxICON_ERROR, this);
422 if (answer == wxNO) {
423 wxbConfigFileEditor(this, configfile).ShowModal();
424 err = console_thread::LoadConfig(configfile);
426 else if (answer == wxCANCEL) {
431 else { // (answer == wxYES)
432 configfile = wxFileSelector(wxT("Please choose a configuration file to use"));
433 if ( !configfile.empty() ) {
434 err = console_thread::LoadConfig(configfile);
443 if ((err == wxT("")) && (config == wxT(""))) {
444 answer = wxMessageBox(
445 wxT("This configuration file has been successfully read, use it as default?"),
446 wxT("Configuration file read successfully"),
447 wxYES_NO | wxICON_QUESTION, this);
448 if (answer == wxYES) {
449 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
455 // former was csprint
456 Print(wxString(wxT("Using this configuration file: ")) << configfile << wxT("\n"), CS_DEBUG);
458 ct = new console_thread();
461 SetStatusText(wxT("Connecting to the director..."));
464 /* Register a new wxbDataParser */
465 void wxbMainFrame::Register(wxbDataParser* dp) {
469 /* Unregister a wxbDataParser */
470 void wxbMainFrame::Unregister(wxbDataParser* dp) {
472 if ((index = parsers.Index(dp)) != wxNOT_FOUND) {
473 parsers.RemoveAt(index);
476 Print(wxT("Failed to unregister a data parser !"), CS_DEBUG);
482 void wxbMainFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
484 Print(wxT("Quitting.\n"), CS_DEBUG);
490 console_thread::FreeLib();
496 void wxbMainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
499 msg.Printf( _T("Welcome to Bacula wx-console.\nWritten by Nicolas Boichat <nicolas@boichat.ch>\n(C) 2004 Kern Sibbald and John Walker\n"));
501 wxMessageBox(msg, _T("About Bacula wx-console"), wxOK | wxICON_INFORMATION, this);
504 void wxbMainFrame::OnChangeConfig(wxCommandEvent& event) {
505 wxString oriconfigfile;
506 wxConfig::Get()->Read(wxT("/ConfigFile"), &oriconfigfile);
507 wxString configfile = wxFileSelector(wxT("Please choose your default configuration file"));
508 if ( !configfile.empty() ) {
509 if (oriconfigfile != configfile) {
510 int answer = wxMessageBox(
511 wxT("Use this configuration file as default?"),
512 wxT("Configuration file"),
513 wxYES_NO | wxICON_QUESTION, this);
514 if (answer == wxYES) {
515 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
516 wxConfigBase::Get()->Flush();
517 StartConsoleThread(wxT(""));
522 StartConsoleThread(configfile);
526 void wxbMainFrame::OnEditConfig(wxCommandEvent& event) {
528 wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile);
529 int stat = wxbConfigFileEditor(this, configfile).ShowModal();
531 StartConsoleThread(configfile);
535 void wxbMainFrame::OnConnect(wxCommandEvent& event) {
536 StartConsoleThread(configfile);
539 void wxbMainFrame::OnDisconnect(wxCommandEvent& event) {
546 void wxbMainFrame::OnEnter(wxCommandEvent& WXUNUSED(event))
548 lockedbyconsole = true;
550 typeCtrl->HistoryAdd(typeCtrl->GetValue());
551 wxString str = typeCtrl->GetValue() + wxT("\n");
556 * Called when data is arriving from director
558 void wxbMainFrame::OnPrint(wxbThreadEvent& event) {
559 wxbPrintObject* po = event.GetEventPrintObject();
561 Print(po->str, po->status);
565 * Prints data received from director to the console, and forwards it to the panels
567 void wxbMainFrame::Print(wxString str, int status)
569 if (lockedbyconsole) {
570 EnableConsole(false);
573 if (status == CS_TERMINATED) {
574 consoleCtrl->AppendText(consoleBuffer);
575 consoleBuffer = wxT("");
576 SetStatusText(wxT("Console thread terminated."));
577 consoleCtrl->PageDown();
580 int answer = wxMessageBox(wxT("Connection to the director lost. Quit program?"), wxT("Connection lost"),
581 wxYES_NO | wxICON_EXCLAMATION, this);
582 if (answer == wxYES) {
586 menuFile->Enable(MenuConnect, true);
587 menuFile->SetLabel(MenuConnect, wxT("Connect"));
588 menuFile->SetHelpString(MenuConnect, wxT("Connect to the director"));
589 menuFile->Enable(MenuDisconnect, false);
590 menuFile->Enable(ChangeConfigFile, true);
591 menuFile->Enable(EditConfigFile, true);
595 if (status == CS_CONNECTED) {
596 SetStatusText(wxT("Connected to the director."));
597 typeCtrl->ClearCommandList();
598 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".help"), true);
601 for (i = 0; i < (int)dt->GetCount(); i++) {
604 if ((j = str.Find(' ')) > -1) {
605 typeCtrl->AddCommand(str.Mid(0, j), str.Mid(j+1));
609 menuFile->Enable(MenuConnect, true);
610 menuFile->SetLabel(MenuConnect, wxT("Reconnect"));
611 menuFile->SetHelpString(MenuConnect, wxT("Reconnect to the director"));
612 menuFile->Enable(MenuDisconnect, true);
613 menuFile->Enable(ChangeConfigFile, true);
614 menuFile->Enable(EditConfigFile, true);
617 if (status == CS_DISCONNECTED) {
618 consoleCtrl->AppendText(consoleBuffer);
619 consoleBuffer = wxT("");
620 consoleCtrl->PageDown();
621 SetStatusText(wxT("Disconnected of the director."));
626 // CS_DEBUG is often sent by panels,
627 // and resend it to them would sometimes cause infinite loops
629 /* One promptcaught is normal, so we must have two true Print values to be
630 * sure that the prompt has effectively been caught.
632 int promptcaught = -1;
634 if (status != CS_DEBUG) {
635 for (unsigned int i = 0; i < parsers.GetCount(); i++) {
636 promptcaught += parsers[i]->Print(str, status) ? 1 : 0;
639 if ((status == CS_PROMPT) && (promptcaught < 1) && (promptparser->isPrompt())) {
640 Print(wxT("Unexpected question has been received.\n"), CS_DEBUG);
641 // Print(wxString("(") << promptparser->getIntroString() << "/-/" << promptparser->getQuestionString() << ")\n", CS_DEBUG);
644 if (promptparser->getIntroString() != wxT("")) {
645 message << promptparser->getIntroString() << wxT("\n");
647 message << promptparser->getQuestionString();
649 if (promptparser->getChoices()) {
650 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
651 int *numbers = new int[promptparser->getChoices()->GetCount()];
654 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
655 if ((*promptparser->getChoices())[i] != wxT("")) {
656 choices[n] = (*promptparser->getChoices())[i];
662 int res = ::wxGetSingleChoiceIndex(message,
663 wxT("wx-console: unexpected director's question."), n, choices, this);
664 if (res == -1) { //Cancel pressed
668 if (promptparser->isNumericalChoice()) {
669 Send(wxString() << numbers[res] << wxT("\n"));
672 Send(wxString() << choices[res] << wxT("\n"));
677 Send(::wxGetTextFromUser(message,
678 wxT("wx-console: unexpected director's question."), wxT(""), this) + wxT("\n"));
683 if (status == CS_END) {
684 if (lockedbyconsole) {
686 lockedbyconsole = false;
691 if (status == CS_DEBUG) {
692 consoleCtrl->AppendText(consoleBuffer);
693 consoleBuffer = wxT("");
694 consoleCtrl->PageDown();
695 consoleCtrl->SetDefaultStyle(wxTextAttr(wxColour(0, 128, 0)));
698 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK));
700 consoleBuffer << wxbUtils::ConvertToPrintable(str);
701 if (status == CS_PROMPT) {
702 if (lockedbyconsole) {
705 //consoleBuffer << "<P>";
708 if ((status == CS_END) || (status == CS_PROMPT) || (str.Find(wxT("\n")) > -1)) {
709 consoleCtrl->AppendText(consoleBuffer);
710 consoleBuffer = wxT("");
712 consoleCtrl->PageDown();
715 // consoleCtrl->ShowPosition(consoleCtrl->GetLastPosition());
717 /*if (status != CS_DEBUG) {
718 consoleCtrl->AppendText("@");
720 //consoleCtrl->SetInsertionPointEnd();
722 /* if ((consoleCtrl->GetNumberOfLines()-1) > nlines) {
723 nlines = consoleCtrl->GetNumberOfLines()-1;
726 if (status == CS_END) {
727 consoleCtrl->ShowPosition(nlines);
732 * Sends data to the director
734 void wxbMainFrame::Send(wxString str)
737 ct->Write(str.mb_str(wxConvUTF8));
738 typeCtrl->SetValue(wxT(""));
739 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxRED));
740 consoleCtrl->AppendText(wxbUtils::ConvertToPrintable(str));
741 consoleCtrl->PageDown();
744 /* if ((consoleCtrl->GetNumberOfLines()-1) > nlines) {
745 nlines = consoleCtrl->GetNumberOfLines()-1;
748 consoleCtrl->ShowPosition(nlines);*/
752 void wxbMainFrame::EnablePanels() {
753 for (int i = 0; panels[i] != NULL; i++) {
754 panels[i]->EnablePanel(true);
759 /* Disable panels, except the one passed as parameter */
760 void wxbMainFrame::DisablePanels(void* except) {
761 for (int i = 0; panels[i] != NULL; i++) {
762 if (panels[i] != except) {
763 panels[i]->EnablePanel(false);
766 panels[i]->EnablePanel(true);
769 if (this != except) {
770 EnableConsole(false);
774 /* Enable or disable console typing */
775 void wxbMainFrame::EnableConsole(bool enable) {
776 typeCtrl->Enable(enable);
777 sendButton->Enable(enable);
779 typeCtrl->SetFocus();
784 * Used by csprint, which is called by console thread.
786 * In GTK and perhaps X11, only the main thread is allowed to interact with
787 * graphical components, so by firing an event, the main loop will call OnPrint.
789 * Calling OnPrint directly from console thread produces "unexpected async replies".
791 void firePrintEvent(wxString str, int status)
793 wxbPrintObject* po = new wxbPrintObject(str, status);
795 wxbThreadEvent evt(Thread);
796 evt.SetEventPrintObject(po);
798 if (wxbMainFrame::GetInstance()) {
799 wxbMainFrame::GetInstance()->AddPendingEvent(evt);
803 //wxString csBuffer; /* Temporary buffer for receiving data from console thread */
806 * Called by console thread, this function forwards data line by line and end
807 * signals to the GUI.
810 void csprint(wxString str, int status)
812 firePrintEvent(str, status);
816 void csprint(const char* str, int status)
819 firePrintEvent(wxString(str,wxConvUTF8), status);
822 firePrintEvent(wxT(""), status);