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 23const 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 34const 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 47ObjectView::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 83ObjectView::~ObjectView() 84{ 85} 86 87// AttachedToWindow 88void 89ObjectView::AttachedToWindow() 90{ 91 SetViewColor(B_TRANSPARENT_COLOR); 92} 93 94// DetachedFromWindow 95void 96ObjectView::DetachedFromWindow() 97{ 98} 99 100// Draw 101void 102ObjectView::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 230void 231ObjectView::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 289void 290ObjectView::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 304void 305ObjectView::MouseMoved(BPoint where, uint32 transit, 306 const BMessage* dragMessage) 307{ 308// BRect dirty(where, where); 309// dirty.InsetBy(-10, -10); 310// Invalidate(dirty); 311 312if (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 376void 377ObjectView::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 390void 391ObjectView::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 409void 410ObjectView::SetObjectType(int32 type) 411{ 412 if (type != fObjectType) { 413 fObjectType = type; 414 SetState(NULL); 415 } 416} 417 418// AddObject 419void 420ObjectView::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 434void 435ObjectView::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 450int32 451ObjectView::CountObjects() const 452{ 453 return fStateList.CountItems(); 454} 455 456// MakeEmpty 457void 458ObjectView::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 472void 473ObjectView::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 490void 491ObjectView::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 504void 505ObjectView::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 523void 524ObjectView::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