| // |
| // Copyright 2005 The Android Open Source Project |
| // |
| // Displays output from the device. |
| // |
| |
| // For compilers that support precompilation, include "wx/wx.h". |
| #include "wx/wxprec.h" |
| |
| // Otherwise, include all standard headers |
| #ifndef WX_PRECOMP |
| # include "wx/wx.h" |
| #endif |
| #include "wx/image.h" // needed for Windows build |
| #include "wx/dcbuffer.h" |
| |
| #include "AssetStream.h" |
| #include "DeviceWindow.h" |
| #include "MyApp.h" |
| #include "Preferences.h" |
| |
| BEGIN_EVENT_TABLE(DeviceWindow, wxWindow) |
| EVT_SIZE(DeviceWindow::OnSize) |
| EVT_ERASE_BACKGROUND(DeviceWindow::OnErase) |
| EVT_PAINT(DeviceWindow::OnPaint) |
| EVT_KEY_DOWN(DeviceWindow::OnKeyDown) |
| EVT_KEY_UP(DeviceWindow::OnKeyUp) |
| |
| EVT_LEFT_DOWN(DeviceWindow::OnMouseLeftDown) |
| EVT_LEFT_DCLICK(DeviceWindow::OnMouseLeftDown) |
| EVT_LEFT_UP(DeviceWindow::OnMouseLeftUp) |
| EVT_RIGHT_DOWN(DeviceWindow::OnMouseRightDown) |
| EVT_RIGHT_DCLICK(DeviceWindow::OnMouseRightDown) |
| EVT_RIGHT_UP(DeviceWindow::OnMouseRightUp) |
| EVT_MOTION(DeviceWindow::OnMouseMotion) |
| |
| EVT_USER_EVENT(DeviceWindow::OnUserEvent) |
| END_EVENT_TABLE() |
| |
| |
| /* |
| * Create a new DeviceWindow. This should be a child of PhoneWindow. |
| * |
| * Note the DeviceManager may not be fully initialized yet. |
| */ |
| DeviceWindow::DeviceWindow(wxWindow* parent, DeviceManager* pDM) |
| : wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, |
| wxNO_BORDER | wxWANTS_CHARS), |
| mpDeviceManager(pDM) |
| { |
| //printf("DW: created (parent=%p DM=%p)\n", parent, pDM); |
| |
| SetBackgroundStyle(wxBG_STYLE_CUSTOM); |
| |
| // create a trivial bitmap so we have something allocated |
| mBitmap.Create(1, 1); |
| |
| } |
| |
| /* |
| * Destructor. |
| */ |
| DeviceWindow::~DeviceWindow(void) |
| { |
| } |
| |
| /* |
| * We don't want to trap key or mouse events here. |
| * |
| * event.Skip() didn't seem to do the trick, so we call AddPendingEvent() |
| * to add it to the parent's input queue. |
| */ |
| void DeviceWindow::OnKeyDown(wxKeyEvent& event) |
| { |
| //printf("DW: down: %d\n", event.GetKeyCode()); |
| GetParent()->AddPendingEvent(event); |
| } |
| void DeviceWindow::OnKeyUp(wxKeyEvent& event) |
| { |
| //printf("DW: up: %d\n", event.GetKeyCode()); |
| GetParent()->AddPendingEvent(event); |
| } |
| |
| /* |
| * Handle mouse events. We want to pass these up to the PhoneWindow, since |
| * that's where the "touch screen" code is. |
| */ |
| void DeviceWindow::OnMouseLeftDown(wxMouseEvent& event) |
| { |
| ClampMouse(&event); |
| GetParent()->AddPendingEvent(event); |
| } |
| void DeviceWindow::OnMouseLeftUp(wxMouseEvent& event) |
| { |
| ClampMouse(&event); |
| GetParent()->AddPendingEvent(event); |
| } |
| void DeviceWindow::OnMouseRightDown(wxMouseEvent& event) |
| { |
| ClampMouse(&event); |
| GetParent()->AddPendingEvent(event); |
| } |
| void DeviceWindow::OnMouseRightUp(wxMouseEvent& event) |
| { |
| ClampMouse(&event); |
| GetParent()->AddPendingEvent(event); |
| } |
| void DeviceWindow::OnMouseMotion(wxMouseEvent& event) |
| { |
| ClampMouse(&event); |
| GetParent()->AddPendingEvent(event); |
| } |
| |
| /* |
| * Clamp the mouse movement to the window bounds. |
| */ |
| void DeviceWindow::ClampMouse(wxMouseEvent* pEvent) |
| { |
| wxWindow* pEventWindow = (wxWindow*) pEvent->GetEventObject(); |
| int width, height; |
| |
| pEventWindow->GetSize(&width, &height); |
| if (pEvent->m_x < 0) |
| pEvent->m_x = 0; |
| else if (pEvent->m_x >= width) |
| pEvent->m_x = width-1; |
| |
| if (pEvent->m_y < 0) |
| pEvent->m_y = 0; |
| else if (pEvent->m_y >= height) |
| pEvent->m_y = height-1; |
| } |
| |
| |
| /* |
| * Handle a "user event". We get these when the runtime wants us to |
| * know that it has a new frame of graphics to display. |
| * |
| */ |
| void DeviceWindow::OnUserEvent(UserEvent& event) |
| { |
| wxBitmap* pBitmap; |
| long displayIndex; |
| |
| displayIndex = (long) event.GetData(); |
| |
| //printf("GOT UAE %d\n", displayIndex); |
| |
| // a displayIndex of -1 means just update the onion skin |
| if (displayIndex >= 0) { |
| /* get a newly-allocated bitmap with converted image data */ |
| pBitmap = mpDeviceManager->GetImageData(displayIndex); |
| |
| /* do a ptr/refcount assignment to hold the data */ |
| mBitmap = *pBitmap; |
| /* delete the temporary object; does not delete the bitmap storage */ |
| delete pBitmap; |
| } |
| |
| if (displayIndex >= -1) { |
| mHasOnionSkinBitmap = false; |
| |
| Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs(); |
| assert(pPrefs != NULL); |
| |
| bool overlayOnionSkin; |
| char* onionSkinFileName = NULL; |
| |
| bool overlayOnionSkinExists = pPrefs->GetBool("overlay-onion-skin", &overlayOnionSkin); |
| if (overlayOnionSkinExists && overlayOnionSkin) { |
| bool fileNameExists = pPrefs->GetString("onion-skin-file-name", &onionSkinFileName); |
| if (fileNameExists && *onionSkinFileName) { |
| wxImage onionSkinImage(wxString::FromAscii(onionSkinFileName)); |
| onionSkinImage.SetAlpha(NULL); |
| bool hasAlpha = onionSkinImage.HasAlpha(); |
| int width = onionSkinImage.GetWidth(); |
| int height = onionSkinImage.GetHeight(); |
| if (hasAlpha) { |
| unsigned char *alpha = onionSkinImage.GetAlpha(); |
| int alphaVal = 127; |
| pPrefs->GetInt("onion-skin-alpha-value", &alphaVal); |
| for (int i = (width * height) - 1; i >= 0; i--) { |
| alpha[i] = alphaVal; |
| } |
| } |
| mOnionSkinBitmap = wxBitmap(onionSkinImage); |
| mHasOnionSkinBitmap = true; |
| } |
| } |
| } |
| |
| /* induce an update */ |
| Refresh(); |
| } |
| |
| /* |
| * Window has been moved or resized. |
| * |
| * We get this when the model of phone is changed. |
| * |
| * FIX: in the future this only happens when the phone is rotated 90deg. |
| */ |
| void DeviceWindow::OnSize(wxSizeEvent& WXUNUSED(event)) |
| { |
| int width, height; |
| |
| GetClientSize(&width, &height); |
| printf("Sim: device window resize: %dx%d\n", width, height); |
| |
| mBitmap.Create(width, height); |
| |
| wxMemoryDC memDC; |
| memDC.SelectObject(mBitmap); |
| |
| wxColour backColor(96, 122, 121); |
| memDC.SetBrush(wxBrush(backColor)); |
| memDC.SetPen(wxPen(backColor, 1)); |
| wxRect windowRect(wxPoint(0, 0), GetClientSize()); |
| memDC.DrawRectangle(windowRect); |
| } |
| |
| /* |
| * No need to erase the background. |
| */ |
| void DeviceWindow::OnErase(wxEraseEvent& WXUNUSED(event)) |
| { |
| //printf("erase device\n"); |
| } |
| |
| /* |
| * Repaint the simulator output. |
| */ |
| void DeviceWindow::OnPaint(wxPaintEvent& WXUNUSED(event)) |
| { |
| wxPaintDC dc(this); |
| |
| /* draw background image */ |
| dc.DrawBitmap(mBitmap, 0, 0, TRUE); |
| |
| /* If necessary, draw onion skin image on top */ |
| if (mHasOnionSkinBitmap) { |
| dc.DrawBitmap(mOnionSkinBitmap, 0, 0, TRUE); |
| } |
| |
| #if 0 |
| // debug - draw the corners |
| int xoff = 0; |
| int yoff = 0; |
| int width; |
| int height; |
| GetClientSize(&width, &height); |
| |
| dc.SetPen(*wxGREEN_PEN); |
| dc.DrawLine(xoff, yoff+9, xoff, yoff); |
| dc.DrawLine(xoff, yoff, xoff+10, yoff); |
| dc.DrawLine(xoff+width-10, yoff, xoff+width, yoff); |
| dc.DrawLine(xoff+width-1, yoff, xoff+width-1, yoff+10); |
| dc.DrawLine(xoff, yoff+height-10, xoff, yoff+height); |
| dc.DrawLine(xoff, yoff+height-1, xoff+10, yoff+height-1); |
| dc.DrawLine(xoff+width-1, yoff+height-10, xoff+width-1, yoff+height); |
| dc.DrawLine(xoff+width-1, yoff+height-1, xoff+width-11, yoff+height-1); |
| #endif |
| } |
| |