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