- add first custom dialog box to the wxWindows interface in

gui/wxdialog.h and gui/wxdialog.cc.  The first dialog box is
  called LogMsgAskDialog.  It displays panic messages and asks if you
  want to continue, quit, etc.
This commit is contained in:
Bryce Denney 2002-08-28 03:20:23 +00:00
parent 67f9213460
commit 7fc65e2e25
4 changed files with 337 additions and 23 deletions

View File

@ -53,7 +53,7 @@ GUI_OBJS_NOGUI = nogui.o
GUI_OBJS_TERM = term.o
GUI_OBJS_RFB = rfb.o
GUI_OBJS_AMIGAOS = amigaos.o
GUI_OBJS_WX = wx.o wxmain.o
GUI_OBJS_WX = wx.o wxmain.o wxdialog.o
GUI_OBJS = keymap.o gui.o siminterface.o @GUI_OBJS@

249
bochs/gui/wxdialog.cc Normal file
View File

@ -0,0 +1,249 @@
/////////////////////////////////////////////////////////////////
// $Id: wxdialog.cc,v 1.1 2002-08-28 03:20:23 bdenney Exp $
/////////////////////////////////////////////////////////////////
//
// misc/wxdialog.cc
// This is a testbed for wxWindows dialog box experiments.
//
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "wx/html/htmlwin.h"
#include "config.h" // definitions based on configure script
#include "osdep.h" // workarounds for missing stuff
#include "gui/siminterface.h" // interface to the simulator
#include "bxversion.h" // get version string
#include "wxmain.h" // wxwindows shared stuff
#include "wxdialog.h" // custom dialog boxes
//////////////////////////////////////////////////////////////////////
// constants, prototypes
//////////////////////////////////////////////////////////////////////
enum {
ID_ShowDialog_1 = 1,
ID_ShowDialog_2,
ID_ShowDialog_3,
ID_Quit,
ID_Button1,
ID_Button2,
ID_Continue,
ID_Die,
ID_DumpCore,
ID_Debugger,
ID_Help,
ID_MY_LAST_ID
};
void ChangeStaticText (wxSizer *sizer, wxStaticText *win, wxString newtext);
//////////////////////////////////////////////////////////////////////
// LogMsgAskDialog implementation
//////////////////////////////////////////////////////////////////////
// all events go to OnEvent method
BEGIN_EVENT_TABLE(LogMsgAskDialog, wxDialog)
EVT_BUTTON(ID_Continue, LogMsgAskDialog::OnEvent)
EVT_BUTTON(ID_Die, LogMsgAskDialog::OnEvent)
EVT_BUTTON(ID_DumpCore, LogMsgAskDialog::OnEvent)
EVT_BUTTON(ID_Debugger, LogMsgAskDialog::OnEvent)
EVT_BUTTON(ID_Help, LogMsgAskDialog::OnEvent)
END_EVENT_TABLE()
LogMsgAskDialog::LogMsgAskDialog(
wxWindow* parent,
wxWindowID id,
const wxString& title)
: wxDialog (parent, id, title, wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
for (int i=0; i<N_BUTTONS; i++) enabled[i] = TRUE;
vertSizer = new wxBoxSizer(wxVERTICAL);
context = new wxStaticText (this, -1, "Context: ");
wxFont font = context->GetFont ();
font.SetWeight (wxBOLD);
font.SetPointSize (2 + font.GetPointSize ());
context->SetFont (font);
message = new wxStaticText (this, -1, "Message: ");
message->SetFont (font);
dontAsk = new wxCheckBox (this, -1, LOG_MSG_DONT_ASK_STRING);
btnSizer = new wxBoxSizer(wxHORIZONTAL);
// fill vertical sizer
vertSizer->Add (context, 0, wxGROW|wxALIGN_LEFT|wxLEFT|wxTOP, 30);
vertSizer->Add (message, 0, wxGROW|wxALIGN_LEFT|wxLEFT, 30);
vertSizer->Add (dontAsk, 0, wxALIGN_CENTER|wxTOP, 30);
vertSizer->Add (btnSizer, 0, wxALIGN_CENTER|wxTOP, 30);
// Some object creation and layout is postponed until Init()
// so that caller has time to configure the dialog.
}
void LogMsgAskDialog::SetContext (char *s) {
wxString text;
text.Printf ("Context: %s", s);
ChangeStaticText (vertSizer, context, text);
}
void LogMsgAskDialog::SetMessage (char *s) {
wxString text;
text.Printf ("Message: %s", s);
ChangeStaticText (vertSizer, message, text);
}
void LogMsgAskDialog::Init ()
{
static const int ids[N_BUTTONS] = LOG_MSG_ASK_IDS;
static const char *names[N_BUTTONS] = LOG_MSG_ASK_NAMES;
for (int i=0; i<N_BUTTONS; i++) {
if (!enabled[i]) continue;
wxButton *btn = new wxButton (this, ids[i], names[i]);
btnSizer->Add (btn, 1, wxALL, 5);
}
wxSize ms = message->GetSize ();
printf ("message size is %d,%d\n", ms.GetWidth(), ms.GetHeight ());
SetAutoLayout(TRUE);
SetSizer(vertSizer);
vertSizer->Fit (this);
wxSize size = vertSizer->GetMinSize ();
printf ("minsize is %d,%d\n", size.GetWidth(), size.GetHeight ());
int margin = 10;
SetSizeHints (size.GetWidth () + margin, size.GetHeight () + margin);
Center ();
}
// Event handler for dialog buttons. Just translate the wx ids into
// enum values and return them with EndModel() to make the dialog
// go away.
void LogMsgAskDialog::OnEvent(wxCommandEvent& event)
{
int id = event.GetId ();
int ret = -1;
switch (id) {
case ID_Continue: ret = CONT; break;
case ID_Die: ret = DIE; break;
case ID_DumpCore: ret = DUMP; break;
case ID_Debugger: ret = DEBUG; break;
case ID_Help: showHelp (); return;
default:
return; // without EndModal
}
printf ("you pressed button id=%d, return value=%d\n", id, ret);
EndModal (ret);
}
void LogMsgAskDialog::showHelp ()
{
wxMessageBox("No help is available yet.", "No Help", wxOK | wxICON_ERROR );
}
/////////////////////////////////////////////////////////////////
// utility
/////////////////////////////////////////////////////////////////
// Unfortunately this step is necessary if you change the text.
// Otherwise the sizer that contains the text never realizes that
// the size has changed, and the layout is never updated. The
// SetItemMinSize trick was reported on comp.soft-sys.wxwindows by
// Dirk Birnhardt.
void ChangeStaticText (wxSizer *sizer, wxStaticText *win, wxString newtext)
{
win->SetLabel (newtext);
wxSize sz = win->GetSize ();
sizer->SetItemMinSize (win, sz.GetWidth (), sz.GetHeight ());
}
#ifdef TEST_DIALOG
//////////////////////////////////////////////////////////////////////
// MyApp declaration
//////////////////////////////////////////////////////////////////////
class MyApp: public wxApp
{
virtual bool OnInit();
};
IMPLEMENT_APP(MyApp)
//////////////////////////////////////////////////////////////////////
// MyFrame declaration
//////////////////////////////////////////////////////////////////////
class MyFrame: public wxFrame
{
public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, const long style);
void OnMenuEvent(wxCommandEvent& event);
private:
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_ShowDialog_1, MyFrame::OnMenuEvent)
EVT_MENU(ID_ShowDialog_2, MyFrame::OnMenuEvent)
EVT_MENU(ID_ShowDialog_3, MyFrame::OnMenuEvent)
EVT_MENU(ID_Quit, MyFrame::OnMenuEvent)
END_EVENT_TABLE()
//////////////////////////////////////////////////////////////////////
// MyApp methods
//////////////////////////////////////////////////////////////////////
bool MyApp::OnInit()
{
MyFrame *frame = new MyFrame( "Bochs x86 Emulator", wxPoint(50,50), wxSize(450,340), wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION );
frame->Show( TRUE );
SetTopWindow( frame );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// MyFrame methods
//////////////////////////////////////////////////////////////////////
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, const long style)
: wxFrame((wxFrame *)NULL, -1, title, pos, size, style)
{
wxMenu *menu1 = new wxMenu;
menu1->Append( ID_ShowDialog_1, "Show Dialog &1" );
menu1->Append( ID_ShowDialog_2, "Show Dialog &2" );
menu1->Append( ID_ShowDialog_3, "Show Dialog &3" );
menu1->Append( ID_Quit, "&Quit" );
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append( menu1, "&File" );
SetMenuBar( menuBar );
CreateStatusBar();
SetStatusText("");
}
void MyFrame::OnMenuEvent(wxCommandEvent& event)
{
int id = event.GetId ();
switch (id) {
case ID_ShowDialog_1:
{
printf ("show dialog 1\n");
LogMsgAskDialog dlg(this, -1, "Panic");
dlg.EnableButton (dlg.DEBUG, FALSE);
dlg.SetContext ("Hard Drive");
dlg.SetMessage ("could not open hard drive image file '30M.sample'");
int n = dlg.ShowModal ();
printf ("modal dialog returned %d\n", n);
printf ("and the dontAsk button is %d\n", dlg.GetDontAsk ());
}
break;
case ID_ShowDialog_2:
printf ("show dialog 2\n");
break;
case ID_ShowDialog_3:
printf ("show dialog 3\n");
break;
case ID_Quit:
Close (TRUE);
break;
}
}
#endif

58
bochs/gui/wxdialog.h Normal file
View File

@ -0,0 +1,58 @@
////////////////////////////////////////////////////////////////////
// $Id: wxdialog.h,v 1.1 2002-08-28 03:20:23 bdenney Exp $
////////////////////////////////////////////////////////////////////
//
// wxWindows dialogs for Bochs
////////////////////////////////////////////////////////////////////
// LogMsgAskDialog is a modal dialog box that shows the user a
// simulation error message and asks if they want to continue or
// not. It looks something like this:
// -------------------------------------------------------------
// Context: Hard Drive
// Message: could not open hard drive image file '30M.sample'
//
// [ ] Don't ask about future messages like this
//
// [Continue] [Die] [Dump Core] [Debugger] [Help]
// -------------------------------------------------------------
// To use this dialog:
// After constructor, use SetContext, SetMessage, EnableButton to
// determine what will be displayed. Then call n = ShowModal(). The return
// value tells which button was pressed (button_t types). Call GetDontAsk()
// to see if they checked "Don't ask about..." or not.
//////////////////////////////////////////////////////////////////////
class LogMsgAskDialog: public wxDialog
{
public:
enum button_t {
CONT=0, DIE, DUMP, DEBUG, HELP,
N_BUTTONS /* number of entries in enum */
};
#define LOG_MSG_ASK_IDS \
{ ID_Continue, ID_Die, ID_DumpCore, ID_Debugger, ID_Help }
#define LOG_MSG_ASK_NAMES \
{ "Continue", "Die", "Dump Core", "Debugger", "Help" }
#define LOG_MSG_DONT_ASK_STRING \
"Don't ask about future messages like this"
private:
wxStaticText *context, *message;
wxCheckBox *dontAsk;
bool enabled[N_BUTTONS];
wxBoxSizer *btnSizer, *vertSizer;
void Init (); // called automatically by ShowModal()
void showHelp ();
public:
LogMsgAskDialog(wxWindow* parent,
wxWindowID id,
const wxString& title);
void EnableButton (button_t btn, bool en) { enabled[(int)btn] = en; }
void SetContext (char *s);
void SetMessage (char *s);
bool GetDontAsk () { return dontAsk->GetValue (); }
void OnEvent (wxCommandEvent& event);
int ShowModal() { Init(); return wxDialog::ShowModal(); }
DECLARE_EVENT_TABLE()
};

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////
// $Id: wxmain.cc,v 1.9 2002-08-27 18:11:13 bdenney Exp $
// $Id: wxmain.cc,v 1.10 2002-08-28 03:20:23 bdenney Exp $
/////////////////////////////////////////////////////////////////
//
// wxmain.cc implements the wxWindows frame, toolbar, menus, and dialogs.
@ -51,7 +51,8 @@
#include "osdep.h" // workarounds for missing stuff
#include "gui/siminterface.h" // interface to the simulator
#include "bxversion.h" // get version string
#include "wxmain.h" // interface to the gui
#include "wxmain.h" // wxwindows shared stuff
#include "wxdialog.h" // custom dialog boxes
// include XPM icons
#include "bitmaps/cdromd.xpm"
@ -531,10 +532,6 @@ MyFrame::HandleAskParam (BxEvent *event)
void
MyFrame::OnSim2CuiEvent (wxCommandEvent& event)
{
static wxString choices[] = { "Continue", "Continue and Disable", "Die" };
int choice;
wxString string;
wxLogDebug ("received a bochs event in the GUI thread");
BxEvent *be = (BxEvent *) event.GetEventObject ();
wxLogDebug ("event type = %d", (int) be->type);
@ -548,31 +545,41 @@ MyFrame::OnSim2CuiEvent (wxCommandEvent& event)
// sync must return something; just return a copy of the event.
sim_thread->SendSyncResponse(be);
wxLogDebug ("after SendSyncResponse");
return;
case BX_ASYNC_EVT_SHUTDOWN_GUI:
wxLogDebug ("configuration interface is exiting");
Close (TRUE);
wxExit ();
return;
return;
case BX_SYNC_EVT_LOG_ASK:
case BX_ASYNC_EVT_LOG_MSG:
{
wxLogDebug ("log msg: level=%d, prefix='%s', msg='%s'",
be->u.logmsg.level,
be->u.logmsg.prefix,
be->u.logmsg.msg);
be->u.logmsg.level,
be->u.logmsg.prefix,
be->u.logmsg.msg);
if (be->type == BX_ASYNC_EVT_LOG_MSG) {
// don't ask for user response
return;
}
string.Printf ("%s", be->u.logmsg.msg);
choice = ::wxGetSingleChoiceIndex (
string,
wxString (SIM->get_log_level_name (be->u.logmsg.level)), 3, choices);
if (choice<0) choice = 2; // treat cancel the same as "die"
be->retcode = choice;
wxLogDebug ("you chose %d", choice);
wxString levelName (SIM->get_log_level_name (be->u.logmsg.level));
LogMsgAskDialog dlg (this, -1, levelName); // panic, error, etc.
#if !BX_DEBUGGER
dlg.EnableButton (dlg.DEBUG, FALSE);
#endif
dlg.SetContext (be->u.logmsg.prefix);
dlg.SetMessage (be->u.logmsg.msg);
int n = dlg.ShowModal ();
Boolean dontAsk = dlg.GetDontAsk ();
// turn the return value into the constant that logfunctions::ask is
// expecting. 0=continue, 1=continue but ignore future messages from this
// device, 2=die, 3=dump core, 4=debugger. FIXME: yuck. replace hardcoded
// constants in logfunctions::ask with enum or defined constant.
if (n==0) {
n = dontAsk? 1 : 0;
} else {
n=n+1;
}
be->retcode = n;
wxLogDebug ("you chose %d", n);
sim_thread->SendSyncResponse (be);
return;
}
default:
wxLogDebug ("OnSim2CuiEvent: event type %d ignored", (int)be->type);
// assume it's a synchronous event and send back a response, to avoid