1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Emulator wxWindows sample
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
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" wxWindows headers)
37 #include "wx/confbase.h"
38 #include "wx/fileconf.h"
39 #include "wx/cmdline.h"
42 #include "wx/x11/reparent.h"
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
51 // the application icon (under Windows and OS/2 it is in resources)
52 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
53 #include "emulator.xpm"
56 // ----------------------------------------------------------------------------
57 // event tables and other macros for wxWindows
58 // ----------------------------------------------------------------------------
60 // the event tables connect the wxWindows events with the functions (event
61 // handlers) which process them. It can be also done at run-time, but for the
62 // simple menu events like this the static method is much simpler.
63 BEGIN_EVENT_TABLE(wxEmulatorFrame
, wxFrame
)
64 EVT_MENU(Emulator_Quit
, wxEmulatorFrame::OnQuit
)
65 EVT_MENU(Emulator_About
, wxEmulatorFrame::OnAbout
)
68 // Create a new application object: this macro will allow wxWindows to create
69 // the application object during program execution (it's better than using a
70 // static object for many reasons) and also declares the accessor function
71 // wxGetApp() which will return the reference of the right type (i.e. wxEmulatorApp and
73 IMPLEMENT_APP(wxEmulatorApp
)
75 static const wxCmdLineEntryDesc sg_cmdLineDesc
[] =
77 { wxCMD_LINE_OPTION
, "u", "use-display", "display number to use (default 100)" },
79 { wxCMD_LINE_SWITCH
, "h", "help", "displays help on the command line parameters" },
80 { wxCMD_LINE_SWITCH
, "v", "version", "print version" },
82 { wxCMD_LINE_PARAM
, NULL
, NULL
, "config file 1", wxCMD_LINE_VAL_STRING
, wxCMD_LINE_PARAM_OPTIONAL
},
88 // ============================================================================
90 // ============================================================================
92 // ----------------------------------------------------------------------------
93 // the application class
94 // ----------------------------------------------------------------------------
96 wxEmulatorApp::wxEmulatorApp()
99 m_containerWindow
= NULL
;
100 m_displayNumber
= wxT("100");
103 // 'Main program' equivalent: the program execution "starts" here
104 bool wxEmulatorApp::OnInit()
106 wxInitAllImageHandlers();
108 wxString currentDir
= wxGetCwd();
110 // Use argv to get current app directory
111 m_appDir
= wxFindAppPath(argv
[0], currentDir
, wxT("WXEMUDIR"));
113 // If the development version, go up a directory.
115 if ((m_appDir
.Right(5).CmpNoCase("DEBUG") == 0) ||
116 (m_appDir
.Right(11).CmpNoCase("DEBUGSTABLE") == 0) ||
117 (m_appDir
.Right(7).CmpNoCase("RELEASE") == 0) ||
118 (m_appDir
.Right(13).CmpNoCase("RELEASESTABLE") == 0)
120 m_appDir
= wxPathOnly(m_appDir
);
123 // Parse the command-line parameters and options
124 wxCmdLineParser
parser(sg_cmdLineDesc
, argc
, argv
);
128 res
= parser
.Parse();
130 if (res
== -1 || res
> 0 || parser
.Found(wxT("h")))
133 wxLog::SetActiveTarget(new wxLogStderr
);
138 if (parser
.Found(wxT("v")))
141 wxLog::SetActiveTarget(new wxLogStderr
);
144 msg
.Printf(wxT("wxWindows PDA Emulator (c) Julian Smart, 2002 Version %.2f, %s"), wxEMULATOR_VERSION
, __DATE__
);
148 if (parser
.Found(wxT("u"), & m_displayNumber
))
150 // Should only be number, so strip out anything before
151 // and including a : character
152 if (m_displayNumber
.Find(wxT(':')) != -1)
154 m_displayNumber
= m_displayNumber
.AfterFirst(wxT(':'));
157 if (parser
.GetParamCount() == 0)
159 m_emulatorInfo
.m_emulatorFilename
= wxT("default.wxe");
161 else if (parser
.GetParamCount() > 0)
163 m_emulatorInfo
.m_emulatorFilename
= parser
.GetParam(0);
166 // Load the emulation info
167 if (!LoadEmulator(m_appDir
))
169 //wxMessageBox(wxT("Sorry, could not load this emulator. Please check bitmaps are valid."));
173 // create the main application window
174 wxEmulatorFrame
*frame
= new wxEmulatorFrame(_T("wxEmulator"),
175 wxPoint(50, 50), wxSize(450, 340));
177 frame
->SetStatusText(m_emulatorInfo
.m_emulatorTitle
, 0);
180 sizeStr
.Printf(wxT("Screen: %dx%d"), (int) m_emulatorInfo
.m_emulatorScreenSize
.x
,
181 (int) m_emulatorInfo
.m_emulatorScreenSize
.y
);
182 frame
->SetStatusText(sizeStr
, 1);
184 m_containerWindow
= new wxEmulatorContainer(frame
, -1);
186 frame
->SetClientSize(m_emulatorInfo
.m_emulatorDeviceSize
.x
,
187 m_emulatorInfo
.m_emulatorDeviceSize
.y
);
189 // and show it (the frames, unlike simple controls, are not shown when
190 // created initially)
194 m_xnestWindow
= new wxAdoptedWindow
;
197 cmd
.Printf(wxT("Xnest %s -geometry %dx%d"),
198 m_displayNumber
.c_str(),
199 (int) m_emulatorInfo
.m_emulatorScreenSize
.x
,
200 (int) m_emulatorInfo
.m_emulatorScreenSize
.y
);
202 // Asynchronously executes Xnest
203 if (0 == wxExecute(cmd
))
206 wxMessageBox(wxT("Sorry, could not run Xnest. Please check your PATH."));
210 wxReparenter reparenter
;
211 if (!reparenter
.WaitAndReparent(m_containerWindow
, m_xnestWindow
, wxT("Xnest")))
213 wxMessageBox(wxT("Sorry, could not reparent Xnest.."));
219 m_containerWindow
->DoResize();
221 // success: wxApp::OnRun() will be called which will enter the main message
222 // loop and the application will run. If we returned FALSE here, the
223 // application would exit immediately.
227 // Prepend the current program directory to the name
228 wxString
wxEmulatorApp::GetFullAppPath(const wxString
& filename
) const
230 wxString
path(m_appDir
);
231 if (path
.Last() != '\\' && path
.Last() != '/' && filename
[0] != '\\' && filename
[0] != '/')
243 // Load the specified emulator.
244 // For now, hard-wired. TODO: make this configurable
245 bool wxEmulatorApp::LoadEmulator(const wxString
& appDir
)
247 // Load config file and bitmaps
248 return m_emulatorInfo
.Load(appDir
);
251 // ----------------------------------------------------------------------------
253 // ----------------------------------------------------------------------------
256 wxEmulatorFrame::wxEmulatorFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
257 : wxFrame(NULL
, -1, title
, pos
, size
)
259 // set the frame icon
260 SetIcon(wxICON(emulator
));
264 wxMenu
*menuFile
= new wxMenu
;
266 // the "About" item should be in the help menu
267 wxMenu
*helpMenu
= new wxMenu
;
268 helpMenu
->Append(Emulator_About
, _T("&About...\tF1"), _T("Show about dialog"));
270 menuFile
->Append(Emulator_Quit
, _T("E&xit\tAlt-X"), _T("Quit this program"));
272 // now append the freshly created menu to the menu bar...
273 wxMenuBar
*menuBar
= new wxMenuBar();
274 menuBar
->Append(menuFile
, _T("&File"));
275 menuBar
->Append(helpMenu
, _T("&Help"));
277 // ... and attach this menu bar to the frame
279 #endif // wxUSE_MENUS
282 // create a status bar just for fun (by default with 1 pane only)
284 #endif // wxUSE_STATUSBAR
290 void wxEmulatorFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
292 // TRUE is to force the frame to close
296 void wxEmulatorFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
299 msg
.Printf( _T("wxEmulator is an environment for testing embedded X11 apps.\n"));
301 wxMessageBox(msg
, _T("About wxEmulator"), wxOK
| wxICON_INFORMATION
, this);
304 IMPLEMENT_CLASS(wxEmulatorContainer
, wxWindow
)
306 BEGIN_EVENT_TABLE(wxEmulatorContainer
, wxWindow
)
307 EVT_SIZE(wxEmulatorContainer::OnSize
)
308 EVT_PAINT(wxEmulatorContainer::OnPaint
)
309 EVT_ERASE_BACKGROUND(wxEmulatorContainer::OnEraseBackground
)
312 wxEmulatorContainer::wxEmulatorContainer(wxWindow
* parent
, wxWindowID id
):
313 wxWindow(parent
, id
, wxDefaultPosition
, wxDefaultSize
)
317 void wxEmulatorContainer::OnSize(wxSizeEvent
& event
)
322 void wxEmulatorContainer::DoResize()
324 wxSize sz
= GetClientSize();
325 if (wxGetApp().m_xnestWindow
)
327 int deviceWidth
= wxGetApp().m_emulatorInfo
.m_emulatorDeviceSize
.x
;
328 int deviceHeight
= wxGetApp().m_emulatorInfo
.m_emulatorDeviceSize
.y
;
330 int x
= wxMax(0, (int) ((sz
.x
- deviceWidth
)/2.0));
331 int y
= wxMax(0, (int) ((sz
.y
- deviceHeight
)/2.0));
333 x
+= wxGetApp().m_emulatorInfo
.m_emulatorScreenPosition
.x
;
334 y
+= wxGetApp().m_emulatorInfo
.m_emulatorScreenPosition
.y
;
336 wxGetApp().m_xnestWindow
->Move(x
, y
);
341 void wxEmulatorContainer::OnPaint(wxPaintEvent
& event
)
345 wxSize sz
= GetClientSize();
346 if (wxGetApp().m_emulatorInfo
.m_emulatorBackgroundBitmap
.Ok())
348 int deviceWidth
= wxGetApp().m_emulatorInfo
.m_emulatorDeviceSize
.x
;
349 int deviceHeight
= wxGetApp().m_emulatorInfo
.m_emulatorDeviceSize
.y
;
351 int x
= wxMax(0, (int) ((sz
.x
- deviceWidth
)/2.0));
352 int y
= wxMax(0, (int) ((sz
.y
- deviceHeight
)/2.0));
354 dc
.DrawBitmap(wxGetApp().m_emulatorInfo
.m_emulatorBackgroundBitmap
, x
, y
);
358 void wxEmulatorContainer::OnEraseBackground(wxEraseEvent
& event
)
368 dc
= new wxClientDC(this);
371 dc
->SetBackground(wxBrush(wxGetApp().m_emulatorInfo
.m_emulatorBackgroundColour
, wxSOLID
));
378 // Information about the emulator decorations
380 void wxEmulatorInfo::Copy(const wxEmulatorInfo
& info
)
382 m_emulatorFilename
= info
.m_emulatorFilename
;
383 m_emulatorTitle
= info
.m_emulatorTitle
;
384 m_emulatorDescription
= info
.m_emulatorDescription
;
385 m_emulatorScreenPosition
= info
.m_emulatorScreenPosition
;
386 m_emulatorScreenSize
= info
.m_emulatorScreenSize
;
387 m_emulatorBackgroundBitmap
= info
.m_emulatorBackgroundBitmap
;
388 m_emulatorBackgroundBitmapName
= info
.m_emulatorBackgroundBitmapName
;
389 m_emulatorBackgroundColour
= info
.m_emulatorBackgroundColour
;
390 m_emulatorDeviceSize
= info
.m_emulatorDeviceSize
;
394 void wxEmulatorInfo::Init()
396 m_emulatorDeviceSize
= wxSize(260, 340);
397 m_emulatorScreenSize
= wxSize(240, 320);
401 bool wxEmulatorInfo::Load(const wxString
& appDir
)
403 // Try to find absolute path
404 wxString absoluteConfigPath
= m_emulatorFilename
;
405 if (!wxIsAbsolutePath(absoluteConfigPath
))
407 wxString currDir
= wxGetCwd();
408 absoluteConfigPath
= currDir
+ wxString(wxFILE_SEP_PATH
) + m_emulatorFilename
;
409 if (!wxFileExists(absoluteConfigPath
))
411 absoluteConfigPath
= appDir
+ wxString(wxFILE_SEP_PATH
) + m_emulatorFilename
;
414 if (!wxFileExists(absoluteConfigPath
))
417 str
.Printf(wxT("Could not find config file %s"), absoluteConfigPath
.c_str()),
422 wxString rootPath
= wxPathOnly(absoluteConfigPath
);
425 wxFileConfig
config(wxT("wxEmulator"), wxT("wxWindows"),
426 absoluteConfigPath
, wxEmptyString
, wxCONFIG_USE_LOCAL_FILE
);
428 config
.Read(wxT("/General/title"), & m_emulatorTitle
);
429 config
.Read(wxT("/General/description"), & m_emulatorDescription
);
430 config
.Read(wxT("/General/backgroundBitmap"), & m_emulatorBackgroundBitmapName
);
433 if (config
.Read(wxT("/General/backgroundColour"), & colString
) ||
434 config
.Read(wxT("/General/backgroundColor"), & colString
)
437 m_emulatorBackgroundColour
= wxHexStringToColour(colString
);
440 int x
= 0, y
= 0, w
= 0, h
= 0, dw
= 0, dh
= 0;
441 config
.Read(wxT("/General/screenX"), & x
);
442 config
.Read(wxT("/General/screenY"), & y
);
443 config
.Read(wxT("/General/screenWidth"), & w
);
444 config
.Read(wxT("/General/screenHeight"), & h
);
445 if (config
.Read(wxT("/General/deviceWidth"), & dw
) && config
.Read(wxT("/General/deviceHeight"), & dh
))
447 m_emulatorDeviceSize
= wxSize(dw
, dh
);
450 m_emulatorScreenPosition
= wxPoint(x
, y
);
451 m_emulatorScreenSize
= wxSize(w
, h
);
454 if (!m_emulatorBackgroundBitmapName
.IsEmpty())
456 wxString absoluteBackgroundBitmapName
= rootPath
+ wxString(wxFILE_SEP_PATH
) + m_emulatorBackgroundBitmapName
;
457 if (!wxFileExists(absoluteBackgroundBitmapName
))
460 str
.Printf(wxT("Could not find bitmap %s"), absoluteBackgroundBitmapName
.c_str()),
465 int type
= wxDetermineImageType(m_emulatorBackgroundBitmapName
);
469 if (!m_emulatorBackgroundBitmap
.LoadFile(m_emulatorBackgroundBitmapName
, type
))
472 str
.Printf(wxT("Could not load bitmap file %s"), m_emulatorBackgroundBitmapName
.c_str()),
476 m_emulatorDeviceSize
= wxSize(m_emulatorBackgroundBitmap
.GetWidth(),
477 m_emulatorBackgroundBitmap
.GetHeight());
482 // Returns the image type, or -1, determined from the extension.
483 int wxDetermineImageType(const wxString
& filename
)
485 wxString path
, name
, ext
;
487 wxSplitPath(filename
, & path
, & name
, & ext
);
490 if (ext
== "jpg" || ext
== "jpeg")
491 return wxBITMAP_TYPE_JPEG
;
492 else if (ext
== "gif")
493 return wxBITMAP_TYPE_GIF
;
494 else if (ext
== "bmp")
495 return wxBITMAP_TYPE_BMP
;
496 else if (ext
== "png")
497 return wxBITMAP_TYPE_PNG
;
498 else if (ext
== "pcx")
499 return wxBITMAP_TYPE_PCX
;
500 else if (ext
== "tif" || ext
== "tiff")
501 return wxBITMAP_TYPE_TIF
;
506 // Convert a colour to a 6-digit hex string
507 wxString
wxColourToHexString(const wxColour
& col
)
511 hex
+= wxDecToHex(col
.Red());
512 hex
+= wxDecToHex(col
.Green());
513 hex
+= wxDecToHex(col
.Blue());
518 // Convert 6-digit hex string to a colour
519 wxColour
wxHexStringToColour(const wxString
& hex
)
524 r
= wxHexToDec(hex
.Mid(0, 2));
525 g
= wxHexToDec(hex
.Mid(2, 2));
526 b
= wxHexToDec(hex
.Mid(4, 2));
528 return wxColour(r
, g
, b
);
531 // Find the absolute path where this application has been run from.
532 // argv0 is wxTheApp->argv[0]
533 // cwd is the current working directory (at startup)
534 // appVariableName is the name of a variable containing the directory for this app, e.g.
535 // MYAPPDIR. This is checked first.
537 wxString
wxFindAppPath(const wxString
& argv0
, const wxString
& cwd
, const wxString
& appVariableName
)
541 // Try appVariableName
542 if (!appVariableName
.IsEmpty())
544 str
= wxGetenv(appVariableName
);
549 if (wxIsAbsolutePath(argv0
))
550 return wxPathOnly(argv0
);
553 // Is it a relative path?
554 wxString
currentDir(cwd
);
555 if (currentDir
.Last() != wxFILE_SEP_PATH
)
556 currentDir
+= wxFILE_SEP_PATH
;
558 str
= currentDir
+ argv0
;
559 if (wxFileExists(str
))
560 return wxPathOnly(str
);
563 // OK, it's neither an absolute path nor a relative path.
567 pathList
.AddEnvList(wxT("PATH"));
568 str
= pathList
.FindAbsoluteValidPath(argv0
);
570 return wxPathOnly(str
);
573 return wxEmptyString
;