Bochs/bochs/gui/wxdialog.cc
Bryce Denney 17da6fe3c1 - add HDConfigDialog box for wxWindows for editing hard disk params.
Now you can edit floppy and hard disk parameters using dialogs.
2002-08-28 15:27:26 +00:00

650 lines
19 KiB
C++

/////////////////////////////////////////////////////////////////
// $Id: wxdialog.cc,v 1.3 2002-08-28 15:27:25 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/spinctrl.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_Button1,
ID_Button2,
ID_MY_LAST_ID
};
void ChangeStaticText (wxSizer *sizer, wxStaticText *win, wxString newtext);
//////////////////////////////////////////////////////////////////////
// LogMsgAskDialog implementation
//////////////////////////////////////////////////////////////////////
// Structure:
// vertSizer:
// context text field,
// message text field
// don't-ask checkbox
// buttonSizer:
// continue button
// die button
// dumpcore button
// debugger button
// help button
//
// 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(wxHELP, 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 wxHELP: 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 );
}
//////////////////////////////////////////////////////////////////////
// FloppyConfigDialog implementation
//////////////////////////////////////////////////////////////////////
// Structure:
// vertSizer:
// instructions
// radioSizer (vert):
// phys0
// phys1
// diskImageSizer (horiz):
// disk image file
// filename
// browse button
// capacitySizer (horizontal):
// capacity text
// capacity choice box
// hint text
// buttonSizer:
// cancel button
// ok button
// help button
//
// all events go to OnEvent method
BEGIN_EVENT_TABLE(FloppyConfigDialog, wxDialog)
EVT_BUTTON(-1, FloppyConfigDialog::OnEvent)
EVT_TEXT(-1, FloppyConfigDialog::OnEvent)
END_EVENT_TABLE()
FloppyConfigDialog::FloppyConfigDialog(
wxWindow* parent,
wxWindowID id)
: wxDialog (parent, id, "", wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
validate = NULL;
n_rbtns = 0;
wxButton *btn;
vertSizer = new wxBoxSizer (wxVERTICAL);
instr = new wxStaticText (this, -1, FLOPPY_CONFIG_INSTRS);
radioSizer = new wxBoxSizer (wxVERTICAL);
diskImageSizer = new wxBoxSizer (wxHORIZONTAL);
capacitySizer = new wxBoxSizer (wxHORIZONTAL);
wxStaticText *hint = new wxStaticText (this, -1, FLOPPY_CONFIG_HINT);
buttonSizer = new wxBoxSizer (wxHORIZONTAL);
// add top level components to vertSizer
vertSizer->Add (instr, 0, wxTOP|wxLEFT, 30);
vertSizer->Add (radioSizer, 0, wxLEFT, 50);
vertSizer->Add (capacitySizer, 0, wxTOP|wxLEFT, 30);
vertSizer->Add (hint, 0, wxTOP|wxLEFT, 30);
vertSizer->Add (buttonSizer, 0, wxALIGN_RIGHT|wxTOP, 30);
// contents of capacitySizer
wxStaticText *captext = new wxStaticText (this, -1, FLOPPY_CONFIG_CAP);
capacity = new wxChoice (this, -1);
capacitySizer->Add (captext, 0, wxALL, 5);
capacitySizer->Add (capacity, 0, wxALL, 5);
// contents of buttonSizer
btn = new wxButton (this, wxHELP, "Help");
buttonSizer->Add (btn, 0, wxALL, 5);
btn = new wxButton (this, wxCANCEL, "Cancel");
buttonSizer->Add (btn, 0, wxALL, 5);
btn = new wxButton (this, wxOK, "Ok");
buttonSizer->Add (btn, 0, wxALL, 5);
// create filename and diskImageRadioBtn so that we can tweak them before
// Init comes. However don't add it to any sizer yet because it needs to go
// in after the last radio button.
filename = new wxTextCtrl (this, ID_FilenameText);
filename->SetSize (300, filename->GetSize ().GetHeight ());
diskImageRadioBtn = new wxRadioButton (this, ID_Filename, FLOPPY_CONFIG_DISKIMG);
// the radioSizer contents will be added by successive calls to
// AddRadio(). The diskImageSizer will be added last, in Init().
}
void FloppyConfigDialog::AddRadio (char *description, char *filename)
{
if (n_rbtns >= MAX_RBTNS) {
wxLogError ("AddRadio failed: increase MAX_RBTNS in wxdialog.h");
return;
}
rbtn[n_rbtns] = new wxRadioButton (this, -1, description);
equivalentFilename[n_rbtns] = filename;
radioSizer->Add (rbtn[n_rbtns]);
n_rbtns++;
}
void FloppyConfigDialog::SetDriveName (char *name)
{
wxString text;
text.Printf (FLOPPY_CONFIG_TITLE, name);
SetTitle (text);
text.Printf (FLOPPY_CONFIG_INSTRS, name);
ChangeStaticText (vertSizer, instr, text);
}
void FloppyConfigDialog::SetCapacityChoices (int n, char *choices[])
{
for (int i=0; i<n; i++)
capacity->Append (wxString (choices[i]));
}
void FloppyConfigDialog::Init()
{
// add contents of diskImageSizer
diskImageSizer->Add (diskImageRadioBtn);
diskImageSizer->Add (filename, 1, wxGROW);
wxButton *btn = new wxButton (this, ID_Browse, "<--Browse");
diskImageSizer->Add (btn, 0, wxALL, 5);
radioSizer->Add (diskImageSizer);
SetAutoLayout(TRUE);
SetSizer(vertSizer);
vertSizer->Fit (this);
wxSize size = vertSizer->GetMinSize ();
printf ("minsize is %d,%d\n", size.GetWidth(), size.GetHeight ());
int margin = 5;
SetSizeHints (size.GetWidth () + margin, size.GetHeight () + margin);
Center ();
}
int
FloppyConfigDialog::GetRadio () {
int i;
for (i=0; i<n_rbtns; i++) {
if (rbtn[i]->GetValue ())
return i;
}
if (diskImageRadioBtn->GetValue ()) {
return i;
}
wxLogError ("GetRadio() found nothing selected");
return 0;
}
void
FloppyConfigDialog::SetRadio (int n) {
if (n < n_rbtns) {
rbtn[n]->SetValue (TRUE);
} else {
diskImageRadioBtn->SetValue (TRUE);
}
}
void FloppyConfigDialog::SetFilename (char *f) {
// search equivalentFilename[] for matches. if it matches, select the
// radio button instead.
for (int i=0; i<n_rbtns; i++) {
if (!strcmp (f, equivalentFilename[i])) {
rbtn[i]->SetValue (TRUE);
return; // leaving filename text field unchanged
}
}
filename->SetValue (f);
}
char *FloppyConfigDialog::GetFilename ()
{
int n = GetRadio ();
if (n < n_rbtns) {
return equivalentFilename[n];
} else {
return (char *)filename->GetValue ().c_str ();
}
}
void FloppyConfigDialog::OnEvent(wxCommandEvent& event)
{
int id = event.GetId ();
printf ("you pressed button id=%d\n", id);
switch (id) {
case ID_FilenameText:
// when you type into the filename field, ensure that the radio
// button associated with that field is chosen.
diskImageRadioBtn->SetValue (TRUE);
break;
case wxOK:
// probably should validate before allowing ok
if (validate!=NULL && !(*validate)(this))
return; // validation failed, don't leave yet
EndModal (0);
break;
case ID_Browse:
{
long style = wxOPEN;
wxFileDialog *fdialog = new wxFileDialog (this, filename->GetValue (), "", "", "*.*", style);
if (fdialog->ShowModal () == wxID_OK)
SetFilename ((char *)fdialog->GetPath().c_str ());
}
break;
case wxCANCEL:
EndModal (-1);
break;
case wxHELP:
ShowHelp();
break;
}
}
void FloppyConfigDialog::ShowHelp ()
{
wxMessageBox("No help is available yet.", "No Help", wxOK | wxICON_ERROR );
}
//////////////////////////////////////////////////////////////////////
// HDConfigDialog implementation
//////////////////////////////////////////////////////////////////////
// Structure:
// vertSizer:
// enable checkbox
// hsizer[0]:
// "Disk image:"
// disk image text control
// browse button
// hsizer[1]:
// "Geometry: cylinders"
// geom[0] = cyl control
// "heads"
// geom[1] = heads control
// " sectors/track "
// geom[2] = spt control
// hsizer[2]:
// "Size in MB: "
// megs text control
// buttonSizer:
// help
// cancel
// ok
// all events go to OnEvent method
BEGIN_EVENT_TABLE(HDConfigDialog, wxDialog)
EVT_BUTTON(-1, HDConfigDialog::OnEvent)
EVT_CHECKBOX(-1, HDConfigDialog::OnEvent)
EVT_TEXT(-1, HDConfigDialog::OnEvent)
END_EVENT_TABLE()
HDConfigDialog::HDConfigDialog(
wxWindow* parent,
wxWindowID id)
: wxDialog (parent, id, "", wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
computeMegs = TRUE;
static char *geomNames[] = HD_CONFIG_GEOM_NAMES;
vertSizer = new wxBoxSizer (wxVERTICAL);
enable = new wxCheckBox (this, ID_Enable, "Enabled");
enable->SetValue (TRUE);
hsizer[0] = new wxBoxSizer (wxHORIZONTAL);
hsizer[1] = new wxBoxSizer (wxHORIZONTAL);
hsizer[2] = new wxBoxSizer (wxHORIZONTAL);
buttonSizer = new wxBoxSizer (wxHORIZONTAL);
// add top level components to vertSizer
vertSizer->Add (enable, 0, wxTOP|wxLEFT, 30);
vertSizer->Add (hsizer[0], 0, wxLEFT, 30);
vertSizer->Add (hsizer[1], 0, wxLEFT, 30);
vertSizer->Add (hsizer[2], 0, wxLEFT, 30);
vertSizer->Add (buttonSizer, 0, wxALIGN_RIGHT|wxTOP, 10);
// contents of hsizer[0]
wxStaticText *text;
text = new wxStaticText (this, -1, HD_CONFIG_DISKIMG);
hsizer[0]->Add (text);
filename = new wxTextCtrl (this, ID_FilenameText);
filename->SetSize (300, filename->GetSize ().GetHeight ());
hsizer[0]->Add (filename, 1);
wxButton *btn = new wxButton (this, ID_Browse, "<--Browse");
hsizer[0]->Add (btn);
// contents of hsizer[1]
for (int i=0; i<3; i++) {
text = new wxStaticText (this, -1, geomNames[i]);
hsizer[1]->Add (text);
geom[i] = new wxSpinCtrl (this, ID_Cylinders+i);
hsizer[1]->Add (geom[i]);
}
// contents of hsizer[2]
text = new wxStaticText (this, ID_Megs, HD_CONTROL_MEGS); // size in megs
hsizer[2]->Add (text);
megs = new wxTextCtrl (this, -1);
hsizer[2]->Add (megs);
// contents of buttonSizer
btn = new wxButton (this, wxHELP, "Help");
buttonSizer->Add (btn, 0, wxALL, 5);
btn = new wxButton (this, wxCANCEL, "Cancel");
buttonSizer->Add (btn, 0, wxALL, 5);
btn = new wxButton (this, wxOK, "Ok");
buttonSizer->Add (btn, 0, wxALL, 5);
// lay it out!
SetAutoLayout(TRUE);
SetSizer(vertSizer);
vertSizer->Fit (this);
wxSize size = vertSizer->GetMinSize ();
printf ("minsize is %d,%d\n", size.GetWidth(), size.GetHeight ());
int margin = 5;
SetSizeHints (size.GetWidth () + margin, size.GetHeight () + margin);
Center ();
}
void HDConfigDialog::SetDriveName (char *name)
{
wxString text;
text.Printf (HD_CONFIG_TITLE, name);
SetTitle (text);
}
void HDConfigDialog::SetGeom (int n, int value) {
printf ("setting geom[%d] to %d\n", n, value);
geom[n]->SetValue (value);
printf ("now geom[%d] has value %d\n", n, geom[n]->GetValue ());
if (computeMegs) ComputeMegs ();
}
void HDConfigDialog::ComputeMegs () {
float meg = 512.0
* geom[0]->GetValue ()
* geom[1]->GetValue ()
* geom[2]->GetValue ()
/ (1024.0*1024.0);
wxString text;
text.Printf ("%.1f", meg);
megs->SetValue (text);
}
void HDConfigDialog::Init()
{
}
void HDConfigDialog::SetFilename (char *f) {
if (!strcmp (f, "none")) {
enable->SetValue (FALSE);
// trick event handler into updating the state
printf ("sending fake ID_Enable event to OnEvent\n");
wxCommandEvent fakeCheckboxEvent;
fakeCheckboxEvent.SetId (ID_Enable);
OnEvent (fakeCheckboxEvent);
}
filename->SetValue (wxString (f));
}
char *HDConfigDialog::GetFilename ()
{
if (enable->GetValue ())
return (char *)filename->GetValue().c_str ();
else
return "none";
}
void HDConfigDialog::OnEvent(wxCommandEvent& event)
{
int id = event.GetId ();
printf ("you pressed button id=%d\n", id);
switch (id) {
case ID_Cylinders:
case ID_Heads:
case ID_SPT:
if (computeMegs) ComputeMegs ();
break;
case ID_Enable:
{
bool en = enable->GetValue ();
filename->Enable (en);
for (int i=0; i<3; i++) geom[i]->Enable (en);
megs->Enable (en);
}
break;
case ID_Megs:
break;
case wxOK:
// probably should validate before allowing ok
EndModal (0);
break;
case ID_Browse:
{
long style = wxOPEN;
wxFileDialog *fdialog = new wxFileDialog (this, filename->GetValue (), "", "", "*.*", style);
if (fdialog->ShowModal () == wxID_OK)
SetFilename ((char *)fdialog->GetPath().c_str ());
}
break;
case wxCANCEL:
EndModal (-1);
break;
case wxHELP:
ShowHelp();
break;
default:
event.Skip ();
}
}
void HDConfigDialog::ShowHelp ()
{
wxMessageBox("No help is available yet.", "No Help", wxOK | wxICON_ERROR );
}
/////////////////////////////////////////////////////////////////
// utility
/////////////////////////////////////////////////////////////////
// Unfortunately this step is necessary if you change the text of
// a wxStaticText. 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