- re-implemented LogOptionsDialog based on ParamDialog

This commit is contained in:
Volker Ruppert 2006-03-11 10:00:56 +00:00
parent 9699eaeca4
commit 568b41c659
3 changed files with 126 additions and 277 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////
// $Id: wxdialog.cc,v 1.91 2006-03-09 20:16:17 vruppert Exp $
// $Id: wxdialog.cc,v 1.92 2006-03-11 10:00:56 vruppert Exp $
/////////////////////////////////////////////////////////////////
// Define BX_PLUGGABLE in files that can be compiled into plugins. For
@ -390,167 +390,6 @@ void FloppyConfigDialog::ShowHelp ()
}
//////////////////////////////////////////////////////////////////////
// LogOptionsDialog implementation
//////////////////////////////////////////////////////////////////////
// Structure:
// vertSizer:
// logfileSizer
// prompt
// logfile
// browse button
// prompt
// gridSizer 2 columns:
// "debug"
// action[0] = wxChoice
// "info"
// action[1] = wxChoice
// "error"
// action[2] = wxChoice
// "panic"
// action[3] = wxChoice
// debuggerlogfileSizer
// prompt
// debuggerlogfile
// browse button
// buttonSizer:
// help
// cancel
// ok
// all events go to OnEvent method
BEGIN_EVENT_TABLE(LogOptionsDialog, wxDialog)
EVT_BUTTON(-1, LogOptionsDialog::OnEvent)
EVT_CHECKBOX(-1, LogOptionsDialog::OnEvent)
EVT_TEXT(-1, LogOptionsDialog::OnEvent)
END_EVENT_TABLE()
LogOptionsDialog::LogOptionsDialog(
wxWindow* parent,
wxWindowID id)
: wxDialog (parent, id, "", wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
static char *names[] = LOG_OPTS_TYPE_NAMES;
SetTitle (LOG_OPTS_TITLE);
vertSizer = new wxBoxSizer (wxVERTICAL);
// top level objects
logfileSizer = new wxBoxSizer (wxHORIZONTAL);
vertSizer->Add (logfileSizer, 0, wxTOP|wxLEFT, 20);
wxStaticText *text = new wxStaticText (this, -1, LOG_OPTS_PROMPT);
vertSizer->Add (text, 0, wxALL, 10);
gridSizer = new wxFlexGridSizer (2);
vertSizer->Add (gridSizer, 1, wxLEFT, 40);
text = new wxStaticText (this, -1, LOG_OPTS_ADV);
vertSizer->Add (text, 0, wxTOP|wxLEFT, 20);
debuggerlogfileSizer = new wxBoxSizer (wxHORIZONTAL);
vertSizer->Add (debuggerlogfileSizer, 0, wxALL, 20);
buttonSizer = new wxBoxSizer (wxHORIZONTAL);
vertSizer->Add (buttonSizer, 0, wxALIGN_RIGHT);
// logfileSizer contents
text = new wxStaticText (this, -1, LOG_OPTS_LOGFILE);
logfileSizer->Add (text);
logfile = new wxTextCtrl (this, -1, "", wxDefaultPosition, longTextSize);
logfileSizer->Add (logfile);
wxButton *btn = new wxButton (this, ID_Browse, BTNLABEL_BROWSE);
logfileSizer->Add (btn, 0, wxALL, 5);
// debuggerlogfileSizer contents
text = new wxStaticText (this, -1, LOG_OPTS_DEBUGGER_LOGFILE);
debuggerlogfileSizer->Add (text);
debuggerlogfile = new wxTextCtrl (this, -1, "", wxDefaultPosition, longTextSize);
debuggerlogfileSizer->Add (debuggerlogfile);
btn = new wxButton (this, ID_Browse2, BTNLABEL_BROWSE);
debuggerlogfileSizer->Add (btn, 0, wxALL, 5);
// gridSizer contents
gridSizer->AddGrowableCol (1);
for (int evtype=0; evtype<LOG_OPTS_N_TYPES; evtype++) {
gridSizer->Add (new wxStaticText (this, -1, names[evtype]), 0, wxALL, 5);
action[evtype] = makeLogOptionChoiceBox (this, -1, evtype, true);
gridSizer->Add (action[evtype], 1, wxALL|wxGROW|wxADJUST_MINSIZE, 5);
}
// buttonSizer contents
btn = new wxButton (this, wxID_HELP, BTNLABEL_HELP);
buttonSizer->Add (btn, 0, wxALL, 5);
// use wxID_CANCEL because pressing ESC produces this same code
btn = new wxButton (this, wxID_CANCEL, BTNLABEL_CANCEL);
buttonSizer->Add (btn, 0, wxALL, 5);
btn = new wxButton (this, wxID_OK, BTNLABEL_OK);
buttonSizer->Add (btn, 0, wxALL, 5);
}
void LogOptionsDialog::Init()
{
// lay it out!
SetAutoLayout(TRUE);
SetSizer(vertSizer);
vertSizer->Fit (this);
wxSize size = vertSizer->GetMinSize ();
wxLogMessage ("minsize is %d,%d", size.GetWidth(), size.GetHeight ());
int margin = 5;
SetSizeHints (size.GetWidth () + margin, size.GetHeight () + margin);
Center ();
}
void LogOptionsDialog::SetAction (int evtype, int a) {
// find the choice whose client data matches "a".
int *ptr;
//wxLogDebug ("SetAction type=%d a=%d", evtype, a);
for (int i=0; i < action[evtype]->GetCount (); i++) {
//wxLogDebug ("reading action[%d]->GetClientData(%d)", evtype, i);
ptr = (int*) action[evtype]->GetClientData (i);
if (ptr == NULL) continue;
if (a == *ptr) { // found it!
action[evtype]->SetSelection (i);
return;
}
}
// this can happen if one of the choices that is excluded by
// LOG_OPTS_EXCLUDE() is used, for example.
wxLogDebug ("SetAction type=%d a=%d not found", evtype, a);
}
int LogOptionsDialog::GetAction (int evtype) {
int sel = action[evtype]->GetSelection ();
int *ptrToChoice = (int*)action[evtype]->GetClientData (sel);
wxASSERT (ptrToChoice != NULL);
return *ptrToChoice;
}
void LogOptionsDialog::OnEvent(wxCommandEvent& event)
{
int id = event.GetId ();
wxLogMessage ("you pressed button id=%d", id);
switch (id) {
case ID_Browse:
BrowseTextCtrl (logfile);
break;
case ID_Browse2:
BrowseTextCtrl (debuggerlogfile);
break;
case wxID_OK:
EndModal (wxID_OK);
break;
case wxID_CANCEL:
EndModal (wxID_CANCEL);
break;
case wxID_HELP:
ShowHelp();
break;
default:
event.Skip ();
}
}
void LogOptionsDialog::ShowHelp ()
{
wxMessageBox(MSG_NO_HELP, MSG_NO_HELP_CAPTION, wxOK | wxICON_ERROR, this );
}
//////////////////////////////////////////////////////////////////////
// AdvancedLogOptionsDialog implementation
//////////////////////////////////////////////////////////////////////
@ -1888,6 +1727,66 @@ CpuRegistersDialog::OnEvent(wxCommandEvent& event)
}
}
//////////////////////////////////////////////////////////////////////
// LogOptionsDialog implementation
//////////////////////////////////////////////////////////////////////
// all events go to OnEvent method
BEGIN_EVENT_TABLE(LogOptionsDialog, wxDialog)
EVT_BUTTON(-1, LogOptionsDialog::OnEvent)
EVT_CHECKBOX(-1, LogOptionsDialog::OnEvent)
EVT_TEXT(-1, LogOptionsDialog::OnEvent)
END_EVENT_TABLE()
LogOptionsDialog::LogOptionsDialog(
wxWindow* parent,
wxWindowID id)
: ParamDialog(parent, id)
{
static char *names[] = LOG_OPTS_TYPE_NAMES;
SetTitle(LOG_OPTS_TITLE);
AddParam(SIM->get_param("log"));
wxStaticText *text = new wxStaticText(this, -1, LOG_OPTS_PROMPT);
mainSizer->Add(text, 0, wxALL, 10);
gridSizer = new wxFlexGridSizer (2);
mainSizer->Add(gridSizer, 1, wxLEFT, 40);
text = new wxStaticText (this, -1, LOG_OPTS_ADV);
mainSizer->Add(text, 0, wxTOP|wxLEFT, 20);
// gridSizer contents
gridSizer->AddGrowableCol(1);
for (int evtype=0; evtype<LOG_OPTS_N_TYPES; evtype++) {
gridSizer->Add(new wxStaticText (this, -1, names[evtype]), 0, wxALL, 5);
action[evtype] = makeLogOptionChoiceBox(this, -1, evtype, true);
gridSizer->Add(action[evtype], 1, wxALL|wxGROW|wxADJUST_MINSIZE, 5);
}
}
void LogOptionsDialog::SetAction(int evtype, int a) {
// find the choice whose client data matches "a".
int *ptr;
//wxLogDebug ("SetAction type=%d a=%d", evtype, a);
for (int i=0; i < action[evtype]->GetCount(); i++) {
//wxLogDebug ("reading action[%d]->GetClientData(%d)", evtype, i);
ptr = (int*) action[evtype]->GetClientData(i);
if (ptr == NULL) continue;
if (a == *ptr) { // found it!
action[evtype]->SetSelection(i);
return;
}
}
// this can happen if one of the choices that is excluded by
// LOG_OPTS_EXCLUDE() is used, for example.
wxLogDebug ("SetAction type=%d a=%d not found", evtype, a);
}
int LogOptionsDialog::GetAction(int evtype) {
int sel = action[evtype]->GetSelection();
int *ptrToChoice = (int*)action[evtype]->GetClientData(sel);
wxASSERT(ptrToChoice != NULL);
return *ptrToChoice;
}
/////////////////////////////////////////////////////////////////
// utility

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////
// $Id: wxdialog.h,v 1.60 2006-03-08 18:10:41 vruppert Exp $
// $Id: wxdialog.h,v 1.61 2006-03-11 10:00:56 vruppert Exp $
////////////////////////////////////////////////////////////////////
//
// wxWidgets dialogs for Bochs
@ -34,14 +34,14 @@
#endif
// utility function prototype
void ChangeStaticText (wxSizer *sizer, wxStaticText *win, wxString newtext);
bool CreateImage (int harddisk, int sectors, const char *filename);
void SetTextCtrl (wxTextCtrl *text, const char *format, int val);
int GetTextCtrlInt (wxTextCtrl *text, bool *valid = NULL, bool complain=false, wxString complaint = "Invalid integer!");
bool BrowseTextCtrl (wxTextCtrl *text,
void ChangeStaticText(wxSizer *sizer, wxStaticText *win, wxString newtext);
bool CreateImage(int harddisk, int sectors, const char *filename);
void SetTextCtrl(wxTextCtrl *text, const char *format, int val);
int GetTextCtrlInt(wxTextCtrl *text, bool *valid = NULL, bool complain=false, wxString complaint = "Invalid integer!");
bool BrowseTextCtrl(wxTextCtrl *text,
wxString prompt="Choose a file",
long style=wxOPEN);
wxChoice *makeLogOptionChoiceBox (wxWindow *parent, wxWindowID id, int evtype, bool includeNoChange = false);
wxChoice *makeLogOptionChoiceBox(wxWindow *parent, wxWindowID id, int evtype, bool includeNoChange = false);
////////////////////////////////////////////////////////////////////
// LogMsgAskDialog is a modal dialog box that shows the user a
@ -209,83 +209,6 @@ public:
DECLARE_EVENT_TABLE()
};
////////////////////////////////////////////////////////////////////////////
// LogOptionsDialog
////////////////////////////////////////////////////////////////////////////
// LogOptionsDialog allows the user to decide how Bochs will
// behave for each type of log event.
//
// +---- Configure events -----------------------------------+
// | |
// | Log file is [_____________________________] [ Browse ] |
// | |
// | How should Bochs respond to each type of event? |
// | |
// | Debug events: [ignore] |
// | Info events: [ignore] |
// | Error events: [report] |
// | Panic events: [ask ] |
// | |
// | For additional control over how each device responds |
// | to events, use the menu option "Log ... By Device". |
// | |
// | Debugger log file is [____________________] [ Browse ] |
// | |
// | [ Advanced ] [ Help ] [ Cancel ] [ Ok ] |
// +---------------------------------------------------------+
// To use this dialog:
// After constructor, call SetAction(eventtype, action) to set initial
// value for each choice field. The eventtype is 0 to LOG_OPTS_N_TYPES-1,
// representing the types listed in LOG_OPTS_TYPE_NAMES. The choice field is 0
// to LOG_OPTS_N_CHOICES-1, representing the actions listed in
// LOG_OPTS_CHOICES. Then call ShowModal(), which will return wxID_OK or
// wxID_CANCEL. Afterward, the GetAction(eventtype) method will tell what was
// selected in each choice box.
class LogOptionsDialog: public wxDialog
{
private:
#define LOG_OPTS_TITLE "Configure Log Events"
#define LOG_OPTS_LOGFILE "Log file is "
#define LOG_OPTS_DEBUGGER_LOGFILE "Debugger log file is "
#define LOG_OPTS_PROMPT "How should Bochs respond to each type of event?"
#define LOG_OPTS_TYPE_NAMES { "Debug events: ", "Info events: ", "Error events: ", "Panic events: ", "Pass events: " }
#define LOG_OPTS_N_TYPES 5
#define LOG_OPTS_CHOICES { "ignore", "log", "ask user", "end simulation", "no change" }
#define LOG_OPTS_N_CHOICES_NORMAL 4
#define LOG_OPTS_N_CHOICES 5 // number of choices, including "no change"
#define LOG_OPTS_NO_CHANGE 4 // index of "no change"
// normally all choices are available for all event types. The exclude
// expression allows some choices to be eliminated if they don't make any
// sense. For example, it would be stupid to ignore a panic.
#define LOG_OPTS_EXCLUDE(type,choice) ( \
/* can't die or ask, on debug or info events */ \
(type <= 1 && (choice==2 || choice==3)) \
/* can't ignore panics or errors */ \
|| (type >= 2 && choice==0) \
)
#define LOG_OPTS_ADV "For additional control over how each device responds to events, use the menu option \"Log ... By Device\"."
void Init (); // called automatically by ShowModal()
void ShowHelp ();
wxBoxSizer *vertSizer, *logfileSizer, *debuggerlogfileSizer, *buttonSizer;
wxFlexGridSizer *gridSizer;
wxButton *applyDefault;
wxTextCtrl *logfile;
wxTextCtrl *debuggerlogfile;
wxChoice *action[LOG_OPTS_N_TYPES];
public:
LogOptionsDialog(wxWindow* parent, wxWindowID id);
void OnEvent (wxCommandEvent& event);
int ShowModal() { Init(); return wxDialog::ShowModal(); }
int GetAction (int evtype);
void SetAction (int evtype, int action);
void SetLogfile (wxString f) { logfile->SetValue (f); }
void SetDebuggerlogfile (wxString f) { debuggerlogfile->SetValue (f); }
wxString GetLogfile () { return logfile->GetValue (); }
wxString GetDebuggerlogfile () { return debuggerlogfile->GetValue (); }
DECLARE_EVENT_TABLE()
};
////////////////////////////////////////////////////////////////////////////
// AdvancedLogOptionsDialog
////////////////////////////////////////////////////////////////////////////
@ -317,7 +240,7 @@ class AdvancedLogOptionsDialog: public wxDialog
{
private:
#define ADVLOG_OPTS_TITLE "Configure Log Events"
#define ADVLOG_OPTS_LOGFILE LOG_OPTS_LOGFILE
#define ADVLOG_OPTS_LOGFILE "Log file"
#define ADVLOG_OPTS_PROMPT \
"This table determines how Bochs will respond to each kind of event coming\n" \
"from a particular source. For example if you are having problems with\n" \
@ -507,6 +430,43 @@ public:
DECLARE_EVENT_TABLE()
};
////////////////////////////////////////////////////////////////////////////
// LogOptionsDialog
////////////////////////////////////////////////////////////////////////////
//
// the new LogOptionsDialog is based on ParamDialog. It allows the user to
// configure the log file settings and to decide how Bochs will behave for
// each type of log event.
class LogOptionsDialog : public ParamDialog
{
private:
#define LOG_OPTS_TITLE "Configure Log Events"
#define LOG_OPTS_PROMPT "How should Bochs respond to each type of event?"
#define LOG_OPTS_TYPE_NAMES { "Debug events: ", "Info events: ", "Error events: ", "Panic events: ", "Pass events: " }
#define LOG_OPTS_N_TYPES 5
#define LOG_OPTS_CHOICES { "ignore", "log", "ask user", "end simulation", "no change" }
#define LOG_OPTS_N_CHOICES_NORMAL 4
#define LOG_OPTS_N_CHOICES 5 // number of choices, including "no change"
#define LOG_OPTS_NO_CHANGE 4 // index of "no change"
// normally all choices are available for all event types. The exclude
// expression allows some choices to be eliminated if they don't make any
// sense. For example, it would be stupid to ignore a panic.
#define LOG_OPTS_EXCLUDE(type,choice) ( \
/* can't die or ask, on debug or info events */ \
(type <= 1 && (choice==2 || choice==3)) \
/* can't ignore panics or errors */ \
|| (type >= 2 && choice==0) \
)
#define LOG_OPTS_ADV "For additional control over how each device responds to events, use the menu option \"Log ... By Device\"."
wxFlexGridSizer *gridSizer;
wxChoice *action[LOG_OPTS_N_TYPES];
public:
LogOptionsDialog(wxWindow* parent, wxWindowID id);
int GetAction(int evtype);
void SetAction(int evtype, int action);
DECLARE_EVENT_TABLE()
};
////////////////////////////////////////////////////////////////////////////
// CpuRegistersDialog
////////////////////////////////////////////////////////////////////////////
@ -603,7 +563,6 @@ public:
};
/**************************************************************************
Everything else in here is a comment!

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////
// $Id: wxmain.cc,v 1.129 2006-03-07 20:32:07 vruppert Exp $
// $Id: wxmain.cc,v 1.130 2006-03-11 10:00:56 vruppert Exp $
/////////////////////////////////////////////////////////////////
//
// wxmain.cc implements the wxWidgets frame, toolbar, menus, and dialogs.
@ -697,12 +697,8 @@ void MyFrame::OnLogPrefs(wxCommandEvent& WXUNUSED(event))
// Ideally I would use the siminterface methods to fill in the fields
// of the LogOptionsDialog, but in fact several things are hardcoded.
// At least I can verify that the expected numbers are the same.
wxASSERT (SIM->get_max_log_level() == LOG_OPTS_N_TYPES);
LogOptionsDialog dlg (this, -1);
bx_param_string_c *logfile = SIM->get_param_string(BXPN_LOG_FILENAME);
dlg.SetLogfile (wxString (logfile->getptr()));
bx_param_string_c *debuggerlogfile = SIM->get_param_string(BXPN_DEBUGGER_LOG_FILENAME);
dlg.SetDebuggerlogfile (wxString (debuggerlogfile->getptr ()));
wxASSERT(SIM->get_max_log_level() == LOG_OPTS_N_TYPES);
LogOptionsDialog dlg(this, -1);
// The inital values of the dialog are complicated. If the panic action
// for all modules is "ask", then clearly the inital value in the dialog
@ -716,36 +712,31 @@ void MyFrame::OnLogPrefs(wxCommandEvent& WXUNUSED(event))
int level, nlevel = SIM->get_max_log_level();
for (level=0; level<nlevel; level++) {
int mod = 0;
int first = SIM->get_log_action (mod, level);
int first = SIM->get_log_action(mod, level);
bool consensus = true;
// now compare all others to first. If all match, then use "first" as
// the initial value.
for (mod=1; mod<SIM->get_n_log_modules (); mod++) {
if (first != SIM->get_log_action (mod, level)) {
for (mod=1; mod<SIM->get_n_log_modules(); mod++) {
if (first != SIM->get_log_action(mod, level)) {
consensus = false;
break;
}
}
if (consensus)
dlg.SetAction (level, first);
dlg.SetAction(level, first);
else
dlg.SetAction (level, LOG_OPTS_NO_CHANGE);
dlg.SetAction(level, LOG_OPTS_NO_CHANGE);
}
int n = dlg.ShowModal (); // show the dialog!
int n = dlg.ShowModal(); // show the dialog!
if (n == wxID_OK) {
char buf[1024];
safeWxStrcpy (buf, dlg.GetLogfile (), sizeof (buf));
logfile->set (buf);
safeWxStrcpy (buf, dlg.GetDebuggerlogfile (), sizeof (buf));
debuggerlogfile->set (buf);
for (level=0; level<nlevel; level++) {
// ask the dialog what action the user chose for this type of event
int action = dlg.GetAction (level);
int action = dlg.GetAction(level);
if (action != LOG_OPTS_NO_CHANGE) {
// set new default
SIM->set_default_log_action (level, action);
SIM->set_default_log_action(level, action);
// apply that action to all modules (devices)
SIM->set_log_action (-1, level, action);
SIM->set_log_action(-1, level, action);
}
}
}
@ -754,8 +745,8 @@ void MyFrame::OnLogPrefs(wxCommandEvent& WXUNUSED(event))
void MyFrame::OnLogPrefsDevice(wxCommandEvent& WXUNUSED(event))
{
wxASSERT (SIM->get_max_log_level() == ADVLOG_OPTS_N_TYPES);
AdvancedLogOptionsDialog dlg (this, -1);
dlg.ShowModal ();
AdvancedLogOptionsDialog dlg(this, -1);
dlg.ShowModal();
}
// How is this going to work?
@ -781,17 +772,17 @@ void MyFrame::OnShowCpu(wxCommandEvent& WXUNUSED(event))
return;
}
if (showCpu == NULL) {
showCpu = new CpuRegistersDialog (this, -1);
showCpu = new CpuRegistersDialog(this, -1);
#if BX_DEBUGGER
showCpu->SetTitle ("Bochs Debugger");
showCpu->SetTitle("Bochs Debugger");
#else
showCpu->SetTitle ("CPU Registers");
showCpu->SetTitle("CPU Registers");
#endif
showCpu->Init ();
showCpu->Init();
} else {
showCpu->CopyParamToGui ();
showCpu->CopyParamToGui();
}
showCpu->Show (TRUE);
showCpu->Show(TRUE);
}
void MyFrame::OnShowKeyboard(wxCommandEvent& WXUNUSED(event))