]> git.saurik.com Git - wxWidgets.git/blob - utils/emulator/src/emulator.cpp
ccc15aa3ea3f86f860baba766eceeac8b60e57da
[wxWidgets.git] / utils / emulator / src / emulator.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: emulator.cpp
3 // Purpose: Emulator wxWindows sample
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 #ifdef __GNUG__
17 #pragma implementation "emulator.h"
18 #endif
19
20 // ----------------------------------------------------------------------------
21 // headers
22 // ----------------------------------------------------------------------------
23
24 // For compilers that support precompilation, includes "wx/wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 // for all others, include the necessary headers (this file is usually all you
32 // need because it includes almost all "standard" wxWindows headers)
33 #ifndef WX_PRECOMP
34 #include "wx/wx.h"
35 #endif
36
37 #include "wx/confbase.h"
38 #include "wx/fileconf.h"
39 #include "wx/cmdline.h"
40
41 #ifdef __WXX11__
42 #include "wx/x11/reparent.h"
43 #endif
44
45 #include "emulator.h"
46
47 // ----------------------------------------------------------------------------
48 // resources
49 // ----------------------------------------------------------------------------
50
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"
54 #endif
55
56 // ----------------------------------------------------------------------------
57 // event tables and other macros for wxWindows
58 // ----------------------------------------------------------------------------
59
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)
66 END_EVENT_TABLE()
67
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
72 // not wxApp)
73 IMPLEMENT_APP(wxEmulatorApp)
74
75 static const wxCmdLineEntryDesc sg_cmdLineDesc[] =
76 {
77 { wxCMD_LINE_OPTION, "u", "use-display", "display number to use (default 100)" },
78
79 { wxCMD_LINE_SWITCH, "h", "help", "displays help on the command line parameters" },
80 { wxCMD_LINE_SWITCH, "v", "version", "print version" },
81
82 { wxCMD_LINE_PARAM, NULL, NULL, "config file 1", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
83
84 { wxCMD_LINE_NONE }
85 };
86
87
88 // ============================================================================
89 // implementation
90 // ============================================================================
91
92 // ----------------------------------------------------------------------------
93 // the application class
94 // ----------------------------------------------------------------------------
95
96 wxEmulatorApp::wxEmulatorApp()
97 {
98 m_xnestWindow = NULL;
99 m_containerWindow = NULL;
100 m_displayNumber = wxT("100");
101 }
102
103 // 'Main program' equivalent: the program execution "starts" here
104 bool wxEmulatorApp::OnInit()
105 {
106 wxInitAllImageHandlers();
107
108 wxString currentDir = wxGetCwd();
109
110 // Use argv to get current app directory
111 m_appDir = wxFindAppPath(argv[0], currentDir, wxT("WXEMUDIR"));
112
113 // If the development version, go up a directory.
114 #ifdef __WXMSW__
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)
119 )
120 m_appDir = wxPathOnly(m_appDir);
121 #endif
122
123 // Parse the command-line parameters and options
124 wxCmdLineParser parser(sg_cmdLineDesc, argc, argv);
125 int res;
126 {
127 wxLogNull log;
128 res = parser.Parse();
129 }
130 if (res == -1 || res > 0 || parser.Found(wxT("h")))
131 {
132 #ifdef __X__
133 wxLog::SetActiveTarget(new wxLogStderr);
134 #endif
135 parser.Usage();
136 return FALSE;
137 }
138 if (parser.Found(wxT("v")))
139 {
140 #ifdef __X__
141 wxLog::SetActiveTarget(new wxLogStderr);
142 #endif
143 wxString msg;
144 msg.Printf(wxT("wxWindows PDA Emulator (c) Julian Smart, 2002 Version %.2f, %s"), wxEMULATOR_VERSION, __DATE__);
145 wxLogMessage(msg);
146 return FALSE;
147 }
148 if (parser.Found(wxT("u"), & m_displayNumber))
149 {
150 // Should only be number, so strip out anything before
151 // and including a : character
152 if (m_displayNumber.Find(wxT(':')) != -1)
153 {
154 m_displayNumber = m_displayNumber.AfterFirst(wxT(':'));
155 }
156 }
157 if (parser.GetParamCount() == 0)
158 {
159 m_emulatorInfo.m_emulatorFilename = wxT("default.wxe");
160 }
161 else if (parser.GetParamCount() > 0)
162 {
163 m_emulatorInfo.m_emulatorFilename = parser.GetParam(0);
164 }
165
166 // Load the emulation info
167 if (!LoadEmulator(m_appDir))
168 {
169 //wxMessageBox(wxT("Sorry, could not load this emulator. Please check bitmaps are valid."));
170 return FALSE;
171 }
172
173 // create the main application window
174 wxEmulatorFrame *frame = new wxEmulatorFrame(_T("wxEmulator"),
175 wxPoint(50, 50), wxSize(450, 340));
176
177 frame->SetStatusText(m_emulatorInfo.m_emulatorTitle, 0);
178
179 wxString sizeStr;
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);
183
184 m_containerWindow = new wxEmulatorContainer(frame, -1);
185
186 frame->SetClientSize(m_emulatorInfo.m_emulatorDeviceSize.x,
187 m_emulatorInfo.m_emulatorDeviceSize.y);
188
189 // and show it (the frames, unlike simple controls, are not shown when
190 // created initially)
191 frame->Show(TRUE);
192
193 #ifdef __WXX11__
194 m_xnestWindow = new wxAdoptedWindow;
195
196 wxString cmd;
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);
201
202 // Asynchronously executes Xnest
203 if (0 == wxExecute(cmd))
204 {
205 frame->Destroy();
206 wxMessageBox(wxT("Sorry, could not run Xnest. Please check your PATH."));
207 return FALSE;
208 }
209
210 wxReparenter reparenter;
211 if (!reparenter.WaitAndReparent(m_containerWindow, m_xnestWindow, wxT("Xnest")))
212 {
213 wxMessageBox(wxT("Sorry, could not reparent Xnest.."));
214 frame->Destroy();
215 return FALSE;
216 }
217
218 #endif
219 m_containerWindow->DoResize();
220
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.
224 return TRUE;
225 }
226
227 // Prepend the current program directory to the name
228 wxString wxEmulatorApp::GetFullAppPath(const wxString& filename) const
229 {
230 wxString path(m_appDir);
231 if (path.Last() != '\\' && path.Last() != '/' && filename[0] != '\\' && filename[0] != '/')
232 #ifdef __X__
233 path += '/';
234 #else
235 path += '\\';
236 #endif
237 path += filename;
238
239 return path;
240 }
241
242
243 // Load the specified emulator.
244 // For now, hard-wired. TODO: make this configurable
245 bool wxEmulatorApp::LoadEmulator(const wxString& appDir)
246 {
247 // Load config file and bitmaps
248 return m_emulatorInfo.Load(appDir);
249 }
250
251 // ----------------------------------------------------------------------------
252 // main frame
253 // ----------------------------------------------------------------------------
254
255 // frame constructor
256 wxEmulatorFrame::wxEmulatorFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
257 : wxFrame(NULL, -1, title, pos, size)
258 {
259 // set the frame icon
260 SetIcon(wxICON(emulator));
261
262 #if wxUSE_MENUS
263 // create a menu bar
264 wxMenu *menuFile = new wxMenu;
265
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"));
269
270 menuFile->Append(Emulator_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
271
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"));
276
277 // ... and attach this menu bar to the frame
278 SetMenuBar(menuBar);
279 #endif // wxUSE_MENUS
280
281 #if wxUSE_STATUSBAR
282 // create a status bar just for fun (by default with 1 pane only)
283 CreateStatusBar(2);
284 #endif // wxUSE_STATUSBAR
285 }
286
287
288 // event handlers
289
290 void wxEmulatorFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
291 {
292 // TRUE is to force the frame to close
293 Close(TRUE);
294 }
295
296 void wxEmulatorFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
297 {
298 wxString msg;
299 msg.Printf( _T("wxEmulator is an environment for testing embedded X11 apps.\n"));
300
301 wxMessageBox(msg, _T("About wxEmulator"), wxOK | wxICON_INFORMATION, this);
302 }
303
304 IMPLEMENT_CLASS(wxEmulatorContainer, wxWindow)
305
306 BEGIN_EVENT_TABLE(wxEmulatorContainer, wxWindow)
307 EVT_SIZE(wxEmulatorContainer::OnSize)
308 EVT_PAINT(wxEmulatorContainer::OnPaint)
309 EVT_ERASE_BACKGROUND(wxEmulatorContainer::OnEraseBackground)
310 END_EVENT_TABLE()
311
312 wxEmulatorContainer::wxEmulatorContainer(wxWindow* parent, wxWindowID id):
313 wxWindow(parent, id, wxDefaultPosition, wxDefaultSize)
314 {
315 }
316
317 void wxEmulatorContainer::OnSize(wxSizeEvent& event)
318 {
319 DoResize();
320 }
321
322 void wxEmulatorContainer::DoResize()
323 {
324 wxSize sz = GetClientSize();
325 if (wxGetApp().m_xnestWindow)
326 {
327 int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x;
328 int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y;
329
330 int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0));
331 int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0));
332
333 x += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.x;
334 y += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.y;
335
336 wxGetApp().m_xnestWindow->Move(x, y);
337 }
338 Refresh();
339 }
340
341 void wxEmulatorContainer::OnPaint(wxPaintEvent& event)
342 {
343 wxPaintDC dc(this);
344
345 wxSize sz = GetClientSize();
346 if (wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.Ok())
347 {
348 int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x;
349 int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y;
350
351 int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0));
352 int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0));
353
354 dc.DrawBitmap(wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap, x, y);
355 }
356 }
357
358 void wxEmulatorContainer::OnEraseBackground(wxEraseEvent& event)
359 {
360 wxDC* dc = NULL;
361
362 if (event.GetDC())
363 {
364 dc = event.GetDC();
365 }
366 else
367 {
368 dc = new wxClientDC(this);
369 }
370
371 dc->SetBackground(wxBrush(wxGetApp().m_emulatorInfo.m_emulatorBackgroundColour, wxSOLID));
372 dc->Clear();
373
374 if (!event.GetDC())
375 delete dc;
376 }
377
378 // Information about the emulator decorations
379
380 void wxEmulatorInfo::Copy(const wxEmulatorInfo& info)
381 {
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;
391 }
392
393 // Initialisation
394 void wxEmulatorInfo::Init()
395 {
396 m_emulatorDeviceSize = wxSize(260, 340);
397 m_emulatorScreenSize = wxSize(240, 320);
398 }
399
400 // Loads bitmaps
401 bool wxEmulatorInfo::Load(const wxString& appDir)
402 {
403 // Try to find absolute path
404 wxString absoluteConfigPath = m_emulatorFilename;
405 if (!wxIsAbsolutePath(absoluteConfigPath))
406 {
407 wxString currDir = wxGetCwd();
408 absoluteConfigPath = currDir + wxString(wxFILE_SEP_PATH) + m_emulatorFilename;
409 if (!wxFileExists(absoluteConfigPath))
410 {
411 absoluteConfigPath = appDir + wxString(wxFILE_SEP_PATH) + m_emulatorFilename;
412 }
413 }
414 if (!wxFileExists(absoluteConfigPath))
415 {
416 wxString str;
417 str.Printf(wxT("Could not find config file %s"), absoluteConfigPath.c_str()),
418 wxMessageBox(str);
419 return FALSE;
420 }
421
422 wxString rootPath = wxPathOnly(absoluteConfigPath);
423
424 {
425 wxFileConfig config(wxT("wxEmulator"), wxT("wxWindows"),
426 absoluteConfigPath, wxEmptyString, wxCONFIG_USE_LOCAL_FILE);
427
428 config.Read(wxT("/General/title"), & m_emulatorTitle);
429 config.Read(wxT("/General/description"), & m_emulatorDescription);
430 config.Read(wxT("/General/backgroundBitmap"), & m_emulatorBackgroundBitmapName);
431
432 wxString colString;
433 if (config.Read(wxT("/General/backgroundColour"), & colString) ||
434 config.Read(wxT("/General/backgroundColor"), & colString)
435 )
436 {
437 m_emulatorBackgroundColour = wxHexStringToColour(colString);
438 }
439
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))
446 {
447 m_emulatorDeviceSize = wxSize(dw, dh);
448 }
449
450 m_emulatorScreenPosition = wxPoint(x, y);
451 m_emulatorScreenSize = wxSize(w, h);
452 }
453
454 if (!m_emulatorBackgroundBitmapName.IsEmpty())
455 {
456 wxString absoluteBackgroundBitmapName = rootPath + wxString(wxFILE_SEP_PATH) + m_emulatorBackgroundBitmapName;
457 if (!wxFileExists(absoluteBackgroundBitmapName))
458 {
459 wxString str;
460 str.Printf(wxT("Could not find bitmap %s"), absoluteBackgroundBitmapName.c_str()),
461 wxMessageBox(str);
462 return FALSE;
463 }
464
465 int type = wxDetermineImageType(m_emulatorBackgroundBitmapName);
466 if (type == -1)
467 return FALSE;
468
469 if (!m_emulatorBackgroundBitmap.LoadFile(m_emulatorBackgroundBitmapName, type))
470 {
471 wxString str;
472 str.Printf(wxT("Could not load bitmap file %s"), m_emulatorBackgroundBitmapName.c_str()),
473 wxMessageBox(str);
474 return FALSE;
475 }
476 m_emulatorDeviceSize = wxSize(m_emulatorBackgroundBitmap.GetWidth(),
477 m_emulatorBackgroundBitmap.GetHeight());
478 }
479 return TRUE;
480 }
481
482 // Returns the image type, or -1, determined from the extension.
483 int wxDetermineImageType(const wxString& filename)
484 {
485 wxString path, name, ext;
486
487 wxSplitPath(filename, & path, & name, & ext);
488
489 ext.MakeLower();
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;
502 else
503 return -1;
504 }
505
506 // Convert a colour to a 6-digit hex string
507 wxString wxColourToHexString(const wxColour& col)
508 {
509 wxString hex;
510
511 hex += wxDecToHex(col.Red());
512 hex += wxDecToHex(col.Green());
513 hex += wxDecToHex(col.Blue());
514
515 return hex;
516 }
517
518 // Convert 6-digit hex string to a colour
519 wxColour wxHexStringToColour(const wxString& hex)
520 {
521 unsigned int r = 0;
522 unsigned int g = 0;
523 unsigned int b = 0;
524 r = wxHexToDec(hex.Mid(0, 2));
525 g = wxHexToDec(hex.Mid(2, 2));
526 b = wxHexToDec(hex.Mid(4, 2));
527
528 return wxColour(r, g, b);
529 }
530
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.
536
537 wxString wxFindAppPath(const wxString& argv0, const wxString& cwd, const wxString& appVariableName)
538 {
539 wxString str;
540
541 // Try appVariableName
542 if (!appVariableName.IsEmpty())
543 {
544 str = wxGetenv(appVariableName);
545 if (!str.IsEmpty())
546 return str;
547 }
548
549 if (wxIsAbsolutePath(argv0))
550 return wxPathOnly(argv0);
551 else
552 {
553 // Is it a relative path?
554 wxString currentDir(cwd);
555 if (currentDir.Last() != wxFILE_SEP_PATH)
556 currentDir += wxFILE_SEP_PATH;
557
558 str = currentDir + argv0;
559 if (wxFileExists(str))
560 return wxPathOnly(str);
561 }
562
563 // OK, it's neither an absolute path nor a relative path.
564 // Search PATH.
565
566 wxPathList pathList;
567 pathList.AddEnvList(wxT("PATH"));
568 str = pathList.FindAbsoluteValidPath(argv0);
569 if (!str.IsEmpty())
570 return wxPathOnly(str);
571
572 // Failed
573 return wxEmptyString;
574 }
575