1 // main.cpp 2 3 #include <stdio.h> 4 #include <string.h> 5 6 #include "Application.h" 7 #include "Bitmap.h" 8 #include "Button.h" 9 #include "Message.h" 10 #include "View.h" 11 #include "Window.h" 12 13 #include "bitmap.h" 14 15 enum { 16 MSG_RESET = 'rset', 17 }; 18 19 class TestView : public BView { 20 21 public: 22 TestView(BRect frame, const char* name, 23 uint32 resizeFlags, uint32 flags) 24 : BView(frame, name, resizeFlags, flags), 25 // fBitmap(new BBitmap(BRect(0, 0, kBitmapWidth - 1, kBitmapHeight -1), 26 // 0, kBitmapFormat)), 27 fBitmap(new BBitmap(BRect(0, 0, 32 - 1, 8 - 1), 28 0, B_CMAP8)), 29 // fBitmap(new BBitmap(BRect(0, 0, 32 - 1, 8 - 1), 30 // 0, B_GRAY8)), 31 fBitmapRect(), 32 fTracking(TRACKING_NONE), 33 fLastMousePos(-1.0, -1.0) 34 { 35 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 36 SetLowColor(ViewColor()); 37 // uint32 size = min_c((uint32)fBitmap->BitsLength(), sizeof(kBitmapBits)); 38 // memcpy(fBitmap->Bits(), kBitmapBits, size); 39 uint8* bits = (uint8*)fBitmap->Bits(); 40 uint32 width = fBitmap->Bounds().IntegerWidth() + 1; 41 uint32 height = fBitmap->Bounds().IntegerHeight() + 1; 42 uint32 bpr = fBitmap->BytesPerRow(); 43 printf("width: %ld, height: %ld, bpr: %ld\n", width, height, bpr); 44 int32 index = 0; 45 for (uint32 y = 0; y < height; y++) { 46 uint8* h = bits; 47 for (uint32 x = 0; x < width; x++) { 48 *h = index++; 49 h++; 50 } 51 bits += bpr; 52 } 53 BRect a(0.0, 10.0, 20.0, 10.0); 54 BRect b(0.0, 10.0, 10.0, 30.0); 55 printf("Intersects: %d\n", a.Intersects(b)); 56 _ResetRect(); 57 } 58 59 virtual void MessageReceived(BMessage* message); 60 61 virtual void Draw(BRect updateRect); 62 63 virtual void MouseDown(BPoint where); 64 virtual void MouseUp(BPoint where); 65 virtual void MouseMoved(BPoint where, uint32 transit, 66 const BMessage* dragMessage); 67 68 private: 69 void _ResetRect(); 70 void _InvalidateBitmapRect(BRect r); 71 void _DrawCross(BPoint where, rgb_color c); 72 73 BBitmap* fBitmap; 74 BRect fBitmapRect; 75 76 enum { 77 TRACKING_NONE = 0, 78 79 TRACKING_LEFT, 80 TRACKING_RIGHT, 81 TRACKING_TOP, 82 TRACKING_BOTTOM, 83 84 TRACKING_LEFT_TOP, 85 TRACKING_RIGHT_TOP, 86 TRACKING_LEFT_BOTTOM, 87 TRACKING_RIGHT_BOTTOM, 88 89 TRACKING_ALL 90 }; 91 92 uint32 fTracking; 93 BPoint fLastMousePos; 94 }; 95 96 // MessageReceived 97 void 98 TestView::MessageReceived(BMessage* message) 99 { 100 if (message->what == MSG_RESET) { 101 BRect old = fBitmapRect; 102 _ResetRect(); 103 _InvalidateBitmapRect(old | fBitmapRect); 104 } else 105 BView::MessageReceived(message); 106 } 107 108 // Draw 109 void 110 TestView::Draw(BRect updateRect) 111 { 112 SetDrawingMode(B_OP_COPY); 113 DrawBitmap(fBitmap, fBitmap->Bounds(), fBitmapRect); 114 115 // indicate the frame to see any errors in the drawing code 116 rgb_color red = (rgb_color){ 255, 0, 0, 255 }; 117 _DrawCross(fBitmapRect.LeftTop() + BPoint(-1.0, -1.0), red); 118 _DrawCross(fBitmapRect.RightTop() + BPoint(1.0, -1.0), red); 119 _DrawCross(fBitmapRect.LeftBottom() + BPoint(-1.0, 1.0), red); 120 _DrawCross(fBitmapRect.RightBottom() + BPoint(1.0, 1.0), red); 121 122 // text 123 SetDrawingMode(B_OP_ALPHA); 124 const char* message = "Click and drag to move and resize the bitmap!"; 125 BPoint textPos(20.0, 30.0); 126 SetHighColor(255, 255, 255, 180); 127 DrawString(message, textPos); 128 SetHighColor(0, 0, 0, 180); 129 DrawString(message, textPos + BPoint(-1.0, -1.0)); 130 } 131 132 bool 133 hit_test(BPoint where, BPoint p) 134 { 135 BRect r(p, p); 136 r.InsetBy(-5.0, -5.0); 137 return r.Contains(where); 138 } 139 140 bool 141 hit_test(BPoint where, BPoint a, BPoint b) 142 { 143 BRect r(a, b); 144 if (a.x == b.x) 145 r.InsetBy(-3.0, 0.0); 146 else 147 r.InsetBy(0.0, -3.0); 148 return r.Contains(where); 149 } 150 151 // MouseDown 152 void 153 TestView::MouseDown(BPoint where) 154 { 155 fTracking = TRACKING_NONE; 156 157 // check if we hit a corner 158 if (hit_test(where, fBitmapRect.LeftTop())) 159 fTracking = TRACKING_LEFT_TOP; 160 else if (hit_test(where, fBitmapRect.RightTop())) 161 fTracking = TRACKING_RIGHT_TOP; 162 else if (hit_test(where, fBitmapRect.LeftBottom())) 163 fTracking = TRACKING_LEFT_BOTTOM; 164 else if (hit_test(where, fBitmapRect.RightBottom())) 165 fTracking = TRACKING_RIGHT_BOTTOM; 166 // check if we hit a side 167 else if (hit_test(where, fBitmapRect.LeftTop(), fBitmapRect.RightTop())) 168 fTracking = TRACKING_TOP; 169 else if (hit_test(where, fBitmapRect.LeftTop(), fBitmapRect.LeftBottom())) 170 fTracking = TRACKING_LEFT; 171 else if (hit_test(where, fBitmapRect.RightTop(), fBitmapRect.RightBottom())) 172 fTracking = TRACKING_RIGHT; 173 else if (hit_test(where, fBitmapRect.LeftBottom(), fBitmapRect.RightBottom())) 174 fTracking = TRACKING_BOTTOM; 175 // check if we hit inside the rect 176 else if (fBitmapRect.Contains(where)) 177 fTracking = TRACKING_ALL; 178 179 fLastMousePos = where; 180 } 181 182 // MouseUp 183 void 184 TestView::MouseUp(BPoint where) 185 { 186 fTracking = TRACKING_NONE; 187 } 188 189 // MouseMoved 190 void 191 TestView::MouseMoved(BPoint where, uint32 transit, 192 const BMessage* dragMessage) 193 { 194 if (fTracking > TRACKING_NONE) { 195 BRect old = fBitmapRect; 196 BPoint offset = where - fLastMousePos; 197 switch (fTracking) { 198 case TRACKING_LEFT_TOP: 199 fBitmapRect.Set(fBitmapRect.left + offset.x, 200 fBitmapRect.top + offset.y, 201 fBitmapRect.right, 202 fBitmapRect.bottom); 203 break; 204 case TRACKING_RIGHT_BOTTOM: 205 fBitmapRect.Set(fBitmapRect.left, 206 fBitmapRect.top, 207 fBitmapRect.right + offset.x, 208 fBitmapRect.bottom + offset.y); 209 break; 210 case TRACKING_LEFT_BOTTOM: 211 fBitmapRect.Set(fBitmapRect.left + offset.x, 212 fBitmapRect.top, 213 fBitmapRect.right, 214 fBitmapRect.bottom + offset.y); 215 break; 216 case TRACKING_RIGHT_TOP: 217 fBitmapRect.Set(fBitmapRect.left, 218 fBitmapRect.top + offset.y, 219 fBitmapRect.right + offset.x, 220 fBitmapRect.bottom); 221 break; 222 case TRACKING_LEFT: 223 fBitmapRect.Set(fBitmapRect.left + offset.x, 224 fBitmapRect.top, 225 fBitmapRect.right, 226 fBitmapRect.bottom); 227 break; 228 case TRACKING_TOP: 229 fBitmapRect.Set(fBitmapRect.left, 230 fBitmapRect.top + offset.y, 231 fBitmapRect.right, 232 fBitmapRect.bottom); 233 break; 234 case TRACKING_RIGHT: 235 fBitmapRect.Set(fBitmapRect.left, 236 fBitmapRect.top, 237 fBitmapRect.right + offset.x, 238 fBitmapRect.bottom); 239 break; 240 case TRACKING_BOTTOM: 241 fBitmapRect.Set(fBitmapRect.left, 242 fBitmapRect.top, 243 fBitmapRect.right, 244 fBitmapRect.bottom + offset.y); 245 break; 246 case TRACKING_ALL: 247 default: 248 fBitmapRect.OffsetBy(offset); 249 break; 250 } 251 fLastMousePos = where; 252 if (old != fBitmapRect) 253 _InvalidateBitmapRect(old | fBitmapRect); 254 } 255 } 256 257 // _ResetRect 258 void 259 TestView::_ResetRect() 260 { 261 fBitmapRect = fBitmap->Bounds(); 262 fBitmapRect.OffsetBy(floorf((Bounds().Width() - fBitmapRect.Width()) / 2.0 + 0.5), 263 floorf((Bounds().Height() - fBitmapRect.Height()) / 2.0 + 0.5)); 264 } 265 266 // _InvalidateBitmapRect 267 void 268 TestView::_InvalidateBitmapRect(BRect r) 269 { 270 r.InsetBy(-4.0, -4.0); 271 Invalidate(r); 272 } 273 274 // _DrawCross 275 void 276 TestView::_DrawCross(BPoint where, rgb_color c) 277 { 278 BeginLineArray(4); 279 AddLine(BPoint(where.x, where.y - 3), 280 BPoint(where.x, where.y - 1), c); 281 AddLine(BPoint(where.x, where.y + 1), 282 BPoint(where.x, where.y + 3), c); 283 AddLine(BPoint(where.x - 3, where.y), 284 BPoint(where.x - 1, where.y), c); 285 AddLine(BPoint(where.x + 1, where.y), 286 BPoint(where.x + 3, where.y), c); 287 EndLineArray(); 288 } 289 290 // show_window 291 void 292 show_window(BRect frame, const char* name) 293 { 294 BWindow* window = new BWindow(frame, name, 295 B_TITLED_WINDOW, 296 B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE); 297 298 BView* view = new TestView(window->Bounds(), "test", B_FOLLOW_ALL, 299 B_WILL_DRAW/* | B_FULL_UPDATE_ON_RESIZE*/); 300 301 window->AddChild(view); 302 BRect b(0.0, 0.0, 60.0, 15.0); 303 b.OffsetTo(5.0, view->Bounds().bottom - (b.Height() + 15.0)); 304 BButton* control = new BButton(b, "button", "Reset", new BMessage(MSG_RESET), 305 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 306 view->AddChild(control); 307 control->SetTarget(view); 308 309 window->Show(); 310 } 311 312 // main 313 int 314 main(int argc, char** argv) 315 { 316 BApplication* app = new BApplication("application/x.vnd-Haiku.BitmapDrawing"); 317 318 BRect frame(50.0, 50.0, 400.0, 250.0); 319 show_window(frame, "Bitmap Drawing"); 320 321 app->Run(); 322 323 delete app; 324 return 0; 325 } 326