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); 175 bool hasAlpha = onionSkinImage.HasAlpha(); 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 265