1
/////////////////////////////////////////////////////////////////////////////
3
// Purpose: Emulator wxWidgets sample
4
// Author: Julian Smart
7
// RCS-ID: $Id: emulator.cpp,v 1.15 2005/02/01 20:36:10 ABX Exp $
8
// Copyright: (c) Julian Smart
9
// Licence: wxWindows licence
10
/////////////////////////////////////////////////////////////////////////////
12
// ============================================================================
14
// ============================================================================
16
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
17
#pragma implementation "emulator.h"
20
// ----------------------------------------------------------------------------
22
// ----------------------------------------------------------------------------
24
// For compilers that support precompilation, includes "wx/wx.h".
25
#include "wx/wxprec.h"
31
// for all others, include the necessary headers (this file is usually all you
32
// need because it includes almost all "standard" wxWidgets headers)
37
#include "wx/confbase.h"
38
#include "wx/fileconf.h"
39
#include "wx/cmdline.h"
44
#include "wx/x11/reparent.h"
49
// ----------------------------------------------------------------------------
51
// ----------------------------------------------------------------------------
53
// the application icon (under Windows and OS/2 it is in resources)
54
#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
55
#include "emulator.xpm"
58
// ----------------------------------------------------------------------------
59
// event tables and other macros for wxWidgets
60
// ----------------------------------------------------------------------------
62
// the event tables connect the wxWidgets events with the functions (event
63
// handlers) which process them. It can be also done at run-time, but for the
64
// simple menu events like this the static method is much simpler.
65
BEGIN_EVENT_TABLE(wxEmulatorFrame, wxFrame)
66
EVT_MENU(Emulator_Quit, wxEmulatorFrame::OnQuit)
67
EVT_MENU(Emulator_About, wxEmulatorFrame::OnAbout)
68
EVT_CLOSE(wxEmulatorFrame::OnCloseWindow)
71
// Create a new application object: this macro will allow wxWidgets to create
72
// the application object during program execution (it's better than using a
73
// static object for many reasons) and also declares the accessor function
74
// wxGetApp() which will return the reference of the right type (i.e. wxEmulatorApp and
76
IMPLEMENT_APP(wxEmulatorApp)
78
static const wxCmdLineEntryDesc sg_cmdLineDesc[] =
80
{ wxCMD_LINE_OPTION, _T("u"), _T("use-display"), _T("display number to use (default 100)"), (wxCmdLineParamType)0, 0 },
82
{ wxCMD_LINE_SWITCH, _T("h"), _T("help"), _T("displays help on the command line parameters"), (wxCmdLineParamType)0, 0 },
83
{ wxCMD_LINE_SWITCH, _T("v"), _T("version"), _T("print version"), (wxCmdLineParamType)0, 0 },
85
{ wxCMD_LINE_PARAM, NULL, NULL, _T("config file 1"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
87
{ wxCMD_LINE_NONE, NULL, NULL, NULL, (wxCmdLineParamType)0, 0 }
91
// ============================================================================
93
// ============================================================================
95
// ----------------------------------------------------------------------------
96
// the application class
97
// ----------------------------------------------------------------------------
99
wxEmulatorApp::wxEmulatorApp()
101
m_xnestWindow = NULL;
102
m_containerWindow = NULL;
103
m_displayNumber = wxT("100");
108
// 'Main program' equivalent: the program execution "starts" here
109
bool wxEmulatorApp::OnInit()
112
wxLog::SetTimestamp(NULL);
114
wxInitAllImageHandlers();
116
wxString currentDir = wxGetCwd();
118
// Use argv to get current app directory
119
m_appDir = wxFindAppPath(argv[0], currentDir, wxT("WXEMUDIR"));
121
// If the development version, go up a directory.
123
if ((m_appDir.Right(5).CmpNoCase(_T("DEBUG")) == 0) ||
124
(m_appDir.Right(11).CmpNoCase(_T("DEBUGSTABLE")) == 0) ||
125
(m_appDir.Right(7).CmpNoCase(_T("RELEASE")) == 0) ||
126
(m_appDir.Right(13).CmpNoCase(_T("RELEASESTABLE")) == 0)
128
m_appDir = wxPathOnly(m_appDir);
131
// Parse the command-line parameters and options
132
wxCmdLineParser parser(sg_cmdLineDesc, argc, argv);
136
res = parser.Parse();
138
if (res == -1 || res > 0 || parser.Found(wxT("h")))
141
wxLog::SetActiveTarget(new wxLogStderr);
146
if (parser.Found(wxT("v")))
149
wxLog::SetActiveTarget(new wxLogStderr);
152
msg.Printf(wxT("wxWidgets PDA Emulator (c) Julian Smart, 2002 Version %.2f, %s"), wxEMULATOR_VERSION, __DATE__);
156
if (parser.Found(wxT("u"), & m_displayNumber))
158
// Should only be number, so strip out anything before
159
// and including a : character
160
if (m_displayNumber.Find(wxT(':')) != -1)
162
m_displayNumber = m_displayNumber.AfterFirst(wxT(':'));
165
if (parser.GetParamCount() == 0)
167
m_emulatorInfo.m_emulatorFilename = wxT("default.wxe");
169
else if (parser.GetParamCount() > 0)
171
m_emulatorInfo.m_emulatorFilename = parser.GetParam(0);
174
// Load the emulation info
175
if (!LoadEmulator(m_appDir))
177
//wxMessageBox(wxT("Sorry, could not load this emulator. Please check bitmaps are valid."));
181
// create the main application window
182
wxEmulatorFrame *frame = new wxEmulatorFrame(_T("wxEmulator"),
183
wxPoint(50, 50), wxSize(450, 340));
186
frame->SetStatusText(m_emulatorInfo.m_emulatorTitle, 0);
189
sizeStr.Printf(wxT("Screen: %dx%d"), (int) m_emulatorInfo.m_emulatorScreenSize.x,
190
(int) m_emulatorInfo.m_emulatorScreenSize.y);
191
frame->SetStatusText(sizeStr, 1);
192
#endif // wxUSE_STATUSBAR
194
m_containerWindow = new wxEmulatorContainer(frame, wxID_ANY);
196
frame->SetClientSize(m_emulatorInfo.m_emulatorDeviceSize.x,
197
m_emulatorInfo.m_emulatorDeviceSize.y);
199
// and show it (the frames, unlike simple controls, are not shown when
200
// created initially)
204
m_xnestWindow = new wxAdoptedWindow;
207
cmd.Printf(wxT("Xnest :%s -geometry %dx%d"),
208
m_displayNumber.c_str(),
209
(int) m_emulatorInfo.m_emulatorScreenSize.x,
210
(int) m_emulatorInfo.m_emulatorScreenSize.y);
212
// Asynchronously executes Xnest
213
m_xnestPID = wxExecute(cmd);
217
wxMessageBox(wxT("Sorry, could not run Xnest. Please check your PATH."));
221
wxReparenter reparenter;
222
if (!reparenter.WaitAndReparent(m_containerWindow, m_xnestWindow, wxT("Xnest")))
224
wxMessageBox(wxT("Sorry, could not reparent Xnest.."));
230
m_containerWindow->DoResize();
232
// success: wxApp::OnRun() will be called which will enter the main message
233
// loop and the application will run. If we returned false here, the
234
// application would exit immediately.
238
// Prepend the current program directory to the name
239
wxString wxEmulatorApp::GetFullAppPath(const wxString& filename) const
241
wxString path(m_appDir);
242
if (path.Last() != '\\' && path.Last() != '/' && filename[0] != '\\' && filename[0] != '/')
254
// Load the specified emulator.
255
// For now, hard-wired. TODO: make this configurable
256
bool wxEmulatorApp::LoadEmulator(const wxString& appDir)
258
// Load config file and bitmaps
259
return m_emulatorInfo.Load(appDir);
262
// ----------------------------------------------------------------------------
264
// ----------------------------------------------------------------------------
267
wxEmulatorFrame::wxEmulatorFrame(const wxString& title,
268
const wxPoint& pos, const wxSize& size)
269
: wxFrame(NULL, wxID_ANY, title, pos, size)
271
// set the frame icon
272
SetIcon(wxICON(emulator));
276
wxMenu *menuFile = new wxMenu;
278
// the "About" item should be in the help menu
279
wxMenu *helpMenu = new wxMenu;
280
helpMenu->Append(Emulator_About, _T("&About...\tF1"), _T("Show about dialog"));
282
menuFile->Append(Emulator_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
284
// now append the freshly created menu to the menu bar...
285
wxMenuBar *menuBar = new wxMenuBar();
286
menuBar->Append(menuFile, _T("&File"));
287
menuBar->Append(helpMenu, _T("&Help"));
289
// ... and attach this menu bar to the frame
291
#endif // wxUSE_MENUS
294
// create a status bar just for fun (by default with 1 pane only)
296
#endif // wxUSE_STATUSBAR
302
void wxEmulatorFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
304
// true is to force the frame to close
308
void wxEmulatorFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
311
msg.Printf( _T("wxEmulator is an environment for testing embedded X11 apps.\n"));
313
wxMessageBox(msg, _T("About wxEmulator"), wxOK | wxICON_INFORMATION, this);
316
void wxEmulatorFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
319
if (wxGetApp().m_xnestWindow)
321
wxGetApp().m_xnestWindow->SetHandle((WXWindow) NULL);
325
if (wxGetApp().m_xnestPID > 0)
327
wxKill(wxGetApp().m_xnestPID);
328
wxGetApp().m_xnestPID = 0;
332
IMPLEMENT_CLASS(wxEmulatorContainer, wxWindow)
334
BEGIN_EVENT_TABLE(wxEmulatorContainer, wxWindow)
335
EVT_SIZE(wxEmulatorContainer::OnSize)
336
EVT_PAINT(wxEmulatorContainer::OnPaint)
337
EVT_ERASE_BACKGROUND(wxEmulatorContainer::OnEraseBackground)
340
wxEmulatorContainer::wxEmulatorContainer(wxWindow* parent, wxWindowID id):
341
wxWindow(parent, id, wxDefaultPosition, wxDefaultSize)
345
void wxEmulatorContainer::OnSize(wxSizeEvent& WXUNUSED(event))
350
void wxEmulatorContainer::DoResize()
352
wxSize sz = GetClientSize();
353
if (wxGetApp().m_xnestWindow
355
&& wxGetApp().m_xnestWindow->GetMainWindow()
359
int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x;
360
int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y;
362
int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0));
363
int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0));
365
x += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.x;
366
y += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.y;
368
wxGetApp().m_xnestWindow->Move(x, y);
373
void wxEmulatorContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
377
wxSize sz = GetClientSize();
378
if (wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.Ok())
380
int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x;
381
int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y;
383
int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0));
384
int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0));
386
dc.DrawBitmap(wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap, x, y);
390
void wxEmulatorContainer::OnEraseBackground(wxEraseEvent& event)
392
wxDC* dc wxDUMMY_INITIALIZE(NULL);
400
dc = new wxClientDC(this);
403
dc->SetBackground(wxBrush(wxGetApp().m_emulatorInfo.m_emulatorBackgroundColour, wxSOLID));
410
// Information about the emulator decorations
412
void wxEmulatorInfo::Copy(const wxEmulatorInfo& info)
414
m_emulatorFilename = info.m_emulatorFilename;
415
m_emulatorTitle = info.m_emulatorTitle;
416
m_emulatorDescription = info.m_emulatorDescription;
417
m_emulatorScreenPosition = info.m_emulatorScreenPosition;
418
m_emulatorScreenSize = info.m_emulatorScreenSize;
419
m_emulatorBackgroundBitmap = info.m_emulatorBackgroundBitmap;
420
m_emulatorBackgroundBitmapName = info.m_emulatorBackgroundBitmapName;
421
m_emulatorBackgroundColour = info.m_emulatorBackgroundColour;
422
m_emulatorDeviceSize = info.m_emulatorDeviceSize;
426
void wxEmulatorInfo::Init()
428
m_emulatorDeviceSize = wxSize(260, 340);
429
m_emulatorScreenSize = wxSize(240, 320);
433
bool wxEmulatorInfo::Load(const wxString& appDir)
435
// Try to find absolute path
436
wxString absoluteConfigPath = m_emulatorFilename;
437
if ( !::wxIsAbsolutePath(absoluteConfigPath) )
439
wxString currDir = wxGetCwd();
440
absoluteConfigPath = currDir + wxString(wxFILE_SEP_PATH) + m_emulatorFilename;
441
if ( !wxFile::Exists(absoluteConfigPath) )
443
absoluteConfigPath = appDir + wxString(wxFILE_SEP_PATH)
444
+ m_emulatorFilename;
448
if ( !wxFile::Exists(absoluteConfigPath) )
451
str.Printf( wxT("Could not find config file %s"),
452
absoluteConfigPath.c_str() );
458
wxString rootPath = wxPathOnly(absoluteConfigPath);
461
wxFileConfig config(wxT("wxEmulator"), wxT("wxWidgets"),
462
absoluteConfigPath, wxEmptyString, wxCONFIG_USE_LOCAL_FILE);
464
config.Read(wxT("/General/title"), & m_emulatorTitle);
465
config.Read(wxT("/General/description"), & m_emulatorDescription);
466
config.Read(wxT("/General/backgroundBitmap"), & m_emulatorBackgroundBitmapName);
469
if (config.Read(wxT("/General/backgroundColour"), & colString) ||
470
config.Read(wxT("/General/backgroundColor"), & colString)
473
m_emulatorBackgroundColour = wxHexStringToColour(colString);
476
int x = 0, y = 0, w = 0, h = 0, dw = 0, dh = 0;
477
config.Read(wxT("/General/screenX"), & x);
478
config.Read(wxT("/General/screenY"), & y);
479
config.Read(wxT("/General/screenWidth"), & w);
480
config.Read(wxT("/General/screenHeight"), & h);
481
if (config.Read(wxT("/General/deviceWidth"), & dw) && config.Read(wxT("/General/deviceHeight"), & dh))
483
m_emulatorDeviceSize = wxSize(dw, dh);
486
m_emulatorScreenPosition = wxPoint(x, y);
487
m_emulatorScreenSize = wxSize(w, h);
490
if (!m_emulatorBackgroundBitmapName.empty())
492
wxString absoluteBackgroundBitmapName = rootPath + wxString(wxFILE_SEP_PATH) + m_emulatorBackgroundBitmapName;
493
if ( !wxFile::Exists(absoluteBackgroundBitmapName) )
496
str.Printf( wxT("Could not find bitmap %s"),
497
absoluteBackgroundBitmapName.c_str() );
502
wxBitmapType type = wxDetermineImageType(m_emulatorBackgroundBitmapName);
503
if (type == wxBITMAP_TYPE_INVALID)
506
if (!m_emulatorBackgroundBitmap.LoadFile(m_emulatorBackgroundBitmapName, type))
509
str.Printf( wxT("Could not load bitmap file %s"),
510
m_emulatorBackgroundBitmapName.c_str() );
515
m_emulatorDeviceSize = wxSize(m_emulatorBackgroundBitmap.GetWidth(),
516
m_emulatorBackgroundBitmap.GetHeight());
521
// Returns the image type, or -1, determined from the extension.
522
wxBitmapType wxDetermineImageType(const wxString& filename)
524
wxString path, name, ext;
526
wxSplitPath(filename, & path, & name, & ext);
529
if (ext == _T("jpg") || ext == _T("jpeg"))
530
return wxBITMAP_TYPE_JPEG;
531
if (ext == _T("gif"))
532
return wxBITMAP_TYPE_GIF;
533
if (ext == _T("bmp"))
534
return wxBITMAP_TYPE_BMP;
535
if (ext == _T("png"))
536
return wxBITMAP_TYPE_PNG;
537
if (ext == _T("pcx"))
538
return wxBITMAP_TYPE_PCX;
539
if (ext == _T("tif") || ext == _T("tiff"))
540
return wxBITMAP_TYPE_TIF;
542
return wxBITMAP_TYPE_INVALID;
545
// Convert a colour to a 6-digit hex string
546
wxString wxColourToHexString(const wxColour& col)
550
hex += wxDecToHex(col.Red());
551
hex += wxDecToHex(col.Green());
552
hex += wxDecToHex(col.Blue());
557
// Convert 6-digit hex string to a colour
558
wxColour wxHexStringToColour(const wxString& hex)
560
unsigned char r = (unsigned char)wxHexToDec(hex.Mid(0, 2));
561
unsigned char g = (unsigned char)wxHexToDec(hex.Mid(2, 2));
562
unsigned char b = (unsigned char)wxHexToDec(hex.Mid(4, 2));
564
return wxColour(r, g, b);
567
// Find the absolute path where this application has been run from.
568
// argv0 is wxTheApp->argv[0]
569
// cwd is the current working directory (at startup)
570
// appVariableName is the name of a variable containing the directory for this app, e.g.
571
// MYAPPDIR. This is checked first.
573
wxString wxFindAppPath(const wxString& argv0, const wxString& cwd, const wxString& appVariableName)
577
// Try appVariableName
578
if (!appVariableName.empty())
580
str = wxGetenv(appVariableName);
585
if (wxIsAbsolutePath(argv0))
586
return wxPathOnly(argv0);
589
// Is it a relative path?
590
wxString currentDir(cwd);
591
if (!wxEndsWithPathSeparator(currentDir))
592
currentDir += wxFILE_SEP_PATH;
594
str = currentDir + argv0;
595
if ( wxFile::Exists(str) )
596
return wxPathOnly(str);
599
// OK, it's neither an absolute path nor a relative path.
603
pathList.AddEnvList(wxT("PATH"));
604
str = pathList.FindAbsoluteValidPath(argv0);
606
return wxPathOnly(str);
609
return wxEmptyString;