/////////////////////////////////////////////////////////////////////////////
// Name: emulator.cpp
-// Purpose: Emulator wxWindows sample
+// Purpose: Emulator wxWidgets sample
// Author: Julian Smart
// Modified by:
// Created: 04/01/98
// declarations
// ============================================================================
-#ifdef __GNUG__
- #pragma implementation "emulator.h"
-#endif
-
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#endif
// for all others, include the necessary headers (this file is usually all you
-// need because it includes almost all "standard" wxWindows headers)
+// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
-#include "emulator.h"
+#include "wx/confbase.h"
+#include "wx/fileconf.h"
+#include "wx/cmdline.h"
+#include "wx/image.h"
+#include "wx/file.h"
+#include "wx/filename.h"
-#ifdef __WXX11__
+#ifdef __WXX11__
#include "wx/x11/reparent.h"
#endif
+#include "emulator.h"
+
// ----------------------------------------------------------------------------
// resources
// ----------------------------------------------------------------------------
// the application icon (under Windows and OS/2 it is in resources)
#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
- #include "mondrian.xpm"
+ #include "emulator.xpm"
#endif
// ----------------------------------------------------------------------------
-// event tables and other macros for wxWindows
+// event tables and other macros for wxWidgets
// ----------------------------------------------------------------------------
-// the event tables connect the wxWindows events with the functions (event
+// the event tables connect the wxWidgets events with the functions (event
// handlers) which process them. It can be also done at run-time, but for the
// simple menu events like this the static method is much simpler.
BEGIN_EVENT_TABLE(wxEmulatorFrame, wxFrame)
EVT_MENU(Emulator_Quit, wxEmulatorFrame::OnQuit)
EVT_MENU(Emulator_About, wxEmulatorFrame::OnAbout)
+ EVT_CLOSE(wxEmulatorFrame::OnCloseWindow)
END_EVENT_TABLE()
-// Create a new application object: this macro will allow wxWindows to create
+// Create a new application object: this macro will allow wxWidgets to create
// the application object during program execution (it's better than using a
// static object for many reasons) and also declares the accessor function
// wxGetApp() which will return the reference of the right type (i.e. wxEmulatorApp and
// not wxApp)
IMPLEMENT_APP(wxEmulatorApp)
+static const wxCmdLineEntryDesc sg_cmdLineDesc[] =
+{
+ { wxCMD_LINE_OPTION, "u", "use-display", "display number to use (default 100)" },
+
+ { wxCMD_LINE_SWITCH, "h", "help", "displays help on the command line parameters" },
+ { wxCMD_LINE_SWITCH, "v", "version", "print version" },
+
+ { wxCMD_LINE_PARAM, NULL, NULL, "config file 1", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
+
+ wxCMD_LINE_DESC_END
+};
+
+
// ============================================================================
// implementation
// ============================================================================
{
m_xnestWindow = NULL;
m_containerWindow = NULL;
+ m_displayNumber = wxT("100");
+ m_xnestPID = 0;
+
}
// 'Main program' equivalent: the program execution "starts" here
bool wxEmulatorApp::OnInit()
{
+#if wxUSE_LOG
+ wxLog::DisableTimestamp();
+#endif // wxUSE_LOG
wxInitAllImageHandlers();
- // create the main application window
- wxEmulatorFrame *frame = new wxEmulatorFrame(_T("wxEmulator"),
- wxPoint(50, 50), wxSize(450, 340));
-
- m_containerWindow = new wxEmulatorContainer(frame, -1);
+ wxString currentDir = wxGetCwd();
+
+ // Use argv to get current app directory
+ m_appDir = wxFindAppPath(argv[0], currentDir, wxT("WXEMUDIR"));
+
+ // If the development version, go up a directory.
+#ifdef __WXMSW__
+ if ((m_appDir.Right(5).CmpNoCase(_T("DEBUG")) == 0) ||
+ (m_appDir.Right(11).CmpNoCase(_T("DEBUGSTABLE")) == 0) ||
+ (m_appDir.Right(7).CmpNoCase(_T("RELEASE")) == 0) ||
+ (m_appDir.Right(13).CmpNoCase(_T("RELEASESTABLE")) == 0)
+ )
+ m_appDir = wxPathOnly(m_appDir);
+#endif
+
+ // Parse the command-line parameters and options
+ wxCmdLineParser parser(sg_cmdLineDesc, argc, argv);
+ int res;
+ {
+ wxLogNull log;
+ res = parser.Parse();
+ }
+ if (res == -1 || res > 0 || parser.Found(wxT("h")))
+ {
+#ifdef __X__
+ wxLog::SetActiveTarget(new wxLogStderr);
+#endif
+ parser.Usage();
+ return false;
+ }
+ if (parser.Found(wxT("v")))
+ {
+#ifdef __X__
+ wxLog::SetActiveTarget(new wxLogStderr);
+#endif
+ wxString msg;
+ msg.Printf(wxT("wxWidgets PDA Emulator (c) Julian Smart, 2002 Version %.2f, %s"), wxEMULATOR_VERSION, __DATE__);
+ wxLogMessage(msg);
+ return false;
+ }
+ if (parser.Found(wxT("u"), & m_displayNumber))
+ {
+ // Should only be number, so strip out anything before
+ // and including a : character
+ if (m_displayNumber.Find(wxT(':')) != -1)
+ {
+ m_displayNumber = m_displayNumber.AfterFirst(wxT(':'));
+ }
+ }
+ if (parser.GetParamCount() == 0)
+ {
+ m_emulatorInfo.m_emulatorFilename = wxT("default.wxe");
+ }
+ else if (parser.GetParamCount() > 0)
+ {
+ m_emulatorInfo.m_emulatorFilename = parser.GetParam(0);
+ }
// Load the emulation info
- if (!LoadEmulator())
+ if (!LoadEmulator(m_appDir))
{
- frame->Destroy();
- wxMessageBox(wxT("Sorry, could not load this emulator. Please check bitmaps are valid."));
- return FALSE;
+ //wxMessageBox(wxT("Sorry, could not load this emulator. Please check bitmaps are valid."));
+ return false;
}
-
- if (m_emulatorInfo.m_emulatorBackgroundBitmap.Ok())
- frame->SetClientSize(m_emulatorInfo.m_emulatorBackgroundBitmap.GetWidth(),
- m_emulatorInfo.m_emulatorBackgroundBitmap.GetHeight());
-
+
+ // create the main application window
+ wxEmulatorFrame *frame = new wxEmulatorFrame(_T("wxEmulator"),
+ wxPoint(50, 50), wxSize(450, 340));
+
+#if wxUSE_STATUSBAR
+ frame->SetStatusText(m_emulatorInfo.m_emulatorTitle, 0);
+
+ wxString sizeStr;
+ sizeStr.Printf(wxT("Screen: %dx%d"), (int) m_emulatorInfo.m_emulatorScreenSize.x,
+ (int) m_emulatorInfo.m_emulatorScreenSize.y);
+ frame->SetStatusText(sizeStr, 1);
+#endif // wxUSE_STATUSBAR
+
+ m_containerWindow = new wxEmulatorContainer(frame, wxID_ANY);
+
+ frame->SetClientSize(m_emulatorInfo.m_emulatorDeviceSize.x,
+ m_emulatorInfo.m_emulatorDeviceSize.y);
+
// and show it (the frames, unlike simple controls, are not shown when
// created initially)
- frame->Show(TRUE);
-
-#ifdef __WXX11__
+ frame->Show(true);
+
+#ifdef __WXX11__
m_xnestWindow = new wxAdoptedWindow;
wxString cmd;
- cmd.Printf(wxT("Xnest :100 -geometry %dx%d+50+50"),
- (int) m_emulatorScreenSize.x, (int) m_emulatorScreenSize.y);
-
- // Asynchronously executes Xnest
- if (0 == wxExecute(cmd))
+ cmd.Printf(wxT("Xnest :%s -geometry %dx%d"),
+ m_displayNumber.c_str(),
+ (int) m_emulatorInfo.m_emulatorScreenSize.x,
+ (int) m_emulatorInfo.m_emulatorScreenSize.y);
+
+ // Asynchronously executes Xnest
+ m_xnestPID = wxExecute(cmd);
+ if (0 == m_xnestPID)
{
frame->Destroy();
wxMessageBox(wxT("Sorry, could not run Xnest. Please check your PATH."));
- return FALSE;
+ return false;
}
-
+
wxReparenter reparenter;
if (!reparenter.WaitAndReparent(m_containerWindow, m_xnestWindow, wxT("Xnest")))
{
wxMessageBox(wxT("Sorry, could not reparent Xnest.."));
frame->Destroy();
- return FALSE;
+ return false;
}
+
#endif
+ m_containerWindow->DoResize();
// success: wxApp::OnRun() will be called which will enter the main message
- // loop and the application will run. If we returned FALSE here, the
+ // loop and the application will run. If we returned false here, the
// application would exit immediately.
- return TRUE;
+ return true;
}
-// Load the specified emulator.
-// For now, hard-wired. TODO: make this configurable
-bool wxEmulatorApp::LoadEmulator()
+// Prepend the current program directory to the name
+wxString wxEmulatorApp::GetFullAppPath(const wxString& filename) const
{
- m_emulatorInfo.m_emulatorTitle = wxT("iPAQ Emulator");
-
- m_emulatorInfo.m_emulatorDescription = wxT("No description yet");
-
- // The offset from the top-left of the main emulator
- // bitmap and the virtual screen (where Xnest is
- // positioned)
- m_emulatorInfo.m_emulatorScreenPosition = wxPoint(45, 57);
+ wxString path(m_appDir);
+ if (path.Last() != '\\' && path.Last() != '/' && filename[0] != '\\' && filename[0] != '/')
+#ifdef __X__
+ path += '/';
+#else
+ path += '\\';
+#endif
+ path += filename;
- // The emulated screen size
- m_emulatorInfo.m_emulatorScreenSize = wxSize(240, 320);
+ return path;
+}
- m_emulatorInfo.m_emulatorBackgroundBitmapName = wxT("ipaq01.jpg");
- m_emulatorInfo.m_emulatorBackgroundColour = * wxBLACK;
-
- return m_emulatorInfo.Load();
+// Load the specified emulator.
+// For now, hard-wired. TODO: make this configurable
+bool wxEmulatorApp::LoadEmulator(const wxString& appDir)
+{
+ // Load config file and bitmaps
+ return m_emulatorInfo.Load(appDir);
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// frame constructor
-wxEmulatorFrame::wxEmulatorFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
- : wxFrame(NULL, -1, title, pos, size)
+wxEmulatorFrame::wxEmulatorFrame(const wxString& title,
+ const wxPoint& pos, const wxSize& size)
+ : wxFrame(NULL, wxID_ANY, title, pos, size)
{
// set the frame icon
- SetIcon(wxICON(mondrian));
+ SetIcon(wxICON(emulator));
#if wxUSE_MENUS
// create a menu bar
#if wxUSE_STATUSBAR
// create a status bar just for fun (by default with 1 pane only)
CreateStatusBar(2);
- SetStatusText(_T("Welcome to wxWindows!"));
#endif // wxUSE_STATUSBAR
}
void wxEmulatorFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
- // TRUE is to force the frame to close
- Close(TRUE);
+ // true is to force the frame to close
+ Close(true);
}
void wxEmulatorFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
wxMessageBox(msg, _T("About wxEmulator"), wxOK | wxICON_INFORMATION, this);
}
+void wxEmulatorFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
+{
+#ifdef __WXX11__
+ if (wxGetApp().m_xnestWindow)
+ {
+ wxGetApp().m_xnestWindow->SetHandle((WXWindow) NULL);
+ }
+#endif
+ this->Destroy();
+ if (wxGetApp().m_xnestPID > 0)
+ {
+ wxKill(wxGetApp().m_xnestPID);
+ wxGetApp().m_xnestPID = 0;
+ }
+}
+
IMPLEMENT_CLASS(wxEmulatorContainer, wxWindow)
BEGIN_EVENT_TABLE(wxEmulatorContainer, wxWindow)
{
}
-void wxEmulatorContainer::OnSize(wxSizeEvent& event)
+void wxEmulatorContainer::OnSize(wxSizeEvent& WXUNUSED(event))
+{
+ DoResize();
+}
+
+void wxEmulatorContainer::DoResize()
{
wxSize sz = GetClientSize();
- if (wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.Ok() &&
- wxGetApp().m_xnestWindow)
+ if (wxGetApp().m_xnestWindow
+#ifdef __WXX11__
+ && wxGetApp().m_xnestWindow->GetMainWindow()
+#endif
+ )
{
- int bitmapWidth = wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.GetWidth();
- int bitmapHeight = wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.GetHeight();
-
- int x = wxMax(0, (sz.x - bitmapWidth)/2.0);
- int y = wxMax(0, (sz.y - bitmapHeight)/2.0);
-
+ int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x;
+ int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y;
+
+ int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0));
+ int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0));
+
x += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.x;
y += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.y;
-
+
wxGetApp().m_xnestWindow->Move(x, y);
}
Refresh();
}
-void wxEmulatorContainer::OnPaint(wxPaintEvent& event)
+void wxEmulatorContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
{
wxPaintDC dc(this);
-
+
wxSize sz = GetClientSize();
if (wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.Ok())
{
- int bitmapWidth = wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.GetWidth();
- int bitmapHeight = wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.GetHeight();
-
- int x = wxMax(0, (sz.x - bitmapWidth)/2.0);
- int y = wxMax(0, (sz.y - bitmapHeight)/2.0);
-
+ int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x;
+ int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y;
+
+ int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0));
+ int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0));
+
dc.DrawBitmap(wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap, x, y);
}
}
void wxEmulatorContainer::OnEraseBackground(wxEraseEvent& event)
{
- wxDC* dc = NULL;
-
+ wxDC* dc wxDUMMY_INITIALIZE(NULL);
+
if (event.GetDC())
{
dc = event.GetDC();
{
dc = new wxClientDC(this);
}
-
+
dc->SetBackground(wxBrush(wxGetApp().m_emulatorInfo.m_emulatorBackgroundColour, wxSOLID));
dc->Clear();
-
+
if (!event.GetDC())
delete dc;
}
void wxEmulatorInfo::Copy(const wxEmulatorInfo& info)
{
+ m_emulatorFilename = info.m_emulatorFilename;
m_emulatorTitle = info.m_emulatorTitle;
m_emulatorDescription = info.m_emulatorDescription;
m_emulatorScreenPosition = info.m_emulatorScreenPosition;
m_emulatorBackgroundBitmap = info.m_emulatorBackgroundBitmap;
m_emulatorBackgroundBitmapName = info.m_emulatorBackgroundBitmapName;
m_emulatorBackgroundColour = info.m_emulatorBackgroundColour;
+ m_emulatorDeviceSize = info.m_emulatorDeviceSize;
}
// Initialisation
void wxEmulatorInfo::Init()
{
+ m_emulatorDeviceSize = wxSize(260, 340);
+ m_emulatorScreenSize = wxSize(240, 320);
}
// Loads bitmaps
-bool wxEmulatorInfo::Load()
+bool wxEmulatorInfo::Load(const wxString& appDir)
{
- if (m_emulatorBackgroundBitmapName.IsEmpty())
- return FALSE;
-
- // TODO: prepend current directory if relative name
- int type = wxDetermineImageType(m_emulatorBackgroundBitmapName);
- if (type == -1)
- return FALSE;
-
- return m_emulatorBackgroundBitmap.LoadFile(m_emulatorBackgroundBitmapName, type);
+ // Try to find absolute path
+ wxString absoluteConfigPath = m_emulatorFilename;
+ if ( !::wxIsAbsolutePath(absoluteConfigPath) )
+ {
+ wxString currDir = wxGetCwd();
+ absoluteConfigPath = currDir + wxString(wxFILE_SEP_PATH) + m_emulatorFilename;
+ if ( !wxFile::Exists(absoluteConfigPath) )
+ {
+ absoluteConfigPath = appDir + wxString(wxFILE_SEP_PATH)
+ + m_emulatorFilename;
+ }
+ }
+
+ if ( !wxFile::Exists(absoluteConfigPath) )
+ {
+ wxString str;
+ str.Printf( wxT("Could not find config file %s"),
+ absoluteConfigPath.c_str() );
+
+ wxMessageBox(str);
+ return false;
+ }
+
+ wxString rootPath = wxPathOnly(absoluteConfigPath);
+
+ {
+ wxFileConfig config(wxT("wxEmulator"), wxT("wxWidgets"),
+ absoluteConfigPath, wxEmptyString, wxCONFIG_USE_LOCAL_FILE);
+
+ config.Read(wxT("/General/title"), & m_emulatorTitle);
+ config.Read(wxT("/General/description"), & m_emulatorDescription);
+ config.Read(wxT("/General/backgroundBitmap"), & m_emulatorBackgroundBitmapName);
+
+ wxString colString;
+ if (config.Read(wxT("/General/backgroundColour"), & colString) ||
+ config.Read(wxT("/General/backgroundColor"), & colString)
+ )
+ {
+ m_emulatorBackgroundColour = wxHexStringToColour(colString);
+ }
+
+ int x = 0, y = 0, w = 0, h = 0, dw = 0, dh = 0;
+ config.Read(wxT("/General/screenX"), & x);
+ config.Read(wxT("/General/screenY"), & y);
+ config.Read(wxT("/General/screenWidth"), & w);
+ config.Read(wxT("/General/screenHeight"), & h);
+ if (config.Read(wxT("/General/deviceWidth"), & dw) && config.Read(wxT("/General/deviceHeight"), & dh))
+ {
+ m_emulatorDeviceSize = wxSize(dw, dh);
+ }
+
+ m_emulatorScreenPosition = wxPoint(x, y);
+ m_emulatorScreenSize = wxSize(w, h);
+ }
+
+ if (!m_emulatorBackgroundBitmapName.empty())
+ {
+ wxString absoluteBackgroundBitmapName = rootPath + wxString(wxFILE_SEP_PATH) + m_emulatorBackgroundBitmapName;
+ if ( !wxFile::Exists(absoluteBackgroundBitmapName) )
+ {
+ wxString str;
+ str.Printf( wxT("Could not find bitmap %s"),
+ absoluteBackgroundBitmapName.c_str() );
+ wxMessageBox(str);
+ return false;
+ }
+
+ wxBitmapType type = wxDetermineImageType(m_emulatorBackgroundBitmapName);
+ if (type == wxBITMAP_TYPE_INVALID)
+ return false;
+
+ if (!m_emulatorBackgroundBitmap.LoadFile(m_emulatorBackgroundBitmapName, type))
+ {
+ wxString str;
+ str.Printf( wxT("Could not load bitmap file %s"),
+ m_emulatorBackgroundBitmapName.c_str() );
+ wxMessageBox(str);
+ return false;
+ }
+
+ m_emulatorDeviceSize = wxSize(m_emulatorBackgroundBitmap.GetWidth(),
+ m_emulatorBackgroundBitmap.GetHeight());
+ }
+ return true;
}
// Returns the image type, or -1, determined from the extension.
-int wxDetermineImageType(const wxString& filename)
+wxBitmapType wxDetermineImageType(const wxString& filename)
{
wxString path, name, ext;
- wxSplitPath(filename, & path, & name, & ext);
+ wxFileName::SplitPath(filename, & path, & name, & ext);
ext.MakeLower();
- if (ext == "jpg" || ext == "jpeg")
+ if (ext == _T("jpg") || ext == _T("jpeg"))
return wxBITMAP_TYPE_JPEG;
- else if (ext == "gif")
+ if (ext == _T("gif"))
return wxBITMAP_TYPE_GIF;
- else if (ext == "bmp")
+ if (ext == _T("bmp"))
return wxBITMAP_TYPE_BMP;
- else if (ext == "png")
+ if (ext == _T("png"))
return wxBITMAP_TYPE_PNG;
- else if (ext == "pcx")
+ if (ext == _T("pcx"))
return wxBITMAP_TYPE_PCX;
- else if (ext == "tif" || ext == "tiff")
+ if (ext == _T("tif") || ext == _T("tiff"))
return wxBITMAP_TYPE_TIF;
- else
- return -1;
+
+ return wxBITMAP_TYPE_INVALID;
}
+// Convert a colour to a 6-digit hex string
+wxString wxColourToHexString(const wxColour& col)
+{
+ wxString hex;
+
+ hex += wxDecToHex(col.Red());
+ hex += wxDecToHex(col.Green());
+ hex += wxDecToHex(col.Blue());
+
+ return hex;
+}
+
+// Convert 6-digit hex string to a colour
+wxColour wxHexStringToColour(const wxString& hex)
+{
+ unsigned char r = (unsigned char)wxHexToDec(hex.Mid(0, 2));
+ unsigned char g = (unsigned char)wxHexToDec(hex.Mid(2, 2));
+ unsigned char b = (unsigned char)wxHexToDec(hex.Mid(4, 2));
+
+ return wxColour(r, g, b);
+}
+
+// Find the absolute path where this application has been run from.
+// argv0 is wxTheApp->argv[0]
+// cwd is the current working directory (at startup)
+// appVariableName is the name of a variable containing the directory for this app, e.g.
+// MYAPPDIR. This is checked first.
+
+wxString wxFindAppPath(const wxString& argv0, const wxString& cwd, const wxString& appVariableName)
+{
+ wxString str;
+
+ // Try appVariableName
+ if (!appVariableName.empty())
+ {
+ str = wxGetenv(appVariableName);
+ if (!str.empty())
+ return str;
+ }
+
+ if (wxIsAbsolutePath(argv0))
+ return wxPathOnly(argv0);
+ else
+ {
+ // Is it a relative path?
+ wxString currentDir(cwd);
+ if (!wxEndsWithPathSeparator(currentDir))
+ currentDir += wxFILE_SEP_PATH;
+
+ str = currentDir + argv0;
+ if ( wxFile::Exists(str) )
+ return wxPathOnly(str);
+ }
+
+ // OK, it's neither an absolute path nor a relative path.
+ // Search PATH.
+
+ wxPathList pathList;
+ pathList.AddEnvList(wxT("PATH"));
+ str = pathList.FindAbsoluteValidPath(argv0);
+ if (!str.empty())
+ return wxPathOnly(str);
+
+ // Failed
+ return wxEmptyString;
+}