5 * Nicolas Boichat, July 2004
10 Copyright (C) 2004-2005 Kern Sibbald
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 version 2 as amended with additional clauses defined in the
15 file LICENSE in the main source directory.
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 the file LICENSE for additional details.
24 #include "wxbmainframe.h" // class's header file
26 #include "wxbrestorepanel.h"
28 #include "wxbconfigfileeditor.h"
32 #include "wxwin16x16.xpm"
34 #include <wx/arrimpl.cpp>
36 #include <wx/stattext.h>
37 #include <wx/statline.h>
38 #include <wx/config.h>
40 #include <wx/filename.h>
42 #undef Yield /* MinGW defines Yield */
44 // ----------------------------------------------------------------------------
45 // event tables and other macros for wxWindows
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 // IDs for the controls and the menu commands
58 // it is important for the id corresponding to the "About" command to have
59 // this standard value as otherwise it won't be handled properly under Mac
60 // (where it is special and put into the "Apple" menu)
61 Minimal_About = wxID_ABOUT,
73 * wxbTHREAD_EVENT declaration, used by csprint
75 BEGIN_DECLARE_EVENT_TYPES()
76 DECLARE_EVENT_TYPE(wxbTHREAD_EVENT, 1)
77 END_DECLARE_EVENT_TYPES()
79 DEFINE_EVENT_TYPE(wxbTHREAD_EVENT)
81 typedef void (wxEvtHandler::*wxThreadEventFunction)(wxbThreadEvent&);
83 #define EVT_THREAD_EVENT(id, fn) \
84 DECLARE_EVENT_TABLE_ENTRY( \
85 wxbTHREAD_EVENT, id, wxID_ANY, \
86 (wxObjectEventFunction)(wxEventFunction)(wxThreadEventFunction)&fn, \
90 // the event tables connect the wxWindows events with the functions (event
91 // handlers) which process them. It can be also done at run-time, but for the
92 // simple menu events like this the static method is much simpler.
93 BEGIN_EVENT_TABLE(wxbMainFrame, wxFrame)
94 EVT_MENU(Minimal_Quit, wxbMainFrame::OnQuit)
95 EVT_MENU(Minimal_About, wxbMainFrame::OnAbout)
96 EVT_MENU(ChangeConfigFile, wxbMainFrame::OnChangeConfig)
97 EVT_MENU(EditConfigFile, wxbMainFrame::OnEditConfig)
98 EVT_MENU(MenuConnect, wxbMainFrame::OnConnect)
99 EVT_MENU(MenuDisconnect, wxbMainFrame::OnDisconnect)
100 EVT_TEXT_ENTER(TypeText, wxbMainFrame::OnEnter)
101 EVT_THREAD_EVENT(Thread, wxbMainFrame::OnPrint)
102 EVT_BUTTON(SendButton, wxbMainFrame::OnEnter)
105 // ----------------------------------------------------------------------------
107 // ----------------------------------------------------------------------------
110 * wxbThreadEvent constructor
112 wxbThreadEvent::wxbThreadEvent(int id): wxEvent(id, wxbTHREAD_EVENT) {
113 m_eventObject = NULL;
117 * wxbThreadEvent destructor
119 wxbThreadEvent::~wxbThreadEvent()
121 if (m_eventObject != NULL) {
122 delete m_eventObject;
127 * wxbThreadEvent copy constructor
129 wxbThreadEvent::wxbThreadEvent(const wxbThreadEvent& te)
131 this->m_eventType = te.m_eventType;
132 this->m_id = te.m_id;
133 if (te.m_eventObject != NULL) {
134 this->m_eventObject = new wxbPrintObject(*((wxbPrintObject*)te.m_eventObject));
137 this->m_eventObject = NULL;
139 this->m_skipped = te.m_skipped;
140 this->m_timeStamp = te.m_timeStamp;
144 * Must be implemented (abstract in wxEvent)
146 wxEvent* wxbThreadEvent::Clone() const
148 return new wxbThreadEvent(*this);
152 * Gets the wxbPrintObject attached to this event, containing data sent by director
154 wxbPrintObject* wxbThreadEvent::GetEventPrintObject()
156 return (wxbPrintObject*)m_eventObject;
160 * Sets the wxbPrintObject attached to this event
162 void wxbThreadEvent::SetEventPrintObject(wxbPrintObject* object)
164 m_eventObject = (wxObject*)object;
167 // ----------------------------------------------------------------------------
169 // ----------------------------------------------------------------------------
171 wxbMainFrame *wxbMainFrame::frame = NULL;
174 * Singleton constructor
176 wxbMainFrame* wxbMainFrame::CreateInstance(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
178 frame = new wxbMainFrame(title, pos, size, style);
183 * Returns singleton instance
185 wxbMainFrame* wxbMainFrame::GetInstance()
193 wxbMainFrame::~wxbMainFrame()
195 wxConfig::Get()->Write(wxT("/Position/X"), (long)GetPosition().x);
196 wxConfig::Get()->Write(wxT("/Position/Y"), (long)GetPosition().y);
197 wxConfig::Get()->Write(wxT("/Size/Width"), (long)GetSize().GetWidth());
198 wxConfig::Get()->Write(wxT("/Size/Height"), (long)GetSize().GetHeight());
200 if (ct != NULL) { // && (!ct->IsRunning())
207 * Private constructor
209 wxbMainFrame::wxbMainFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
210 : wxFrame(NULL, -1, title, pos, size, style)
212 lockedbyconsole = false;
218 // set the frame icon
219 SetIcon(wxIcon(wxwin16x16_xpm));
223 menuFile = new wxMenu;
225 // the "About" item should be in the help menu
226 wxMenu *helpMenu = new wxMenu;
227 helpMenu->Append(Minimal_About, _T(_("&About...\tF1")), _T(_("Show about dialog")));
229 menuFile->Append(MenuConnect, _T(_("Connect")), _T(_("Connect to the director")));
230 menuFile->Append(MenuDisconnect, _T(_("Disconnect")), _T(_("Disconnect of the director")));
231 menuFile->AppendSeparator();
232 menuFile->Append(ChangeConfigFile, _T(_("Change of configuration file")), _T(_("Change your default configuration file")));
233 menuFile->Append(EditConfigFile, _T(_("Edit your configuration file")), _T(_("Edit your configuration file")));
234 menuFile->AppendSeparator();
235 menuFile->Append(Minimal_Quit, _T(_("E&xit\tAlt-X")), _T(_("Quit this program")));
237 // now append the freshly created menu to the menu bar...
238 wxMenuBar *menuBar = new wxMenuBar();
239 menuBar->Append(menuFile, _T(_("&File")));
240 menuBar->Append(helpMenu, _T(_("&Help")));
242 // ... and attach this menu bar to the frame
244 #endif // wxUSE_MENUS
248 SetStatusText(wxString::Format(wxT(_("Welcome to bacula wx-console %s (%s)!\n")), wxT(VERSION), wxT(BDATE)));
250 wxPanel* global = new wxPanel(this, -1);
252 notebook = new wxNotebook(global, -1);
256 wxPanel* consolePanel = new wxPanel(notebook, -1);
257 notebook->AddPage(consolePanel, wxT(_("Console")));
259 consoleCtrl = new wxTextCtrl(consolePanel,-1,wxT(""),wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH);
260 wxFont font(10, wxMODERN, wxNORMAL, wxNORMAL);
261 #if defined __WXGTK12__ && !defined __WXGTK20__ // Fix for "chinese" fonts under gtk+ 1.2
262 font.SetDefaultEncoding(wxFONTENCODING_ISO8859_1);
263 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
264 Print(wxT(_("Warning : Unicode is disabled because you are using wxWidgets for GTK+ 1.2.\n")), CS_DEBUG);
266 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
267 #if (wxUSE_UNICODE == 0) && __WXGTK20__
268 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);
272 helpCtrl = new wxStaticText(consolePanel, -1, wxT(_("Type your command below:")));
274 wxFlexGridSizer *consoleSizer = new wxFlexGridSizer(4, 1, 0, 0);
275 consoleSizer->AddGrowableCol(0);
276 consoleSizer->AddGrowableRow(0);
278 typeCtrl = new wxbHistoryTextCtrl(helpCtrl, consolePanel,TypeText,wxT(""),wxDefaultPosition,wxSize(200,20));
279 sendButton = new wxButton(consolePanel, SendButton, wxT(_("Send")));
281 wxFlexGridSizer *typeSizer = new wxFlexGridSizer(1, 2, 0, 0);
282 typeSizer->AddGrowableCol(0);
283 typeSizer->AddGrowableRow(0);
285 //typeSizer->Add(new wxStaticText(consolePanel, -1, _("Command: ")), 0, wxALIGN_CENTER | wxALL, 0);
286 typeSizer->Add(typeCtrl, 1, wxEXPAND | wxALL, 0);
287 typeSizer->Add(sendButton, 1, wxEXPAND | wxLEFT, 5);
289 consoleSizer->Add(consoleCtrl, 1, wxEXPAND | wxALL, 0);
290 consoleSizer->Add(new wxStaticLine(consolePanel, -1), 0, wxEXPAND | wxALL, 0);
291 consoleSizer->Add(helpCtrl, 1, wxEXPAND | wxALL, 2);
292 consoleSizer->Add(typeSizer, 0, wxEXPAND | wxALL, 2);
294 consolePanel->SetAutoLayout( TRUE );
295 consolePanel->SetSizer( consoleSizer );
296 consoleSizer->SetSizeHints( consolePanel );
298 // Creates the list of panels which are included in notebook, and that need to receive director information
300 panels = new wxbPanel* [2];
301 panels[0] = new wxbRestorePanel(notebook);
304 for (int i = 0; panels[i] != NULL; i++) {
305 notebook->AddPage(panels[i], panels[i]->GetTitle());
308 wxBoxSizer* globalSizer = new wxBoxSizer(wxHORIZONTAL);
310 #if wxCHECK_VERSION(2, 6, 0)
311 globalSizer->Add(notebook, 1, wxEXPAND, 0);
313 globalSizer->Add(new wxNotebookSizer(notebook), 1, wxEXPAND, 0);
316 global->SetSizer( globalSizer );
317 globalSizer->SetSizeHints( global );
319 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
321 sizer->Add(global, 1, wxEXPAND | wxALL, 0);
324 sizer->SetSizeHints( this );
326 EnableConsole(false);
328 consoleBuffer = wxT("");
330 configfile = wxT("");
334 * Starts the thread interacting with the director
335 * If config is not empty, uses this config file.
337 void wxbMainFrame::StartConsoleThread(const wxString& config) {
338 menuFile->Enable(MenuConnect, false);
339 menuFile->Enable(MenuDisconnect, false);
340 menuFile->Enable(ChangeConfigFile, false);
341 menuFile->Enable(EditConfigFile, false);
348 if (promptparser == NULL) {
349 promptparser = new wxbPromptParser();
352 if (config == wxT("")) {
353 configfile = wxT("");
355 if (((wxTheApp->argc % 2) != 1)) {
356 Print(wxT(_("Error while parsing command line arguments, using defaults.\n")), CS_DEBUG);
357 Print(wxT(_("Usage: wx-console [-c configfile] [-w tmp]\n")), CS_DEBUG);
360 for (int c = 1; c < wxTheApp->argc; c += 2) {
361 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-c"))) {
362 configfile = wxTheApp->argv[c+1];
364 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-w"))) {
365 console_thread::SetWorkingDirectory(wxTheApp->argv[c+1]);
367 if (wxTheApp->argv[c][0] != '-') {
368 Print(wxT(_("Error while parsing command line arguments, using defaults.\n")), CS_DEBUG);
369 Print(wxT(_("Usage: wx-console [-c configfile] [-w tmp]\n")), CS_DEBUG);
375 if (configfile == wxT("")) {
376 wxConfig::Set(new wxConfig(wxT("wx-console"), wxT("bacula")));
377 if (!wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile)) {
379 wxFileName filename(::wxGetHomeDir());
380 filename.MakeAbsolute();
381 configfile = filename.GetLongPath();
382 if (configfile.Last() != '/')
384 configfile += "Library/Preferences/org.bacula.wxconsole.conf";
386 wxFileName filename(::wxGetCwd(), wxT("wx-console.conf"));
387 filename.MakeAbsolute();
388 configfile = filename.GetLongPath();
390 configfile.Replace(wxT("\\"), wxT("/"));
393 wxConfig::Get()->Write(wxT("/ConfigFile"), configfile);
395 int answer = wxMessageBox(
396 wxString::Format(wxT(_(
397 "It seems that it is the first time you run wx-console.\n"
398 "This file (%s) has been choosen as default configuration file.\n"
399 "Do you want to edit it? (if you click No you will have to select another file)")),
402 wxYES_NO | wxICON_QUESTION, this);
403 if (answer == wxYES) {
404 wxbConfigFileEditor(this, configfile).ShowModal();
413 wxString err = console_thread::LoadConfig(configfile);
415 while (err != wxT("")) {
416 int answer = wxMessageBox(
417 wxString::Format(wxT(_(
418 "Unable to read %s\n"
420 "Do you want to choose another one? (Press no to edit this file)")), configfile.c_str(), err.c_str()),
421 wxT(_("Unable to read configuration file")),
422 wxYES_NO | wxCANCEL | wxICON_ERROR, this);
423 if (answer == wxNO) {
424 wxbConfigFileEditor(this, configfile).ShowModal();
425 err = console_thread::LoadConfig(configfile);
427 else if (answer == wxCANCEL) {
432 else { // (answer == wxYES)
433 configfile = wxFileSelector(wxT(_("Please choose a configuration file to use")));
434 if ( !configfile.empty() ) {
435 err = console_thread::LoadConfig(configfile);
444 if ((err == wxT("")) && (config == wxT(""))) {
445 answer = wxMessageBox(
446 wxT(_("This configuration file has been successfully read, use it as default?")),
447 wxT(_("Configuration file read successfully")),
448 wxYES_NO | wxICON_QUESTION, this);
449 if (answer == wxYES) {
450 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
456 // former was csprint
457 Print(wxString::Format(wxT(_("Using this configuration file: %s\n")), configfile.c_str()), CS_DEBUG);
459 ct = new console_thread();
462 SetStatusText(wxT(_("Connecting to the director...")));
465 /* Register a new wxbDataParser */
466 void wxbMainFrame::Register(wxbDataParser* dp) {
470 /* Unregister a wxbDataParser */
471 void wxbMainFrame::Unregister(wxbDataParser* dp) {
473 if ((index = parsers.Index(dp)) != wxNOT_FOUND) {
474 parsers.RemoveAt(index);
477 Print(wxT(_("Failed to unregister a data parser !")), CS_DEBUG);
483 void wxbMainFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
485 Print(wxT(_("Quitting.\n")), CS_DEBUG);
491 console_thread::FreeLib();
497 void wxbMainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
500 msg.Printf( _T(_("Welcome to Bacula wx-console.\nWritten by Nicolas Boichat <nicolas@boichat.ch>\n(C) 2004 Kern Sibbald and John Walker\n")));
502 wxMessageBox(msg, _T(_("About Bacula wx-console")), wxOK | wxICON_INFORMATION, this);
505 void wxbMainFrame::OnChangeConfig(wxCommandEvent& event) {
506 wxString oriconfigfile;
507 wxConfig::Get()->Read(wxT("/ConfigFile"), &oriconfigfile);
508 wxString configfile = wxFileSelector(wxT(_("Please choose your default configuration file")));
509 if ( !configfile.empty() ) {
510 if (oriconfigfile != configfile) {
511 int answer = wxMessageBox(
512 wxT(_("Use this configuration file as default?")),
513 wxT(_("Configuration file")),
514 wxYES_NO | wxICON_QUESTION, this);
515 if (answer == wxYES) {
516 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
517 wxConfigBase::Get()->Flush();
518 StartConsoleThread(wxT(""));
523 StartConsoleThread(configfile);
527 void wxbMainFrame::OnEditConfig(wxCommandEvent& event) {
529 wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile);
530 int stat = wxbConfigFileEditor(this, configfile).ShowModal();
532 StartConsoleThread(configfile);
536 void wxbMainFrame::OnConnect(wxCommandEvent& event) {
537 StartConsoleThread(configfile);
540 void wxbMainFrame::OnDisconnect(wxCommandEvent& event) {
547 void wxbMainFrame::OnEnter(wxCommandEvent& WXUNUSED(event))
549 lockedbyconsole = true;
551 typeCtrl->HistoryAdd(typeCtrl->GetValue());
552 wxString str = typeCtrl->GetValue() + wxT("\n");
557 * Called when data is arriving from director
559 void wxbMainFrame::OnPrint(wxbThreadEvent& event) {
560 wxbPrintObject* po = event.GetEventPrintObject();
562 Print(po->str, po->status);
566 * Prints data received from director to the console, and forwards it to the panels
568 void wxbMainFrame::Print(wxString str, int status)
570 if (lockedbyconsole) {
571 EnableConsole(false);
574 if (status == CS_TERMINATED) {
575 consoleCtrl->AppendText(consoleBuffer);
576 consoleBuffer = wxT("");
577 SetStatusText(wxT(_("Console thread terminated.")));
578 consoleCtrl->PageDown();
581 int answer = wxMessageBox( wxT(_("Connection to the director lost. Quit program?")),
582 wxT(_("Connection lost")),
583 wxYES_NO | wxICON_EXCLAMATION, this);
584 if (answer == wxYES) {
588 menuFile->Enable(MenuConnect, true);
589 menuFile->SetLabel(MenuConnect, wxT(_("Connect")));
590 menuFile->SetHelpString(MenuConnect, wxT(_("Connect to the director")));
591 menuFile->Enable(MenuDisconnect, false);
592 menuFile->Enable(ChangeConfigFile, true);
593 menuFile->Enable(EditConfigFile, true);
597 if (status == CS_CONNECTED) {
598 SetStatusText(wxT(_("Connected to the director.")));
599 typeCtrl->ClearCommandList();
600 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".help"), true);
603 for (i = 0; i < (int)dt->GetCount(); i++) {
606 if ((j = str.Find(' ')) > -1) {
607 typeCtrl->AddCommand(str.Mid(0, j), str.Mid(j+1));
611 menuFile->Enable(MenuConnect, true);
612 menuFile->SetLabel(MenuConnect, wxT(_("Reconnect")));
613 menuFile->SetHelpString(MenuConnect, wxT(_("Reconnect to the director")));
614 menuFile->Enable(MenuDisconnect, true);
615 menuFile->Enable(ChangeConfigFile, true);
616 menuFile->Enable(EditConfigFile, true);
619 if (status == CS_DISCONNECTED) {
620 consoleCtrl->AppendText(consoleBuffer);
621 consoleBuffer = wxT("");
622 consoleCtrl->PageDown();
623 SetStatusText(wxT(_("Disconnected of the director.")));
628 // CS_DEBUG is often sent by panels,
629 // and resend it to them would sometimes cause infinite loops
631 /* One promptcaught is normal, so we must have two true Print values to be
632 * sure that the prompt has effectively been caught.
634 int promptcaught = -1;
636 if (status != CS_DEBUG) {
637 for (unsigned int i = 0; i < parsers.GetCount(); i++) {
638 promptcaught += parsers[i]->Print(str, status) ? 1 : 0;
641 if ((status == CS_PROMPT) && (promptcaught < 1) && (promptparser->isPrompt())) {
642 Print(wxT(_("Unexpected question has been received.\n")), CS_DEBUG);
643 // Print(wxString("(") << promptparser->getIntroString() << "/-/" << promptparser->getQuestionString() << ")\n", CS_DEBUG);
646 if (promptparser->getIntroString() != wxT("")) {
647 message << promptparser->getIntroString() << wxT("\n");
649 message << promptparser->getQuestionString();
651 if (promptparser->getChoices()) {
652 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
653 int *numbers = new int[promptparser->getChoices()->GetCount()];
656 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
657 if ((*promptparser->getChoices())[i] != wxT("")) {
658 choices[n] = (*promptparser->getChoices())[i];
664 int res = ::wxGetSingleChoiceIndex(message,
665 wxT(_("wx-console: unexpected director's question.")), n, choices, this);
666 if (res == -1) { //Cancel pressed
670 if (promptparser->isNumericalChoice()) {
671 Send(wxString() << numbers[res] << wxT("\n"));
674 Send(wxString() << choices[res] << wxT("\n"));
679 Send(::wxGetTextFromUser(message,
680 wxT(_("wx-console: unexpected director's question.")),
681 wxT(""), this) + wxT("\n"));
686 if (status == CS_END) {
687 if (lockedbyconsole) {
689 lockedbyconsole = false;
694 if (status == CS_DEBUG) {
695 consoleCtrl->AppendText(consoleBuffer);
696 consoleBuffer = wxT("");
697 consoleCtrl->PageDown();
698 consoleCtrl->SetDefaultStyle(wxTextAttr(wxColour(0, 128, 0)));
701 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK));
703 consoleBuffer << wxbUtils::ConvertToPrintable(str);
704 if (status == CS_PROMPT) {
705 if (lockedbyconsole) {
708 //consoleBuffer << "<P>";
711 if ((status == CS_END) || (status == CS_PROMPT) || (str.Find(wxT("\n")) > -1)) {
712 consoleCtrl->AppendText(consoleBuffer);
713 consoleBuffer = wxT("");
715 consoleCtrl->PageDown();
718 // consoleCtrl->ShowPosition(consoleCtrl->GetLastPosition());
720 /*if (status != CS_DEBUG) {
721 consoleCtrl->AppendText("@");
723 //consoleCtrl->SetInsertionPointEnd();
725 /* if ((consoleCtrl->GetNumberOfLines()-1) > nlines) {
726 nlines = consoleCtrl->GetNumberOfLines()-1;
729 if (status == CS_END) {
730 consoleCtrl->ShowPosition(nlines);
735 * Sends data to the director
737 void wxbMainFrame::Send(wxString str)
740 ct->Write(str.mb_str(wxConvUTF8));
741 typeCtrl->SetValue(wxT(""));
742 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxRED));
743 consoleCtrl->AppendText(wxbUtils::ConvertToPrintable(str));
744 consoleCtrl->PageDown();
747 /* if ((consoleCtrl->GetNumberOfLines()-1) > nlines) {
748 nlines = consoleCtrl->GetNumberOfLines()-1;
751 consoleCtrl->ShowPosition(nlines);*/
755 void wxbMainFrame::EnablePanels() {
756 for (int i = 0; panels[i] != NULL; i++) {
757 panels[i]->EnablePanel(true);
762 /* Disable panels, except the one passed as parameter */
763 void wxbMainFrame::DisablePanels(void* except) {
764 for (int i = 0; panels[i] != NULL; i++) {
765 if (panels[i] != except) {
766 panels[i]->EnablePanel(false);
769 panels[i]->EnablePanel(true);
772 if (this != except) {
773 EnableConsole(false);
777 /* Enable or disable console typing */
778 void wxbMainFrame::EnableConsole(bool enable) {
779 typeCtrl->Enable(enable);
780 sendButton->Enable(enable);
782 typeCtrl->SetFocus();
787 * Used by csprint, which is called by console thread.
789 * In GTK and perhaps X11, only the main thread is allowed to interact with
790 * graphical components, so by firing an event, the main loop will call OnPrint.
792 * Calling OnPrint directly from console thread produces "unexpected async replies".
794 void firePrintEvent(wxString str, int status)
796 wxbPrintObject* po = new wxbPrintObject(str, status);
798 wxbThreadEvent evt(Thread);
799 evt.SetEventPrintObject(po);
801 if (wxbMainFrame::GetInstance()) {
802 wxbMainFrame::GetInstance()->AddPendingEvent(evt);
806 //wxString csBuffer; /* Temporary buffer for receiving data from console thread */
809 * Called by console thread, this function forwards data line by line and end
810 * signals to the GUI.
813 void csprint(wxString str, int status)
815 firePrintEvent(str, status);
819 void csprint(const char* str, int status)
822 firePrintEvent(wxString(str,wxConvUTF8), status);
825 firePrintEvent(wxT(""), status);