///////////////////////////////////////////////////////////////////////////// // Name: emulator.cpp // Purpose: Emulator wxWindows sample // Author: Julian Smart // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ // Copyright: (c) Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ // declarations // ============================================================================ #ifdef __GNUG__ #pragma implementation "emulator.h" #endif // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers (this file is usually all you // need because it includes almost all "standard" wxWindows headers) #ifndef WX_PRECOMP #include "wx/wx.h" #endif #ifdef __WXX11__ #include "wx/x11/reparent.h" #endif #include "emulator.h" // ---------------------------------------------------------------------------- // resources // ---------------------------------------------------------------------------- // the application icon (under Windows and OS/2 it is in resources) #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__) #include "mondrian.xpm" #endif // ---------------------------------------------------------------------------- // event tables and other macros for wxWindows // ---------------------------------------------------------------------------- // the event tables connect the wxWindows events with the functions (event // handlers) which process them. It can be also done at run-time, but for the // simple menu events like this the static method is much simpler. BEGIN_EVENT_TABLE(wxEmulatorFrame, wxFrame) EVT_MENU(Emulator_Quit, wxEmulatorFrame::OnQuit) EVT_MENU(Emulator_About, wxEmulatorFrame::OnAbout) END_EVENT_TABLE() // Create a new application object: this macro will allow wxWindows to create // the application object during program execution (it's better than using a // static object for many reasons) and also declares the accessor function // wxGetApp() which will return the reference of the right type (i.e. wxEmulatorApp and // not wxApp) IMPLEMENT_APP(wxEmulatorApp) // ============================================================================ // implementation // ============================================================================ // ---------------------------------------------------------------------------- // the application class // ---------------------------------------------------------------------------- wxEmulatorApp::wxEmulatorApp() { m_xnestWindow = NULL; m_containerWindow = NULL; } // 'Main program' equivalent: the program execution "starts" here bool wxEmulatorApp::OnInit() { wxInitAllImageHandlers(); // create the main application window wxEmulatorFrame *frame = new wxEmulatorFrame(_T("wxEmulator"), wxPoint(50, 50), wxSize(450, 340)); m_containerWindow = new wxEmulatorContainer(frame, -1); // Load the emulation info if (!LoadEmulator()) { frame->Destroy(); wxMessageBox(wxT("Sorry, could not load this emulator. Please check bitmaps are valid.")); return FALSE; } if (m_emulatorInfo.m_emulatorBackgroundBitmap.Ok()) frame->SetClientSize(m_emulatorInfo.m_emulatorBackgroundBitmap.GetWidth(), m_emulatorInfo.m_emulatorBackgroundBitmap.GetHeight()); // and show it (the frames, unlike simple controls, are not shown when // created initially) frame->Show(TRUE); #ifdef __WXX11__ m_xnestWindow = new wxAdoptedWindow; wxString cmd; // cmd.Printf(wxT("Xnest :100 -geometry %dx%d+50+50"), cmd.Printf(wxT("Xnest :100 -geometry %dx%d"), (int) m_emulatorInfo.m_emulatorScreenSize.x, (int) m_emulatorInfo.m_emulatorScreenSize.y); // Asynchronously executes Xnest if (0 == wxExecute(cmd)) { frame->Destroy(); wxMessageBox(wxT("Sorry, could not run Xnest. Please check your PATH.")); return FALSE; } wxReparenter reparenter; if (!reparenter.WaitAndReparent(m_containerWindow, m_xnestWindow, wxT("Xnest"))) { wxMessageBox(wxT("Sorry, could not reparent Xnest..")); frame->Destroy(); return FALSE; } m_containerWindow->DoResize(); #endif // success: wxApp::OnRun() will be called which will enter the main message // loop and the application will run. If we returned FALSE here, the // application would exit immediately. return TRUE; } // Load the specified emulator. // For now, hard-wired. TODO: make this configurable bool wxEmulatorApp::LoadEmulator() { m_emulatorInfo.m_emulatorTitle = wxT("iPAQ Emulator"); m_emulatorInfo.m_emulatorDescription = wxT("No description yet"); // The offset from the top-left of the main emulator // bitmap and the virtual screen (where Xnest is // positioned) m_emulatorInfo.m_emulatorScreenPosition = wxPoint(56, 69); // The emulated screen size m_emulatorInfo.m_emulatorScreenSize = wxSize(240, 320); m_emulatorInfo.m_emulatorBackgroundBitmapName = wxT("ipaq01.jpg"); m_emulatorInfo.m_emulatorBackgroundColour = * wxBLACK; return m_emulatorInfo.Load(); } // ---------------------------------------------------------------------------- // main frame // ---------------------------------------------------------------------------- // frame constructor wxEmulatorFrame::wxEmulatorFrame(const wxString& title, const wxPoint& pos, const wxSize& size) : wxFrame(NULL, -1, title, pos, size) { // set the frame icon SetIcon(wxICON(mondrian)); #if wxUSE_MENUS // create a menu bar wxMenu *menuFile = new wxMenu; // the "About" item should be in the help menu wxMenu *helpMenu = new wxMenu; helpMenu->Append(Emulator_About, _T("&About...\tF1"), _T("Show about dialog")); menuFile->Append(Emulator_Quit, _T("E&xit\tAlt-X"), _T("Quit this program")); // now append the freshly created menu to the menu bar... wxMenuBar *menuBar = new wxMenuBar(); menuBar->Append(menuFile, _T("&File")); menuBar->Append(helpMenu, _T("&Help")); // ... and attach this menu bar to the frame SetMenuBar(menuBar); #endif // wxUSE_MENUS #if wxUSE_STATUSBAR // create a status bar just for fun (by default with 1 pane only) CreateStatusBar(2); SetStatusText(_T("Welcome to wxWindows!")); #endif // wxUSE_STATUSBAR } // event handlers void wxEmulatorFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { // TRUE is to force the frame to close Close(TRUE); } void wxEmulatorFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { wxString msg; msg.Printf( _T("wxEmulator is an environment for testing embedded X11 apps.\n")); wxMessageBox(msg, _T("About wxEmulator"), wxOK | wxICON_INFORMATION, this); } IMPLEMENT_CLASS(wxEmulatorContainer, wxWindow) BEGIN_EVENT_TABLE(wxEmulatorContainer, wxWindow) EVT_SIZE(wxEmulatorContainer::OnSize) EVT_PAINT(wxEmulatorContainer::OnPaint) EVT_ERASE_BACKGROUND(wxEmulatorContainer::OnEraseBackground) END_EVENT_TABLE() wxEmulatorContainer::wxEmulatorContainer(wxWindow* parent, wxWindowID id): wxWindow(parent, id, wxDefaultPosition, wxDefaultSize) { } void wxEmulatorContainer::OnSize(wxSizeEvent& event) { DoResize(); } void wxEmulatorContainer::DoResize() { wxSize sz = GetClientSize(); if (wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.Ok() && wxGetApp().m_xnestWindow) { int bitmapWidth = wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.GetWidth(); int bitmapHeight = wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.GetHeight(); int x = wxMax(0, (int) ((sz.x - bitmapWidth)/2.0)); int y = wxMax(0, (int) ((sz.y - bitmapHeight)/2.0)); x += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.x; y += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.y; wxGetApp().m_xnestWindow->Move(x, y); } Refresh(); } void wxEmulatorContainer::OnPaint(wxPaintEvent& event) { wxPaintDC dc(this); wxSize sz = GetClientSize(); if (wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.Ok()) { int bitmapWidth = wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.GetWidth(); int bitmapHeight = wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.GetHeight(); int x = wxMax(0, (int) ((sz.x - bitmapWidth)/2.0)); int y = wxMax(0, (int) ((sz.y - bitmapHeight)/2.0)); dc.DrawBitmap(wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap, x, y); } } void wxEmulatorContainer::OnEraseBackground(wxEraseEvent& event) { wxDC* dc = NULL; if (event.GetDC()) { dc = event.GetDC(); } else { dc = new wxClientDC(this); } dc->SetBackground(wxBrush(wxGetApp().m_emulatorInfo.m_emulatorBackgroundColour, wxSOLID)); dc->Clear(); if (!event.GetDC()) delete dc; } // Information about the emulator decorations void wxEmulatorInfo::Copy(const wxEmulatorInfo& info) { m_emulatorTitle = info.m_emulatorTitle; m_emulatorDescription = info.m_emulatorDescription; m_emulatorScreenPosition = info.m_emulatorScreenPosition; m_emulatorScreenSize = info.m_emulatorScreenSize; m_emulatorBackgroundBitmap = info.m_emulatorBackgroundBitmap; m_emulatorBackgroundBitmapName = info.m_emulatorBackgroundBitmapName; m_emulatorBackgroundColour = info.m_emulatorBackgroundColour; } // Initialisation void wxEmulatorInfo::Init() { } // Loads bitmaps bool wxEmulatorInfo::Load() { if (m_emulatorBackgroundBitmapName.IsEmpty()) return FALSE; // TODO: prepend current directory if relative name int type = wxDetermineImageType(m_emulatorBackgroundBitmapName); if (type == -1) return FALSE; return m_emulatorBackgroundBitmap.LoadFile(m_emulatorBackgroundBitmapName, type); } // Returns the image type, or -1, determined from the extension. int wxDetermineImageType(const wxString& filename) { wxString path, name, ext; wxSplitPath(filename, & path, & name, & ext); ext.MakeLower(); if (ext == "jpg" || ext == "jpeg") return wxBITMAP_TYPE_JPEG; else if (ext == "gif") return wxBITMAP_TYPE_GIF; else if (ext == "bmp") return wxBITMAP_TYPE_BMP; else if (ext == "png") return wxBITMAP_TYPE_PNG; else if (ext == "pcx") return wxBITMAP_TYPE_PCX; else if (ext == "tif" || ext == "tiff") return wxBITMAP_TYPE_TIF; else return -1; }