The Android Open Source Project | 52d4c30 | 2009-03-03 19:29:09 -0800 | [diff] [blame] | 1 | // |
| 2 | // Copyright 2005 The Android Open Source Project |
| 3 | // |
| 4 | // Displays output from the device. |
| 5 | // |
| 6 | |
| 7 | // For compilers that support precompilation, include "wx/wx.h". |
| 8 | #include "wx/wxprec.h" |
| 9 | |
| 10 | // Otherwise, include all standard headers |
| 11 | #ifndef WX_PRECOMP |
| 12 | # include "wx/wx.h" |
| 13 | #endif |
| 14 | #include "wx/image.h" // needed for Windows build |
| 15 | #include "wx/dcbuffer.h" |
| 16 | |
| 17 | #include "AssetStream.h" |
| 18 | #include "DeviceWindow.h" |
| 19 | #include "MyApp.h" |
| 20 | #include "Preferences.h" |
| 21 | |
| 22 | BEGIN_EVENT_TABLE(DeviceWindow, wxWindow) |
| 23 | EVT_SIZE(DeviceWindow::OnSize) |
| 24 | EVT_ERASE_BACKGROUND(DeviceWindow::OnErase) |
| 25 | EVT_PAINT(DeviceWindow::OnPaint) |
| 26 | EVT_KEY_DOWN(DeviceWindow::OnKeyDown) |
| 27 | EVT_KEY_UP(DeviceWindow::OnKeyUp) |
| 28 | |
| 29 | EVT_LEFT_DOWN(DeviceWindow::OnMouseLeftDown) |
| 30 | EVT_LEFT_DCLICK(DeviceWindow::OnMouseLeftDown) |
| 31 | EVT_LEFT_UP(DeviceWindow::OnMouseLeftUp) |
| 32 | EVT_RIGHT_DOWN(DeviceWindow::OnMouseRightDown) |
| 33 | EVT_RIGHT_DCLICK(DeviceWindow::OnMouseRightDown) |
| 34 | EVT_RIGHT_UP(DeviceWindow::OnMouseRightUp) |
| 35 | EVT_MOTION(DeviceWindow::OnMouseMotion) |
| 36 | |
| 37 | EVT_USER_EVENT(DeviceWindow::OnUserEvent) |
| 38 | END_EVENT_TABLE() |
| 39 | |
| 40 | |
| 41 | /* |
| 42 | * Create a new DeviceWindow. This should be a child of PhoneWindow. |
| 43 | * |
| 44 | * Note the DeviceManager may not be fully initialized yet. |
| 45 | */ |
| 46 | DeviceWindow::DeviceWindow(wxWindow* parent, DeviceManager* pDM) |
| 47 | : wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, |
| 48 | wxNO_BORDER | wxWANTS_CHARS), |
| 49 | mpDeviceManager(pDM) |
| 50 | { |
| 51 | //printf("DW: created (parent=%p DM=%p)\n", parent, pDM); |
| 52 | |
| 53 | SetBackgroundStyle(wxBG_STYLE_CUSTOM); |
| 54 | |
| 55 | // create a trivial bitmap so we have something allocated |
| 56 | mBitmap.Create(1, 1); |
| 57 | |
| 58 | } |
| 59 | |
| 60 | /* |
| 61 | * Destructor. |
| 62 | */ |
| 63 | DeviceWindow::~DeviceWindow(void) |
| 64 | { |
| 65 | } |
| 66 | |
| 67 | /* |
| 68 | * We don't want to trap key or mouse events here. |
| 69 | * |
| 70 | * event.Skip() didn't seem to do the trick, so we call AddPendingEvent() |
| 71 | * to add it to the parent's input queue. |
| 72 | */ |
| 73 | void DeviceWindow::OnKeyDown(wxKeyEvent& event) |
| 74 | { |
| 75 | //printf("DW: down: %d\n", event.GetKeyCode()); |
| 76 | GetParent()->AddPendingEvent(event); |
| 77 | } |
| 78 | void DeviceWindow::OnKeyUp(wxKeyEvent& event) |
| 79 | { |
| 80 | //printf("DW: up: %d\n", event.GetKeyCode()); |
| 81 | GetParent()->AddPendingEvent(event); |
| 82 | } |
| 83 | |
| 84 | /* |
| 85 | * Handle mouse events. We want to pass these up to the PhoneWindow, since |
| 86 | * that's where the "touch screen" code is. |
| 87 | */ |
| 88 | void DeviceWindow::OnMouseLeftDown(wxMouseEvent& event) |
| 89 | { |
| 90 | ClampMouse(&event); |
| 91 | GetParent()->AddPendingEvent(event); |
| 92 | } |
| 93 | void DeviceWindow::OnMouseLeftUp(wxMouseEvent& event) |
| 94 | { |
| 95 | ClampMouse(&event); |
| 96 | GetParent()->AddPendingEvent(event); |
| 97 | } |
| 98 | void DeviceWindow::OnMouseRightDown(wxMouseEvent& event) |
| 99 | { |
| 100 | ClampMouse(&event); |
| 101 | GetParent()->AddPendingEvent(event); |
| 102 | } |
| 103 | void DeviceWindow::OnMouseRightUp(wxMouseEvent& event) |
| 104 | { |
| 105 | ClampMouse(&event); |
| 106 | GetParent()->AddPendingEvent(event); |
| 107 | } |
| 108 | void DeviceWindow::OnMouseMotion(wxMouseEvent& event) |
| 109 | { |
| 110 | ClampMouse(&event); |
| 111 | GetParent()->AddPendingEvent(event); |
| 112 | } |
| 113 | |
| 114 | /* |
| 115 | * Clamp the mouse movement to the window bounds. |
| 116 | */ |
| 117 | void DeviceWindow::ClampMouse(wxMouseEvent* pEvent) |
| 118 | { |
| 119 | wxWindow* pEventWindow = (wxWindow*) pEvent->GetEventObject(); |
| 120 | int width, height; |
| 121 | |
| 122 | pEventWindow->GetSize(&width, &height); |
| 123 | if (pEvent->m_x < 0) |
| 124 | pEvent->m_x = 0; |
| 125 | else if (pEvent->m_x >= width) |
| 126 | pEvent->m_x = width-1; |
| 127 | |
| 128 | if (pEvent->m_y < 0) |
| 129 | pEvent->m_y = 0; |
| 130 | else if (pEvent->m_y >= height) |
| 131 | pEvent->m_y = height-1; |
| 132 | } |
| 133 | |
| 134 | |
| 135 | /* |
| 136 | * Handle a "user event". We get these when the runtime wants us to |
| 137 | * know that it has a new frame of graphics to display. |
| 138 | * |
| 139 | */ |
| 140 | void DeviceWindow::OnUserEvent(UserEvent& event) |
| 141 | { |
| 142 | wxBitmap* pBitmap; |
| 143 | long displayIndex; |
| 144 | |
| 145 | displayIndex = (long) event.GetData(); |
| 146 | |
| 147 | //printf("GOT UAE %d\n", displayIndex); |
| 148 | |
| 149 | // a displayIndex of -1 means just update the onion skin |
| 150 | if (displayIndex >= 0) { |
| 151 | /* get a newly-allocated bitmap with converted image data */ |
| 152 | pBitmap = mpDeviceManager->GetImageData(displayIndex); |
| 153 | |
| 154 | /* do a ptr/refcount assignment to hold the data */ |
| 155 | mBitmap = *pBitmap; |
| 156 | /* delete the temporary object; does not delete the bitmap storage */ |
| 157 | delete pBitmap; |
| 158 | } |
| 159 | |
| 160 | if (displayIndex >= -1) { |
| 161 | mHasOnionSkinBitmap = false; |
| 162 | |
| 163 | Preferences* pPrefs = ((MyApp*)wxTheApp)->GetPrefs(); |
| 164 | assert(pPrefs != NULL); |
| 165 | |
| 166 | bool overlayOnionSkin; |
| 167 | char* onionSkinFileName = NULL; |
| 168 | |
| 169 | bool overlayOnionSkinExists = pPrefs->GetBool("overlay-onion-skin", &overlayOnionSkin); |
| 170 | if (overlayOnionSkinExists && overlayOnionSkin) { |
| 171 | bool fileNameExists = pPrefs->GetString("onion-skin-file-name", &onionSkinFileName); |
| 172 | if (fileNameExists && *onionSkinFileName) { |
| 173 | wxImage onionSkinImage(wxString::FromAscii(onionSkinFileName)); |
| 174 | onionSkinImage.SetAlpha(NULL); |
Patrick Scott | ed149c2 | 2010-10-08 10:11:04 -0400 | [diff] [blame^] | 175 | bool hasAlpha = onionSkinImage.HasAlpha(); |
The Android Open Source Project | 52d4c30 | 2009-03-03 19:29:09 -0800 | [diff] [blame] | 176 | int width = onionSkinImage.GetWidth(); |
| 177 | int height = onionSkinImage.GetHeight(); |
| 178 | if (hasAlpha) { |
| 179 | unsigned char *alpha = onionSkinImage.GetAlpha(); |
| 180 | int alphaVal = 127; |
| 181 | pPrefs->GetInt("onion-skin-alpha-value", &alphaVal); |
| 182 | for (int i = (width * height) - 1; i >= 0; i--) { |
| 183 | alpha[i] = alphaVal; |
| 184 | } |
| 185 | } |
| 186 | mOnionSkinBitmap = wxBitmap(onionSkinImage); |
| 187 | mHasOnionSkinBitmap = true; |
| 188 | } |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | /* induce an update */ |
| 193 | Refresh(); |
| 194 | } |
| 195 | |
| 196 | /* |
| 197 | * Window has been moved or resized. |
| 198 | * |
| 199 | * We get this when the model of phone is changed. |
| 200 | * |
| 201 | * FIX: in the future this only happens when the phone is rotated 90deg. |
| 202 | */ |
| 203 | void DeviceWindow::OnSize(wxSizeEvent& WXUNUSED(event)) |
| 204 | { |
| 205 | int width, height; |
| 206 | |
| 207 | GetClientSize(&width, &height); |
| 208 | printf("Sim: device window resize: %dx%d\n", width, height); |
| 209 | |
| 210 | mBitmap.Create(width, height); |
| 211 | |
| 212 | wxMemoryDC memDC; |
| 213 | memDC.SelectObject(mBitmap); |
| 214 | |
| 215 | wxColour backColor(96, 122, 121); |
| 216 | memDC.SetBrush(wxBrush(backColor)); |
| 217 | memDC.SetPen(wxPen(backColor, 1)); |
| 218 | wxRect windowRect(wxPoint(0, 0), GetClientSize()); |
| 219 | memDC.DrawRectangle(windowRect); |
| 220 | } |
| 221 | |
| 222 | /* |
| 223 | * No need to erase the background. |
| 224 | */ |
| 225 | void DeviceWindow::OnErase(wxEraseEvent& WXUNUSED(event)) |
| 226 | { |
| 227 | //printf("erase device\n"); |
| 228 | } |
| 229 | |
| 230 | /* |
| 231 | * Repaint the simulator output. |
| 232 | */ |
| 233 | void DeviceWindow::OnPaint(wxPaintEvent& WXUNUSED(event)) |
| 234 | { |
| 235 | wxPaintDC dc(this); |
| 236 | |
| 237 | /* draw background image */ |
| 238 | dc.DrawBitmap(mBitmap, 0, 0, TRUE); |
| 239 | |
| 240 | /* If necessary, draw onion skin image on top */ |
| 241 | if (mHasOnionSkinBitmap) { |
| 242 | dc.DrawBitmap(mOnionSkinBitmap, 0, 0, TRUE); |
| 243 | } |
| 244 | |
| 245 | #if 0 |
| 246 | // debug - draw the corners |
| 247 | int xoff = 0; |
| 248 | int yoff = 0; |
| 249 | int width; |
| 250 | int height; |
| 251 | GetClientSize(&width, &height); |
| 252 | |
| 253 | dc.SetPen(*wxGREEN_PEN); |
| 254 | dc.DrawLine(xoff, yoff+9, xoff, yoff); |
| 255 | dc.DrawLine(xoff, yoff, xoff+10, yoff); |
| 256 | dc.DrawLine(xoff+width-10, yoff, xoff+width, yoff); |
| 257 | dc.DrawLine(xoff+width-1, yoff, xoff+width-1, yoff+10); |
| 258 | dc.DrawLine(xoff, yoff+height-10, xoff, yoff+height); |
| 259 | dc.DrawLine(xoff, yoff+height-1, xoff+10, yoff+height-1); |
| 260 | dc.DrawLine(xoff+width-1, yoff+height-10, xoff+width-1, yoff+height); |
| 261 | dc.DrawLine(xoff+width-1, yoff+height-1, xoff+width-11, yoff+height-1); |
| 262 | #endif |
| 263 | } |
| 264 | |