1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Emulator wxWidgets sample
4 // Author: Julian Smart
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
;