]> git.saurik.com Git - wxWidgets.git/blob - utils/emulator/src/emulator.cpp
Fixes for wxUSE_STATUSBAR.
[wxWidgets.git] / utils / emulator / src / emulator.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: emulator.cpp
3 // Purpose: Emulator wxWidgets 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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
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" wxWidgets 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 #include "wx/image.h"
41 #include "wx/file.h"
42
43 #ifdef __WXX11__
44 #include "wx/x11/reparent.h"
45 #endif
46
47 #include "emulator.h"
48
49 // ----------------------------------------------------------------------------
50 // resources
51 // ----------------------------------------------------------------------------
52
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"
56 #endif
57
58 // ----------------------------------------------------------------------------
59 // event tables and other macros for wxWidgets
60 // ----------------------------------------------------------------------------
61
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)
69 END_EVENT_TABLE()
70
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
75 // not wxApp)
76 IMPLEMENT_APP(wxEmulatorApp)
77
78 static const wxCmdLineEntryDesc sg_cmdLineDesc[] =
79 {
80 { wxCMD_LINE_OPTION, _T("u"), _T("use-display"), _T("display number to use (default 100)") },
81
82 { wxCMD_LINE_SWITCH, _T("h"), _T("help"), _T("displays help on the command line parameters") },
83 { wxCMD_LINE_SWITCH, _T("v"), _T("version"), _T("print version") },
84
85 { wxCMD_LINE_PARAM, NULL, NULL, _T("config file 1"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
86
87 { wxCMD_LINE_NONE }
88 };
89
90
91 // ============================================================================
92 // implementation
93 // ============================================================================
94
95 // ----------------------------------------------------------------------------
96 // the application class
97 // ----------------------------------------------------------------------------
98
99 wxEmulatorApp::wxEmulatorApp()
100 {
101 m_xnestWindow = NULL;
102 m_containerWindow = NULL;
103 m_displayNumber = wxT("100");
104 m_xnestPID = 0;
105
106 }
107
108 // 'Main program' equivalent: the program execution "starts" here
109 bool wxEmulatorApp::OnInit()
110 {
111 wxLog::SetTimestamp(NULL);
112 wxInitAllImageHandlers();
113
114 wxString currentDir = wxGetCwd();
115
116 // Use argv to get current app directory
117 m_appDir = wxFindAppPath(argv[0], currentDir, wxT("WXEMUDIR"));
118
119 // If the development version, go up a directory.
120 #ifdef __WXMSW__
121 if ((m_appDir.Right(5).CmpNoCase(_T("DEBUG")) == 0) ||
122 (m_appDir.Right(11).CmpNoCase(_T("DEBUGSTABLE")) == 0) ||
123 (m_appDir.Right(7).CmpNoCase(_T("RELEASE")) == 0) ||
124 (m_appDir.Right(13).CmpNoCase(_T("RELEASESTABLE")) == 0)
125 )
126 m_appDir = wxPathOnly(m_appDir);
127 #endif
128
129 // Parse the command-line parameters and options
130 wxCmdLineParser parser(sg_cmdLineDesc, argc, argv);
131 int res;
132 {
133 wxLogNull log;
134 res = parser.Parse();
135 }
136 if (res == -1 || res > 0 || parser.Found(wxT("h")))
137 {
138 #ifdef __X__
139 wxLog::SetActiveTarget(new wxLogStderr);
140 #endif
141 parser.Usage();
142 return false;
143 }
144 if (parser.Found(wxT("v")))
145 {
146 #ifdef __X__
147 wxLog::SetActiveTarget(new wxLogStderr);
148 #endif
149 wxString msg;
150 msg.Printf(wxT("wxWidgets PDA Emulator (c) Julian Smart, 2002 Version %.2f, %s"), wxEMULATOR_VERSION, __DATE__);
151 wxLogMessage(msg);
152 return false;
153 }
154 if (parser.Found(wxT("u"), & m_displayNumber))
155 {
156 // Should only be number, so strip out anything before
157 // and including a : character
158 if (m_displayNumber.Find(wxT(':')) != -1)
159 {
160 m_displayNumber = m_displayNumber.AfterFirst(wxT(':'));
161 }
162 }
163 if (parser.GetParamCount() == 0)
164 {
165 m_emulatorInfo.m_emulatorFilename = wxT("default.wxe");
166 }
167 else if (parser.GetParamCount() > 0)
168 {
169 m_emulatorInfo.m_emulatorFilename = parser.GetParam(0);
170 }
171
172 // Load the emulation info
173 if (!LoadEmulator(m_appDir))
174 {
175 //wxMessageBox(wxT("Sorry, could not load this emulator. Please check bitmaps are valid."));
176 return false;
177 }
178
179 // create the main application window
180 wxEmulatorFrame *frame = new wxEmulatorFrame(_T("wxEmulator"),
181 wxPoint(50, 50), wxSize(450, 340));
182
183 #if wxUSE_STATUSBAR
184 frame->SetStatusText(m_emulatorInfo.m_emulatorTitle, 0);
185
186 wxString sizeStr;
187 sizeStr.Printf(wxT("Screen: %dx%d"), (int) m_emulatorInfo.m_emulatorScreenSize.x,
188 (int) m_emulatorInfo.m_emulatorScreenSize.y);
189 frame->SetStatusText(sizeStr, 1);
190 #endif // wxUSE_STATUSBAR
191
192 m_containerWindow = new wxEmulatorContainer(frame, wxID_ANY);
193
194 frame->SetClientSize(m_emulatorInfo.m_emulatorDeviceSize.x,
195 m_emulatorInfo.m_emulatorDeviceSize.y);
196
197 // and show it (the frames, unlike simple controls, are not shown when
198 // created initially)
199 frame->Show(true);
200
201 #ifdef __WXX11__
202 m_xnestWindow = new wxAdoptedWindow;
203
204 wxString cmd;
205 cmd.Printf(wxT("Xnest :%s -geometry %dx%d"),
206 m_displayNumber.c_str(),
207 (int) m_emulatorInfo.m_emulatorScreenSize.x,
208 (int) m_emulatorInfo.m_emulatorScreenSize.y);
209
210 // Asynchronously executes Xnest
211 m_xnestPID = wxExecute(cmd);
212 if (0 == m_xnestPID)
213 {
214 frame->Destroy();
215 wxMessageBox(wxT("Sorry, could not run Xnest. Please check your PATH."));
216 return false;
217 }
218
219 wxReparenter reparenter;
220 if (!reparenter.WaitAndReparent(m_containerWindow, m_xnestWindow, wxT("Xnest")))
221 {
222 wxMessageBox(wxT("Sorry, could not reparent Xnest.."));
223 frame->Destroy();
224 return false;
225 }
226
227 #endif
228 m_containerWindow->DoResize();
229
230 // success: wxApp::OnRun() will be called which will enter the main message
231 // loop and the application will run. If we returned false here, the
232 // application would exit immediately.
233 return true;
234 }
235
236 // Prepend the current program directory to the name
237 wxString wxEmulatorApp::GetFullAppPath(const wxString& filename) const
238 {
239 wxString path(m_appDir);
240 if (path.Last() != '\\' && path.Last() != '/' && filename[0] != '\\' && filename[0] != '/')
241 #ifdef __X__
242 path += '/';
243 #else
244 path += '\\';
245 #endif
246 path += filename;
247
248 return path;
249 }
250
251
252 // Load the specified emulator.
253 // For now, hard-wired. TODO: make this configurable
254 bool wxEmulatorApp::LoadEmulator(const wxString& appDir)
255 {
256 // Load config file and bitmaps
257 return m_emulatorInfo.Load(appDir);
258 }
259
260 // ----------------------------------------------------------------------------
261 // main frame
262 // ----------------------------------------------------------------------------
263
264 // frame constructor
265 wxEmulatorFrame::wxEmulatorFrame(const wxString& title,
266 const wxPoint& pos, const wxSize& size)
267 : wxFrame(NULL, wxID_ANY, title, pos, size)
268 {
269 // set the frame icon
270 SetIcon(wxICON(emulator));
271
272 #if wxUSE_MENUS
273 // create a menu bar
274 wxMenu *menuFile = new wxMenu;
275
276 // the "About" item should be in the help menu
277 wxMenu *helpMenu = new wxMenu;
278 helpMenu->Append(Emulator_About, _T("&About...\tF1"), _T("Show about dialog"));
279
280 menuFile->Append(Emulator_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
281
282 // now append the freshly created menu to the menu bar...
283 wxMenuBar *menuBar = new wxMenuBar();
284 menuBar->Append(menuFile, _T("&File"));
285 menuBar->Append(helpMenu, _T("&Help"));
286
287 // ... and attach this menu bar to the frame
288 SetMenuBar(menuBar);
289 #endif // wxUSE_MENUS
290
291 #if wxUSE_STATUSBAR
292 // create a status bar just for fun (by default with 1 pane only)
293 CreateStatusBar(2);
294 #endif // wxUSE_STATUSBAR
295 }
296
297
298 // event handlers
299
300 void wxEmulatorFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
301 {
302 // true is to force the frame to close
303 Close(true);
304 }
305
306 void wxEmulatorFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
307 {
308 wxString msg;
309 msg.Printf( _T("wxEmulator is an environment for testing embedded X11 apps.\n"));
310
311 wxMessageBox(msg, _T("About wxEmulator"), wxOK | wxICON_INFORMATION, this);
312 }
313
314 void wxEmulatorFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
315 {
316 #ifdef __WXX11__
317 if (wxGetApp().m_xnestWindow)
318 {
319 wxGetApp().m_xnestWindow->SetHandle((WXWindow) NULL);
320 }
321 #endif
322 this->Destroy();
323 if (wxGetApp().m_xnestPID > 0)
324 {
325 wxKill(wxGetApp().m_xnestPID);
326 wxGetApp().m_xnestPID = 0;
327 }
328 }
329
330 IMPLEMENT_CLASS(wxEmulatorContainer, wxWindow)
331
332 BEGIN_EVENT_TABLE(wxEmulatorContainer, wxWindow)
333 EVT_SIZE(wxEmulatorContainer::OnSize)
334 EVT_PAINT(wxEmulatorContainer::OnPaint)
335 EVT_ERASE_BACKGROUND(wxEmulatorContainer::OnEraseBackground)
336 END_EVENT_TABLE()
337
338 wxEmulatorContainer::wxEmulatorContainer(wxWindow* parent, wxWindowID id):
339 wxWindow(parent, id, wxDefaultPosition, wxDefaultSize)
340 {
341 }
342
343 void wxEmulatorContainer::OnSize(wxSizeEvent& WXUNUSED(event))
344 {
345 DoResize();
346 }
347
348 void wxEmulatorContainer::DoResize()
349 {
350 wxSize sz = GetClientSize();
351 if (wxGetApp().m_xnestWindow
352 #ifdef __WXX11__
353 && wxGetApp().m_xnestWindow->GetMainWindow()
354 #endif
355 )
356 {
357 int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x;
358 int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y;
359
360 int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0));
361 int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0));
362
363 x += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.x;
364 y += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.y;
365
366 wxGetApp().m_xnestWindow->Move(x, y);
367 }
368 Refresh();
369 }
370
371 void wxEmulatorContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
372 {
373 wxPaintDC dc(this);
374
375 wxSize sz = GetClientSize();
376 if (wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.Ok())
377 {
378 int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x;
379 int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y;
380
381 int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0));
382 int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0));
383
384 dc.DrawBitmap(wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap, x, y);
385 }
386 }
387
388 void wxEmulatorContainer::OnEraseBackground(wxEraseEvent& event)
389 {
390 wxDC* dc wxDUMMY_INITIALIZE(NULL);
391
392 if (event.GetDC())
393 {
394 dc = event.GetDC();
395 }
396 else
397 {
398 dc = new wxClientDC(this);
399 }
400
401 dc->SetBackground(wxBrush(wxGetApp().m_emulatorInfo.m_emulatorBackgroundColour, wxSOLID));
402 dc->Clear();
403
404 if (!event.GetDC())
405 delete dc;
406 }
407
408 // Information about the emulator decorations
409
410 void wxEmulatorInfo::Copy(const wxEmulatorInfo& info)
411 {
412 m_emulatorFilename = info.m_emulatorFilename;
413 m_emulatorTitle = info.m_emulatorTitle;
414 m_emulatorDescription = info.m_emulatorDescription;
415 m_emulatorScreenPosition = info.m_emulatorScreenPosition;
416 m_emulatorScreenSize = info.m_emulatorScreenSize;
417 m_emulatorBackgroundBitmap = info.m_emulatorBackgroundBitmap;
418 m_emulatorBackgroundBitmapName = info.m_emulatorBackgroundBitmapName;
419 m_emulatorBackgroundColour = info.m_emulatorBackgroundColour;
420 m_emulatorDeviceSize = info.m_emulatorDeviceSize;
421 }
422
423 // Initialisation
424 void wxEmulatorInfo::Init()
425 {
426 m_emulatorDeviceSize = wxSize(260, 340);
427 m_emulatorScreenSize = wxSize(240, 320);
428 }
429
430 // Loads bitmaps
431 bool wxEmulatorInfo::Load(const wxString& appDir)
432 {
433 // Try to find absolute path
434 wxString absoluteConfigPath = m_emulatorFilename;
435 if ( !::wxIsAbsolutePath(absoluteConfigPath) )
436 {
437 wxString currDir = wxGetCwd();
438 absoluteConfigPath = currDir + wxString(wxFILE_SEP_PATH) + m_emulatorFilename;
439 if ( !wxFile::Exists(absoluteConfigPath) )
440 {
441 absoluteConfigPath = appDir + wxString(wxFILE_SEP_PATH)
442 + m_emulatorFilename;
443 }
444 }
445
446 if ( !wxFile::Exists(absoluteConfigPath) )
447 {
448 wxString str;
449 str.Printf( wxT("Could not find config file %s"),
450 absoluteConfigPath.c_str() );
451
452 wxMessageBox(str);
453 return false;
454 }
455
456 wxString rootPath = wxPathOnly(absoluteConfigPath);
457
458 {
459 wxFileConfig config(wxT("wxEmulator"), wxT("wxWidgets"),
460 absoluteConfigPath, wxEmptyString, wxCONFIG_USE_LOCAL_FILE);
461
462 config.Read(wxT("/General/title"), & m_emulatorTitle);
463 config.Read(wxT("/General/description"), & m_emulatorDescription);
464 config.Read(wxT("/General/backgroundBitmap"), & m_emulatorBackgroundBitmapName);
465
466 wxString colString;
467 if (config.Read(wxT("/General/backgroundColour"), & colString) ||
468 config.Read(wxT("/General/backgroundColor"), & colString)
469 )
470 {
471 m_emulatorBackgroundColour = wxHexStringToColour(colString);
472 }
473
474 int x = 0, y = 0, w = 0, h = 0, dw = 0, dh = 0;
475 config.Read(wxT("/General/screenX"), & x);
476 config.Read(wxT("/General/screenY"), & y);
477 config.Read(wxT("/General/screenWidth"), & w);
478 config.Read(wxT("/General/screenHeight"), & h);
479 if (config.Read(wxT("/General/deviceWidth"), & dw) && config.Read(wxT("/General/deviceHeight"), & dh))
480 {
481 m_emulatorDeviceSize = wxSize(dw, dh);
482 }
483
484 m_emulatorScreenPosition = wxPoint(x, y);
485 m_emulatorScreenSize = wxSize(w, h);
486 }
487
488 if (!m_emulatorBackgroundBitmapName.IsEmpty())
489 {
490 wxString absoluteBackgroundBitmapName = rootPath + wxString(wxFILE_SEP_PATH) + m_emulatorBackgroundBitmapName;
491 if ( !wxFile::Exists(absoluteBackgroundBitmapName) )
492 {
493 wxString str;
494 str.Printf( wxT("Could not find bitmap %s"),
495 absoluteBackgroundBitmapName.c_str() );
496 wxMessageBox(str);
497 return false;
498 }
499
500 wxBitmapType type = wxDetermineImageType(m_emulatorBackgroundBitmapName);
501 if (type == wxBITMAP_TYPE_INVALID)
502 return false;
503
504 if (!m_emulatorBackgroundBitmap.LoadFile(m_emulatorBackgroundBitmapName, type))
505 {
506 wxString str;
507 str.Printf( wxT("Could not load bitmap file %s"),
508 m_emulatorBackgroundBitmapName.c_str() );
509 wxMessageBox(str);
510 return false;
511 }
512
513 m_emulatorDeviceSize = wxSize(m_emulatorBackgroundBitmap.GetWidth(),
514 m_emulatorBackgroundBitmap.GetHeight());
515 }
516 return true;
517 }
518
519 // Returns the image type, or -1, determined from the extension.
520 wxBitmapType wxDetermineImageType(const wxString& filename)
521 {
522 wxString path, name, ext;
523
524 wxSplitPath(filename, & path, & name, & ext);
525
526 ext.MakeLower();
527 if (ext == _T("jpg") || ext == _T("jpeg"))
528 return wxBITMAP_TYPE_JPEG;
529 if (ext == _T("gif"))
530 return wxBITMAP_TYPE_GIF;
531 if (ext == _T("bmp"))
532 return wxBITMAP_TYPE_BMP;
533 if (ext == _T("png"))
534 return wxBITMAP_TYPE_PNG;
535 if (ext == _T("pcx"))
536 return wxBITMAP_TYPE_PCX;
537 if (ext == _T("tif") || ext == _T("tiff"))
538 return wxBITMAP_TYPE_TIF;
539
540 return wxBITMAP_TYPE_INVALID;
541 }
542
543 // Convert a colour to a 6-digit hex string
544 wxString wxColourToHexString(const wxColour& col)
545 {
546 wxString hex;
547
548 hex += wxDecToHex(col.Red());
549 hex += wxDecToHex(col.Green());
550 hex += wxDecToHex(col.Blue());
551
552 return hex;
553 }
554
555 // Convert 6-digit hex string to a colour
556 wxColour wxHexStringToColour(const wxString& hex)
557 {
558 unsigned int r = wxHexToDec(hex.Mid(0, 2));
559 unsigned int g = wxHexToDec(hex.Mid(2, 2));
560 unsigned int b = wxHexToDec(hex.Mid(4, 2));
561
562 return wxColour(r, g, b);
563 }
564
565 // Find the absolute path where this application has been run from.
566 // argv0 is wxTheApp->argv[0]
567 // cwd is the current working directory (at startup)
568 // appVariableName is the name of a variable containing the directory for this app, e.g.
569 // MYAPPDIR. This is checked first.
570
571 wxString wxFindAppPath(const wxString& argv0, const wxString& cwd, const wxString& appVariableName)
572 {
573 wxString str;
574
575 // Try appVariableName
576 if (!appVariableName.IsEmpty())
577 {
578 str = wxGetenv(appVariableName);
579 if (!str.IsEmpty())
580 return str;
581 }
582
583 if (wxIsAbsolutePath(argv0))
584 return wxPathOnly(argv0);
585 else
586 {
587 // Is it a relative path?
588 wxString currentDir(cwd);
589 if (!wxEndsWithPathSeparator(currentDir))
590 currentDir += wxFILE_SEP_PATH;
591
592 str = currentDir + argv0;
593 if ( wxFile::Exists(str) )
594 return wxPathOnly(str);
595 }
596
597 // OK, it's neither an absolute path nor a relative path.
598 // Search PATH.
599
600 wxPathList pathList;
601 pathList.AddEnvList(wxT("PATH"));
602 str = pathList.FindAbsoluteValidPath(argv0);
603 if (!str.IsEmpty())
604 return wxPathOnly(str);
605
606 // Failed
607 return wxEmptyString;
608 }
609