1 // ObjectView.cpp 2 3 #include <stdio.h> 4 5 #include <Application.h> 6 #include <Bitmap.h> 7 #include <Catalog.h> 8 #include <Cursor.h> 9 #include <Message.h> 10 #include <MessageQueue.h> 11 #include <Region.h> 12 #include <Shape.h> 13 #include <String.h> 14 #include <Window.h> 15 16 #include "ObjectView.h" 17 #include "States.h" 18 19 #undef B_TRANSLATION_CONTEXT 20 #define B_TRANSLATION_CONTEXT "Playground" 21 22 23 const unsigned char kMoveCursor[] = { 16, 1, 8, 8, 24 0x01, 0x80, 0x02, 0x40, 0x04, 0x20, 0x08, 0x10, 25 0x1e, 0x78, 0x2a, 0x54, 0x4e, 0x72, 0x80, 0x01, 26 0x80, 0x01, 0x4e, 0x72, 0x2a, 0x54, 0x1e, 0x78, 27 0x08, 0x10, 0x04, 0x20, 0x02, 0x40, 0x01, 0x80, 28 29 0x01, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 30 0x1f, 0xf8, 0x3b, 0xdc, 0x7f, 0xfe, 0xff, 0xff, 31 0xff, 0xff, 0x7f, 0xfe, 0x3b, 0xdc, 0x1f, 0xf8, 32 0x0f, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01, 0x80 }; 33 34 const unsigned char kGrabCursor[] = { 16, 1, 8, 9, 35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 36 0x0d, 0xb0, 0x12, 0x4c, 0x10, 0x0a, 0x08, 0x02, 37 0x18, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x04, 38 0x10, 0x04, 0x08, 0x08, 0x04, 0x08, 0x04, 0x08, 39 40 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 41 0x0d, 0xb0, 0x1f, 0xfc, 0x1f, 0xfe, 0x0f, 0xfe, 42 0x1f, 0xfe, 0x3f, 0xfe, 0x3f, 0xfe, 0x3f, 0xfc, 43 0x1f, 0xfc, 0x0f, 0xf8, 0x07, 0xf8, 0x07, 0xf8 }; 44 45 46 // constructor 47 ObjectView::ObjectView(BRect frame, const char* name, 48 uint32 resizeFlags, uint32 flags) 49 : BView(frame, name, resizeFlags, flags), 50 fState(NULL), 51 fObjectType(OBJECT_LINE), 52 fStateList(20), 53 fColor((rgb_color){ 0, 80, 255, 100 }), 54 fDrawingMode(B_OP_ALPHA), 55 fFill(false), 56 fPenSize(10.0), 57 fScrolling(false), 58 fInitiatingDrag(false), 59 fLastMousePos(0.0, 0.0) 60 { 61 62 SetLowColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_1_TINT)); 63 64 // BFont font; 65 // GetFont(&font); 66 // font.SetFamilyAndStyle("Bitstream Vera Serif", "Roman"); 67 // font.SetSize(20.0); 68 //// font.SetRotation(6.0); 69 // SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_ROTATION | B_FONT_SIZE); 70 71 // State* state = State::StateFor(OBJECT_ROUND_RECT, fColor, B_OP_COPY, 72 // false, 50.0); 73 // state->MouseDown(BPoint(15, 15)); 74 // state->MouseMoved(BPoint(255, 305)); 75 // state->MouseUp(); 76 // 77 // AddObject(state); 78 79 SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); 80 } 81 82 // destructor 83 ObjectView::~ObjectView() 84 { 85 } 86 87 // AttachedToWindow 88 void 89 ObjectView::AttachedToWindow() 90 { 91 SetViewColor(B_TRANSPARENT_COLOR); 92 } 93 94 // DetachedFromWindow 95 void 96 ObjectView::DetachedFromWindow() 97 { 98 } 99 100 // Draw 101 void 102 ObjectView::Draw(BRect updateRect) 103 { 104 FillRect(updateRect, B_SOLID_LOW); 105 106 // SetHighColor(0, 0, 0); 107 // for (float i = 10; i < 200; i += 4.25) { 108 // StrokeLine(BPoint(i, 10), BPoint(i, 200)); 109 // StrokeLine(BPoint(10, i), BPoint(200, i)); 110 // } 111 // 112 // SetHighColor(0, 0, 50); 113 // for (float i = 10; i < 200; i += 8.25) { 114 // FillRect(BRect(i, 10 + 230, i + 2, 200 + 230)); 115 // FillRect(BRect(10, i + 230, 200, i + 2 + 230)); 116 // } 117 // 118 // rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR); 119 // rgb_color shadow = tint_color(noTint, B_DARKEN_2_TINT); 120 // rgb_color light = tint_color(noTint, B_LIGHTEN_MAX_TINT); 121 122 BRect r(Bounds()); 123 124 /* BeginLineArray(4); 125 AddLine(BPoint(r.left, r.top), 126 BPoint(r.right, r.top), shadow); 127 AddLine(BPoint(r.right, r.top + 1), 128 BPoint(r.right, r.bottom), light); 129 AddLine(BPoint(r.right - 1, r.bottom), 130 BPoint(r.left, r.bottom), light); 131 AddLine(BPoint(r.left, r.bottom - 1), 132 BPoint(r.left, r.top + 1), shadow); 133 EndLineArray();*/ 134 135 //Sync(); 136 // SetHighColor(200, 200, 200, 255); 137 //// BRect rect(0.0, 0.0, 10.0, 11.0); 138 // int32 counter = 0; 139 // BRegion region; 140 //// while (rect.top < r.bottom) { 141 //// while (rect.left < r.right) { 142 //// region.Include(rect); 143 //// rect.OffsetBy(rect.Width() + 2, 0.0); 144 //// 145 //// counter++; 146 //// } 147 //// rect.OffsetTo(0.0, rect.top + rect.Height() + 2); 148 //// } 149 // BRect rect(0.0, 0.0, 0.0, 10.0); 150 // for (int32 i = 0; i < 100; i++) { 151 // region.Include(rect); 152 // rect.OffsetBy(rect.Width() + 1, 1.0); 153 // counter++; 154 // } 155 //bigtime_t now = system_time(); 156 // FillRegion(®ion); 157 //Sync(); 158 //printf("rendering %ld small rects (region: %ld): %lld\n", counter, 159 //region.CountRects(), system_time() - now); 160 161 SetDrawingMode(B_OP_OVER); 162 SetHighColor(255, 0, 0, 128); 163 164 const char* message = B_TRANSLATE("Click and drag to draw an object"); 165 float width = StringWidth(message); 166 167 BPoint p((r.Width() - width) / 2.0, r.Height() / 2.0); 168 169 //Sync(); 170 //snooze(1000); 171 // 172 //bigtime_t now = system_time(); 173 // 174 //#ifdef __HAIKU__ 175 // BFont font; 176 // GetFont(&font); 177 // font.SetFalseBoldWidth(1.0); 178 // SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 179 // SetHighColor(0, 0, 0); 180 // DrawString(message, p); 181 // 182 // font.SetFalseBoldWidth(0.0); 183 // SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 184 // SetHighColor(255, 0, 0); 185 //#endif // __HAIKU__ 186 187 DrawString(message, p); 188 189 //Sync(); 190 //printf("Drawing Text: %lld\n", system_time() - now); 191 192 // r.OffsetTo(B_ORIGIN); 193 // 194 //now = system_time(); 195 // int32 rectCount = 20; 196 // BeginLineArray(4 * rectCount); 197 // for (int32 i = 0; i < rectCount; i++) { 198 // r.InsetBy(5, 5); 199 // 200 // AddLine(BPoint(r.left, r.top), 201 // BPoint(r.right, r.top), shadow); 202 // AddLine(BPoint(r.right, r.top + 1), 203 // BPoint(r.right, r.bottom), light); 204 // AddLine(BPoint(r.right - 1, r.bottom), 205 // BPoint(r.left, r.bottom), light); 206 // AddLine(BPoint(r.left, r.bottom - 1), 207 // BPoint(r.left, r.top + 1), shadow); 208 // } 209 // EndLineArray(); 210 //Sync(); 211 //printf("Drawing Lines: %lld\n", system_time() - now); 212 213 //Flush(); 214 //Sync(); 215 //bigtime_t start = system_time(); 216 //SetDrawingMode(B_OP_ALPHA); 217 //SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); 218 //SetHighColor(0, 0, 255, 128); 219 //FillRect(BRect(0, 0, 250, 300)); 220 //Sync(); 221 //printf("Alpha Fill: %lld\n", system_time() - start); 222 223 for (int32 i = 0; State* state = (State*)fStateList.ItemAt(i); i++) 224 state->Draw(this); 225 //Sync(); 226 //printf("State: %lld\n", system_time() - start); 227 } 228 229 // MouseDown 230 void 231 ObjectView::MouseDown(BPoint where) 232 { 233 uint32 buttons; 234 int32 clicks; 235 // 236 // snooze(1000000); 237 // BMessageQueue* queue = Window()->MessageQueue(); 238 // BMessage* msg; 239 // int32 count = 0; 240 // for (int32 i = 0; (msg = queue->FindMessage(i)); i++) { 241 // if (msg->what == B_MOUSE_MOVED) 242 // count++; 243 // } 244 // printf("B_MOUSE_MOVED count before GetMouse(): %ld\n", count); 245 // 246 // GetMouse(&where, &buttons); 247 // 248 // count = 0; 249 // for (int32 i = 0; (msg = queue->FindMessage(i)); i++) { 250 // if (msg->what == B_MOUSE_MOVED) 251 // count++; 252 // } 253 // printf("B_MOUSE_MOVED count after 1st GetMouse(): %ld\n", count); 254 // 255 // GetMouse(&where, &buttons); 256 // 257 // count = 0; 258 // for (int32 i = 0; (msg = queue->FindMessage(i)); i++) { 259 // if (msg->what == B_MOUSE_MOVED) 260 // count++; 261 // } 262 // printf("B_MOUSE_MOVED count after 2nd GetMouse(): %ld\n", count); 263 // return; 264 265 //be_app->HideCursor(); 266 267 Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons); 268 Window()->CurrentMessage()->FindInt32("clicks", &clicks); 269 //printf("ObjectView::MouseDown() - clicks: %ld\n", clicks); 270 fInitiatingDrag = buttons & B_SECONDARY_MOUSE_BUTTON; 271 fScrolling = !fInitiatingDrag && (buttons & B_TERTIARY_MOUSE_BUTTON); 272 273 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); 274 275 if (fScrolling || fInitiatingDrag) { 276 fLastMousePos = where; 277 } else { 278 if (!fState) 279 AddObject(State::StateFor(fObjectType, fColor, fDrawingMode, 280 fFill, fPenSize)); 281 282 if (fState) { 283 fState->MouseDown(where); 284 } 285 } 286 } 287 288 // MouseUp 289 void 290 ObjectView::MouseUp(BPoint where) 291 { 292 //be_app->ShowCursor(); 293 294 if (fScrolling) { 295 fScrolling = false; 296 } else { 297 if (fState) { 298 fState->MouseUp(); 299 } 300 } 301 } 302 303 // MouseMoved 304 void 305 ObjectView::MouseMoved(BPoint where, uint32 transit, 306 const BMessage* dragMessage) 307 { 308 // BRect dirty(where, where); 309 // dirty.InsetBy(-10, -10); 310 // Invalidate(dirty); 311 312 if (dragMessage) { 313 //printf("ObjectView::MouseMoved(BPoint(%.1f, %.1f)) - DRAG MESSAGE\n", where.x, where.y); 314 //Window()->CurrentMessage()->PrintToStream(); 315 } else { 316 //printf("ObjectView::MouseMoved(BPoint(%.1f, %.1f))\n", where.x, where.y); 317 } 318 319 if (fScrolling) { 320 BCursor cursor(kGrabCursor); 321 SetViewCursor(&cursor); 322 323 BPoint offset = fLastMousePos - where; 324 ScrollBy(offset.x, offset.y); 325 fLastMousePos = where + offset; 326 } else if (fInitiatingDrag) { 327 BPoint offset = fLastMousePos - where; 328 if (sqrtf(offset.x * offset.x + offset.y * offset.y) > 5.0) { 329 BMessage newDragMessage('drag'); 330 BBitmap* dragBitmap = new BBitmap(BRect(0, 0, 40, 40), B_RGBA32, 331 true); 332 if (dragBitmap->Lock()) { 333 BView* helper = new BView(dragBitmap->Bounds(), 334 "offscreen view", B_FOLLOW_ALL, B_WILL_DRAW); 335 dragBitmap->AddChild(helper); 336 helper->SetDrawingMode(B_OP_ALPHA); 337 helper->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); 338 339 BRect r(helper->Bounds()); 340 helper->SetHighColor(0, 0, 0, 128); 341 helper->StrokeRect(r); 342 343 helper->SetHighColor(200, 200, 200, 100); 344 r.InsetBy(1, 1); 345 helper->FillRect(r); 346 347 helper->SetHighColor(0, 0, 0, 255); 348 const char* text = B_TRANSLATE("Test"); 349 float pos = (r.Width() - helper->StringWidth(text)) / 2; 350 helper->DrawString(text, BPoint(pos, 25)); 351 helper->Sync(); 352 } 353 354 DragMessage(&newDragMessage, dragBitmap, B_OP_ALPHA, B_ORIGIN, 355 this); 356 fInitiatingDrag = false; 357 } 358 } else { 359 BCursor cursor(kMoveCursor); 360 SetViewCursor(&cursor); 361 362 if (fState && fState->IsTracking()) { 363 BRect before = fState->Bounds(); 364 365 fState->MouseMoved(where); 366 367 BRect after = fState->Bounds(); 368 BRect invalid(before | after); 369 Invalidate(invalid); 370 } 371 } 372 // SetViewCursor(); 373 } 374 375 // MessageReceived 376 void 377 ObjectView::MessageReceived(BMessage* message) 378 { 379 switch (message->what) { 380 case 'drag': 381 printf("ObjectView::MessageReceived() - received drag message\n"); 382 break; 383 default: 384 BView::MessageReceived(message); 385 break; 386 } 387 } 388 389 // SetState 390 void 391 ObjectView::SetState(State* state) 392 { 393 if (fState != state) { 394 if (fState) { 395 fState->SetEditing(false); 396 Invalidate(fState->Bounds()); 397 } 398 399 fState = state; 400 401 if (fState) { 402 fState->SetEditing(true); 403 Invalidate(fState->Bounds()); 404 } 405 } 406 } 407 408 // SetObjectType 409 void 410 ObjectView::SetObjectType(int32 type) 411 { 412 if (type != fObjectType) { 413 fObjectType = type; 414 SetState(NULL); 415 } 416 } 417 418 // AddObject 419 void 420 ObjectView::AddObject(State* state) 421 { 422 if (state) { 423 fStateList.AddItem((void*)state); 424 425 BMessage message(MSG_OBJECT_ADDED); 426 message.AddPointer("object", state); 427 Window()->PostMessage(&message); 428 429 SetState(state); 430 } 431 } 432 433 // RemoveObject 434 void 435 ObjectView::RemoveObject(State* state) 436 { 437 if (state && fStateList.RemoveItem((void*)state)) { 438 if (fState == state) 439 SetState(NULL); 440 else 441 Invalidate(state->Bounds()); 442 443 Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED); 444 445 delete state; 446 } 447 } 448 449 // CountObjects 450 int32 451 ObjectView::CountObjects() const 452 { 453 return fStateList.CountItems(); 454 } 455 456 // MakeEmpty 457 void 458 ObjectView::MakeEmpty() 459 { 460 for (int32 i = 0; State* state = (State*)fStateList.ItemAt(i); i++) 461 delete state; 462 fStateList.MakeEmpty(); 463 464 Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED); 465 466 fState = NULL; 467 468 Invalidate(); 469 } 470 471 // SetStateColor 472 void 473 ObjectView::SetStateColor(rgb_color color) 474 { 475 if (color.red != fColor.red || 476 color.green != fColor.green || 477 color.blue != fColor.blue || 478 color.alpha != fColor.alpha) { 479 480 fColor = color; 481 482 if (fState) { 483 fState->SetColor(fColor); 484 Invalidate(fState->Bounds()); 485 } 486 } 487 } 488 489 // SetStateDrawingMode 490 void 491 ObjectView::SetStateDrawingMode(drawing_mode mode) 492 { 493 if (fDrawingMode != mode) { 494 fDrawingMode = mode; 495 496 if (fState) { 497 fState->SetDrawingMode(fDrawingMode); 498 Invalidate(fState->Bounds()); 499 } 500 } 501 } 502 503 // SetStateFill 504 void 505 ObjectView::SetStateFill(bool fill) 506 { 507 if (fFill != fill) { 508 fFill = fill; 509 510 if (fState) { 511 BRect before = fState->Bounds(); 512 513 fState->SetFill(fFill); 514 515 BRect after = fState->Bounds(); 516 BRect invalid(before | after); 517 Invalidate(invalid); 518 } 519 } 520 } 521 522 // SetStatePenSize 523 void 524 ObjectView::SetStatePenSize(float penSize) 525 { 526 if (fPenSize != penSize) { 527 fPenSize = penSize; 528 529 if (fState) { 530 BRect before = fState->Bounds(); 531 532 fState->SetPenSize(fPenSize); 533 534 BRect after = fState->Bounds(); 535 BRect invalid(before | after); 536 Invalidate(invalid); 537 } 538 } 539 } 540