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)") }, 
  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") }, 
  85     { wxCMD_LINE_PARAM
,  NULL
, NULL
, _T("config file 1"), wxCMD_LINE_VAL_STRING
, wxCMD_LINE_PARAM_OPTIONAL 
}, 
  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
.IsEmpty()) 
 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
.IsEmpty()) 
 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
;