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 rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR); 103 rgb_color shadow = tint_color(noTint, B_DARKEN_2_TINT); 104 rgb_color light = tint_color(noTint, B_LIGHTEN_MAX_TINT); 105 106 BRect r(Bounds()); 107 108 /* BeginLineArray(4); 109 AddLine(BPoint(r.left, r.top), 110 BPoint(r.right, r.top), shadow); 111 AddLine(BPoint(r.right, r.top + 1), 112 BPoint(r.right, r.bottom), light); 113 AddLine(BPoint(r.right - 1, r.bottom), 114 BPoint(r.left, r.bottom), light); 115 AddLine(BPoint(r.left, r.bottom - 1), 116 BPoint(r.left, r.top + 1), shadow); 117 EndLineArray();*/ 118 119 //Sync(); 120 // SetHighColor(200, 200, 200, 255); 121 //// BRect rect(0.0, 0.0, 10.0, 11.0); 122 // int32 counter = 0; 123 // BRegion region; 124 //// while (rect.top < r.bottom) { 125 //// while (rect.left < r.right) { 126 //// region.Include(rect); 127 //// rect.OffsetBy(rect.Width() + 2, 0.0); 128 //// 129 //// counter++; 130 //// } 131 //// rect.OffsetTo(0.0, rect.top + rect.Height() + 2); 132 //// } 133 // BRect rect(0.0, 0.0, 0.0, 10.0); 134 // for (int32 i = 0; i < 100; i++) { 135 // region.Include(rect); 136 // rect.OffsetBy(rect.Width() + 1, 1.0); 137 // counter++; 138 // } 139 //bigtime_t now = system_time(); 140 // FillRegion(®ion); 141 //Sync(); 142 //printf("rendering %ld small rects (region: %ld): %lld\n", counter, 143 //region.CountRects(), system_time() - now); 144 145 SetDrawingMode(B_OP_COPY); 146 SetHighColor(255, 0, 0, 128); 147 148 const char* message = "Click and drag to draw an object"; 149 float width = StringWidth(message); 150 151 BPoint p((r.Width() - width) / 2.0, r.Height() / 2.0); 152 153 //Sync(); 154 //snooze(1000); 155 // 156 //bigtime_t now = system_time(); 157 DrawString(message, p); 158 159 //Sync(); 160 //printf("Drawing Text: %lld\n", system_time() - now); 161 162 // r.OffsetTo(B_ORIGIN); 163 // 164 //now = system_time(); 165 // int32 rectCount = 20; 166 // BeginLineArray(4 * rectCount); 167 // for (int32 i = 0; i < rectCount; i++) { 168 // r.InsetBy(5, 5); 169 // 170 // AddLine(BPoint(r.left, r.top), 171 // BPoint(r.right, r.top), shadow); 172 // AddLine(BPoint(r.right, r.top + 1), 173 // BPoint(r.right, r.bottom), light); 174 // AddLine(BPoint(r.right - 1, r.bottom), 175 // BPoint(r.left, r.bottom), light); 176 // AddLine(BPoint(r.left, r.bottom - 1), 177 // BPoint(r.left, r.top + 1), shadow); 178 // } 179 // EndLineArray(); 180 //Sync(); 181 //printf("Drawing Lines: %lld\n", system_time() - now); 182 183 //Flush(); 184 //Sync(); 185 //bigtime_t start = system_time(); 186 //SetDrawingMode(B_OP_ALPHA); 187 //SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); 188 //SetHighColor(0, 0, 255, 128); 189 //FillRect(BRect(0, 0, 250, 300)); 190 //Sync(); 191 //printf("Alpha Fill: %lld\n", system_time() - start); 192 193 for (int32 i = 0; State* state = (State*)fStateList.ItemAt(i); i++) 194 state->Draw(this); 195 //Sync(); 196 //printf("State: %lld\n", system_time() - start); 197 } 198 199 // MouseDown 200 void 201 ObjectView::MouseDown(BPoint where) 202 { 203 uint32 buttons; 204 int32 clicks; 205 // 206 // snooze(1000000); 207 // BMessageQueue* queue = Window()->MessageQueue(); 208 // BMessage* msg; 209 // int32 count = 0; 210 // for (int32 i = 0; (msg = queue->FindMessage(i)); i++) { 211 // if (msg->what == B_MOUSE_MOVED) 212 // count++; 213 // } 214 // printf("B_MOUSE_MOVED count before GetMouse(): %ld\n", count); 215 // 216 // GetMouse(&where, &buttons); 217 // 218 // count = 0; 219 // for (int32 i = 0; (msg = queue->FindMessage(i)); i++) { 220 // if (msg->what == B_MOUSE_MOVED) 221 // count++; 222 // } 223 // printf("B_MOUSE_MOVED count after 1st GetMouse(): %ld\n", count); 224 // 225 // GetMouse(&where, &buttons); 226 // 227 // count = 0; 228 // for (int32 i = 0; (msg = queue->FindMessage(i)); i++) { 229 // if (msg->what == B_MOUSE_MOVED) 230 // count++; 231 // } 232 // printf("B_MOUSE_MOVED count after 2nd GetMouse(): %ld\n", count); 233 // return; 234 235 //be_app->HideCursor(); 236 237 Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons); 238 Window()->CurrentMessage()->FindInt32("clicks", &clicks); 239 //printf("ObjectView::MouseDown() - clicks: %ld\n", clicks); 240 fInitiatingDrag = buttons & B_SECONDARY_MOUSE_BUTTON; 241 fScrolling = !fInitiatingDrag && (buttons & B_TERTIARY_MOUSE_BUTTON); 242 243 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); 244 245 if (fScrolling || fInitiatingDrag) { 246 fLastMousePos = where; 247 } else { 248 if (!fState) 249 AddObject(State::StateFor(fObjectType, fColor, fDrawingMode, 250 fFill, fPenSize)); 251 252 if (fState) { 253 fState->MouseDown(where); 254 } 255 } 256 } 257 258 // MouseUp 259 void 260 ObjectView::MouseUp(BPoint where) 261 { 262 //be_app->ShowCursor(); 263 264 if (fScrolling) { 265 fScrolling = false; 266 } else { 267 if (fState) { 268 fState->MouseUp(); 269 } 270 } 271 } 272 273 // MouseMoved 274 void 275 ObjectView::MouseMoved(BPoint where, uint32 transit, 276 const BMessage* dragMessage) 277 { 278 if (dragMessage) { 279 //printf("ObjectView::MouseMoved(BPoint(%.1f, %.1f)) - DRAG MESSAGE\n", where.x, where.y); 280 //Window()->CurrentMessage()->PrintToStream(); 281 } else { 282 //printf("ObjectView::MouseMoved(BPoint(%.1f, %.1f))\n", where.x, where.y); 283 } 284 285 if (fScrolling) { 286 BCursor cursor(kGrabCursor); 287 SetViewCursor(&cursor); 288 289 BPoint offset = fLastMousePos - where; 290 ScrollBy(offset.x, offset.y); 291 fLastMousePos = where + offset; 292 } else if (fInitiatingDrag) { 293 BPoint offset = fLastMousePos - where; 294 if (sqrtf(offset.x * offset.x + offset.y * offset.y) > 5.0) { 295 BMessage dragMessage('drag'); 296 BBitmap* dragBitmap = new BBitmap(BRect(0, 0, 40, 40), B_RGBA32, true); 297 if (dragBitmap->Lock()) { 298 BView* helper = new BView(dragBitmap->Bounds(), "offscreen view", 299 B_FOLLOW_ALL, B_WILL_DRAW); 300 dragBitmap->AddChild(helper); 301 helper->SetDrawingMode(B_OP_ALPHA); 302 helper->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); 303 304 BRect r(helper->Bounds()); 305 helper->SetHighColor(0, 0, 0, 128); 306 helper->StrokeRect(r); 307 308 helper->SetHighColor(200, 200, 200, 100); 309 r.InsetBy(1, 1); 310 helper->FillRect(r); 311 312 helper->SetHighColor(0, 0, 0, 255); 313 const char* text = "Test"; 314 float pos = (r.Width() - helper->StringWidth(text)) / 2; 315 helper->DrawString(text, BPoint(pos, 25)); 316 helper->Sync(); 317 } 318 319 DragMessage(&dragMessage, dragBitmap, B_OP_ALPHA, B_ORIGIN, this); 320 fInitiatingDrag = false; 321 } 322 } else { 323 BCursor cursor(kMoveCursor); 324 SetViewCursor(&cursor); 325 326 if (fState && fState->IsTracking()) { 327 BRect before = fState->Bounds(); 328 329 fState->MouseMoved(where); 330 331 BRect after = fState->Bounds(); 332 BRect invalid(before | after); 333 Invalidate(invalid); 334 } 335 } 336 // SetViewCursor(); 337 } 338 339 // MessageReceived 340 void 341 ObjectView::MessageReceived(BMessage* message) 342 { 343 switch (message->what) { 344 case 'drag': 345 printf("ObjectView::MessageReceived() - received drag message\n"); 346 break; 347 default: 348 BView::MessageReceived(message); 349 break; 350 } 351 } 352 353 // SetState 354 void 355 ObjectView::SetState(State* state) 356 { 357 if (fState != state) { 358 if (fState) { 359 fState->SetEditing(false); 360 Invalidate(fState->Bounds()); 361 } 362 363 fState = state; 364 365 if (fState) { 366 fState->SetEditing(true); 367 Invalidate(fState->Bounds()); 368 } 369 } 370 } 371 372 // SetObjectType 373 void 374 ObjectView::SetObjectType(int32 type) 375 { 376 if (type != fObjectType) { 377 fObjectType = type; 378 SetState(NULL); 379 } 380 } 381 382 // AddObject 383 void 384 ObjectView::AddObject(State* state) 385 { 386 if (state) { 387 fStateList.AddItem((void*)state); 388 389 BMessage message(MSG_OBJECT_ADDED); 390 message.AddPointer("object", state); 391 Window()->PostMessage(&message); 392 393 SetState(state); 394 } 395 } 396 397 // RemoveObject 398 void 399 ObjectView::RemoveObject(State* state) 400 { 401 if (state && fStateList.RemoveItem((void*)state)) { 402 if (fState == state) 403 SetState(NULL); 404 else 405 Invalidate(state->Bounds()); 406 407 Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED); 408 409 delete state; 410 } 411 } 412 413 // CountObjects 414 int32 415 ObjectView::CountObjects() const 416 { 417 return fStateList.CountItems(); 418 } 419 420 // MakeEmpty 421 void 422 ObjectView::MakeEmpty() 423 { 424 for (int32 i = 0; State* state = (State*)fStateList.ItemAt(i); i++) 425 delete state; 426 fStateList.MakeEmpty(); 427 428 Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED); 429 430 fState = NULL; 431 432 Invalidate(); 433 } 434 435 // SetStateColor 436 void 437 ObjectView::SetStateColor(rgb_color color) 438 { 439 if (color.red != fColor.red || 440 color.green != fColor.green || 441 color.blue != fColor.blue || 442 color.alpha != fColor.alpha) { 443 444 fColor = color; 445 446 if (fState) { 447 fState->SetColor(fColor); 448 Invalidate(fState->Bounds()); 449 } 450 } 451 } 452 453 // SetStateDrawingMode 454 void 455 ObjectView::SetStateDrawingMode(drawing_mode mode) 456 { 457 if (fDrawingMode != mode) { 458 fDrawingMode = mode; 459 460 if (fState) { 461 fState->SetDrawingMode(fDrawingMode); 462 Invalidate(fState->Bounds()); 463 } 464 } 465 } 466 467 // SetStateFill 468 void 469 ObjectView::SetStateFill(bool fill) 470 { 471 if (fFill != fill) { 472 fFill = fill; 473 474 if (fState) { 475 BRect before = fState->Bounds(); 476 477 fState->SetFill(fFill); 478 479 BRect after = fState->Bounds(); 480 BRect invalid(before | after); 481 Invalidate(invalid); 482 } 483 } 484 } 485 486 // SetStatePenSize 487 void 488 ObjectView::SetStatePenSize(float penSize) 489 { 490 if (fPenSize != penSize) { 491 fPenSize = penSize; 492 493 if (fState) { 494 BRect before = fState->Bounds(); 495 496 fState->SetPenSize(fPenSize); 497 498 BRect after = fState->Bounds(); 499 BRect invalid(before | after); 500 Invalidate(invalid); 501 } 502 } 503 } 504