1 /* 2 * Copyright 2001-2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Adrian Oanca <adioanca@cotty.iren.ro> 7 * Axel Dörfler, axeld@pinc-software.de 8 * Stephan Aßmus <superstippi@gmx.de> 9 */ 10 11 12 #include <AppMisc.h> 13 #include <AppServerLink.h> 14 #include <MessagePrivate.h> 15 #include <MessageUtils.h> 16 #include <PortLink.h> 17 #include <ServerProtocol.h> 18 #include <TokenSpace.h> 19 #include <ViewPrivate.h> 20 21 #include <Application.h> 22 #include <Bitmap.h> 23 #include <Button.h> 24 #include <Cursor.h> 25 #include <File.h> 26 #include <InterfaceDefs.h> 27 #include <MenuBar.h> 28 #include <Message.h> 29 #include <MessageQueue.h> 30 #include <Picture.h> 31 #include <Point.h> 32 #include <Polygon.h> 33 #include <PropertyInfo.h> 34 #include <Region.h> 35 #include <ScrollBar.h> 36 #include <Shape.h> 37 #include <Shelf.h> 38 #include <String.h> 39 #include <View.h> 40 #include <Window.h> 41 42 #include <math.h> 43 #include <new> 44 #include <stdio.h> 45 46 47 using std::nothrow; 48 49 //#define DEBUG_BVIEW 50 #ifdef DEBUG_BVIEW 51 # include <stdio.h> 52 # define STRACE(x) printf x 53 # define BVTRACE PrintToStream() 54 #else 55 # define STRACE(x) ; 56 # define BVTRACE ; 57 #endif 58 59 #define MAX_ATTACHMENT_SIZE 49152 60 61 62 static property_info sViewPropInfo[] = { 63 { "Frame", { B_GET_PROPERTY, 0 }, 64 { B_DIRECT_SPECIFIER, 0 }, "Returns the view's frame rectangle.",0 }, 65 66 { "Frame", { B_SET_PROPERTY, 0 }, 67 { B_DIRECT_SPECIFIER, 0 }, "Sets the view's frame rectangle.",0 }, 68 69 { "Hidden", { B_GET_PROPERTY, 0 }, 70 { B_DIRECT_SPECIFIER, 0 }, "Returns true if the view is hidden; false otherwise.",0 }, 71 72 { "Hidden", { B_SET_PROPERTY, 0 }, 73 { B_DIRECT_SPECIFIER, 0 }, "Hides or shows the view.",0 }, 74 75 { "Shelf", { 0 }, 76 { B_DIRECT_SPECIFIER, 0 }, "Directs the scripting message to the shelf.",0 }, 77 78 { "View", { B_COUNT_PROPERTIES, 0 }, 79 { B_DIRECT_SPECIFIER, 0 }, "Returns the number of of child views.",0 }, 80 81 { "View", { 0 }, 82 { B_INDEX_SPECIFIER, 0 }, "Directs the scripting message to the specified view.",0 }, 83 84 { "View", { 0 }, 85 { B_REVERSE_INDEX_SPECIFIER, 0 }, "Directs the scripting message to the specified view.",0 }, 86 87 { "View", { 0 }, 88 { B_NAME_SPECIFIER, 0 }, "Directs the scripting message to the specified view.",0 }, 89 90 { 0, { 0 }, { 0 }, 0, 0 } 91 }; 92 93 94 // #pragma mark - 95 96 97 namespace BPrivate { 98 99 ViewState::ViewState() 100 { 101 pen_location.Set(0, 0); 102 pen_size = 1.0; 103 104 // NOTE: the clipping_region is empty 105 // on construction but it is not used yet, 106 // we avoid having to keep track of it via 107 // this flag 108 clipping_region_used = false; 109 110 high_color = (rgb_color){ 0, 0, 0, 255 }; 111 low_color = (rgb_color){ 255, 255, 255, 255 }; 112 view_color = low_color; 113 114 pattern = B_SOLID_HIGH; 115 drawing_mode = B_OP_COPY; 116 117 origin.Set(0, 0); 118 119 line_join = B_MITER_JOIN; 120 line_cap = B_BUTT_CAP; 121 miter_limit = B_DEFAULT_MITER_LIMIT; 122 123 alpha_source_mode = B_PIXEL_ALPHA; 124 alpha_function_mode = B_ALPHA_OVERLAY; 125 126 scale = 1.0; 127 128 font = *be_plain_font; 129 font_flags = font.Flags(); 130 font_aliasing = false; 131 132 /* 133 INFO: We include(invalidate) only B_VIEW_CLIP_REGION_BIT flag 134 because we should get the clipping region from app_server. 135 The other flags do not need to be included because the data they 136 represent is already in sync with app_server - app_server uses the 137 same init(default) values. 138 */ 139 valid_flags = ~B_VIEW_CLIP_REGION_BIT; 140 141 archiving_flags = B_VIEW_FRAME_BIT | B_VIEW_RESIZE_BIT; 142 } 143 144 145 void 146 ViewState::UpdateServerFontState(BPrivate::PortLink &link) 147 { 148 link.StartMessage(AS_LAYER_SET_FONT_STATE); 149 link.Attach<uint16>(font_flags); 150 151 // always present. 152 if (font_flags & B_FONT_FAMILY_AND_STYLE) { 153 uint32 fontID; 154 fontID = font.FamilyAndStyle(); 155 156 link.Attach<uint32>(fontID); 157 } 158 159 if (font_flags & B_FONT_SIZE) 160 link.Attach<float>(font.Size()); 161 162 if (font_flags & B_FONT_SHEAR) 163 link.Attach<float>(font.Shear()); 164 165 if (font_flags & B_FONT_ROTATION) 166 link.Attach<float>(font.Rotation()); 167 168 if (font_flags & B_FONT_SPACING) 169 link.Attach<uint8>(font.Spacing()); 170 171 if (font_flags & B_FONT_ENCODING) 172 link.Attach<uint8>(font.Encoding()); 173 174 if (font_flags & B_FONT_FACE) 175 link.Attach<uint16>(font.Face()); 176 177 if (font_flags & B_FONT_FLAGS) 178 link.Attach<uint32>(font.Flags()); 179 } 180 181 182 void 183 ViewState::UpdateServerState(BPrivate::PortLink &link) 184 { 185 UpdateServerFontState(link); 186 187 link.StartMessage(AS_LAYER_SET_STATE); 188 link.Attach<BPoint>(pen_location); 189 link.Attach<float>(pen_size); 190 link.Attach<rgb_color>(high_color); 191 link.Attach<rgb_color>(low_color); 192 link.Attach< ::pattern>(pattern); 193 link.Attach<int8>((int8)drawing_mode); 194 link.Attach<BPoint>(origin); 195 link.Attach<int8>((int8)line_join); 196 link.Attach<int8>((int8)line_cap); 197 link.Attach<float>(miter_limit); 198 link.Attach<int8>((int8)alpha_source_mode); 199 link.Attach<int8>((int8)alpha_function_mode); 200 link.Attach<float>(scale); 201 link.Attach<bool>(font_aliasing); 202 203 // we send the 'local' clipping region... if we have one... 204 if (clipping_region_used) { 205 int32 count = clipping_region.CountRects(); 206 link.Attach<int32>(count); 207 for (int32 i = 0; i < count; i++) 208 link.Attach<BRect>(clipping_region.RectAt(i)); 209 } else { 210 // no clipping region 211 link.Attach<int32>(-1); 212 } 213 214 // Although we might have a 'local' clipping region, when we call 215 // BView::GetClippingRegion() we ask for the 'global' one and it 216 // is kept on server, so we must invalidate B_VIEW_CLIP_REGION_BIT flag 217 218 valid_flags = ~B_VIEW_CLIP_REGION_BIT; 219 } 220 221 222 void 223 ViewState::UpdateFrom(BPrivate::PortLink &link) 224 { 225 link.StartMessage(AS_LAYER_GET_STATE); 226 227 int32 code; 228 if (link.FlushWithReply(code) != B_OK 229 || code != B_OK) 230 return; 231 232 uint32 fontID; 233 float size; 234 float shear; 235 float rotation; 236 uint8 spacing; 237 uint8 encoding; 238 uint16 face; 239 uint32 flags; 240 241 // read and set the font state 242 link.Read<int32>((int32 *)&fontID); 243 link.Read<float>(&size); 244 link.Read<float>(&shear); 245 link.Read<float>(&rotation); 246 link.Read<int8>((int8 *)&spacing); 247 link.Read<int8>((int8 *)&encoding); 248 link.Read<int16>((int16 *)&face); 249 link.Read<int32>((int32 *)&flags); 250 251 font_flags = B_FONT_ALL; 252 font.SetFamilyAndStyle(fontID); 253 font.SetSize(size); 254 font.SetShear(shear); 255 font.SetRotation(rotation); 256 font.SetSpacing(spacing); 257 font.SetEncoding(encoding); 258 font.SetFace(face); 259 font.SetFlags(flags); 260 261 // read and set view's state 262 link.Read<BPoint>(&pen_location); 263 link.Read<float>(&pen_size); 264 link.Read<rgb_color>(&high_color); 265 link.Read<rgb_color>(&low_color); 266 link.Read< ::pattern>(&pattern); 267 link.Read<BPoint>(&origin); 268 269 int8 drawingMode; 270 link.Read<int8>((int8 *)&drawingMode); 271 drawing_mode = (::drawing_mode)drawingMode; 272 273 link.Read<int8>((int8 *)&line_cap); 274 link.Read<int8>((int8 *)&line_join); 275 link.Read<float>(&miter_limit); 276 link.Read<int8>((int8 *)&alpha_source_mode); 277 link.Read<int8>((int8 *)&alpha_function_mode); 278 link.Read<float>(&scale); 279 link.Read<bool>(&font_aliasing); 280 281 // read the user clipping 282 // (that's NOT the current View visible clipping but the additional 283 // user specified clipping!) 284 int32 clippingRectCount; 285 link.Read<int32>(&clippingRectCount); 286 if (clippingRectCount >= 0) { 287 clipping_region.MakeEmpty(); 288 for (int32 i = 0; i < clippingRectCount; i++) { 289 BRect rect; 290 link.Read<BRect>(&rect); 291 clipping_region.Include(rect); 292 } 293 } else { 294 // no user clipping used 295 clipping_region_used = false; 296 } 297 298 valid_flags = ~B_VIEW_CLIP_REGION_BIT; 299 } 300 301 } // namespace BPrivate 302 303 304 // #pragma mark - 305 306 307 BView::BView(BRect frame, const char *name, uint32 resizingMode, uint32 flags) 308 : BHandler(name) 309 { 310 _InitData(frame, name, resizingMode, flags); 311 } 312 313 314 BView::BView(BMessage *archive) 315 : BHandler(archive) 316 { 317 BRect frame; 318 archive->FindRect("_frame", &frame); 319 320 uint32 resizingMode; 321 if (archive->FindInt32("_resize_mode", (int32*)&resizingMode) != B_OK) 322 resizingMode = 0; 323 324 uint32 flags; 325 if (archive->FindInt32("_flags", (int32*)&flags) != B_OK) 326 flags = 0; 327 328 _InitData(frame, Name(), resizingMode, flags); 329 330 font_family family; 331 font_style style; 332 if (archive->FindString("_fname", 0, (const char **)&family) == B_OK 333 && archive->FindString("_fname", 1, (const char **)&style) == B_OK) { 334 BFont font; 335 font.SetFamilyAndStyle(family, style); 336 337 float size; 338 if (archive->FindFloat("_fflt", 0, &size) == B_OK) 339 font.SetSize(size); 340 341 float shear; 342 if (archive->FindFloat("_fflt", 1, &shear) == B_OK) 343 font.SetShear(shear); 344 345 float rotation; 346 if (archive->FindFloat("_fflt", 2, &rotation) == B_OK) 347 font.SetRotation(rotation); 348 349 SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE 350 | B_FONT_SHEAR | B_FONT_ROTATION); 351 } 352 353 rgb_color color; 354 if (archive->FindInt32("_color", 0, (int32 *)&color) == B_OK) 355 SetHighColor(color); 356 if (archive->FindInt32("_color", 1, (int32 *)&color) == B_OK) 357 SetLowColor(color); 358 if (archive->FindInt32("_color", 2, (int32 *)&color) == B_OK) 359 SetViewColor(color); 360 361 uint32 evMask; 362 uint32 options; 363 if (archive->FindInt32("_evmask", 0, (int32 *)&evMask) == B_OK 364 && archive->FindInt32("_evmask", 1, (int32 *)&options) == B_OK) 365 SetEventMask(evMask, options); 366 367 BPoint origin; 368 if (archive->FindPoint("_origin", &origin) == B_OK) 369 SetOrigin(origin); 370 371 float penSize; 372 if (archive->FindFloat("_psize", &penSize) == B_OK) 373 SetPenSize(penSize); 374 375 BPoint penLocation; 376 if (archive->FindPoint("_ploc", &penLocation) == B_OK) 377 MovePenTo(penLocation); 378 379 int16 lineCap; 380 int16 lineJoin; 381 float lineMiter; 382 if (archive->FindInt16("_lmcapjoin", 0, &lineCap) == B_OK 383 && archive->FindInt16("_lmcapjoin", 1, &lineJoin) == B_OK 384 && archive->FindFloat("_lmmiter", &lineMiter) == B_OK) 385 SetLineMode((cap_mode)lineCap, (join_mode)lineJoin, lineMiter); 386 387 int16 alphaBlend; 388 int16 modeBlend; 389 if (archive->FindInt16("_blend", 0, &alphaBlend) == B_OK 390 && archive->FindInt16("_blend", 1, &modeBlend) == B_OK) 391 SetBlendingMode( (source_alpha)alphaBlend, (alpha_function)modeBlend); 392 393 uint32 drawingMode; 394 if (archive->FindInt32("_dmod", (int32 *)&drawingMode) == B_OK) 395 SetDrawingMode((drawing_mode)drawingMode); 396 397 BMessage msg; 398 for (int32 i = 0; archive->FindMessage("_views", i, &msg) == B_OK; i++) { 399 BArchivable *object = instantiate_object(&msg); 400 if (BView *child = dynamic_cast<BView *>(object)) 401 AddChild(child); 402 } 403 } 404 405 406 BArchivable * 407 BView::Instantiate(BMessage *data) 408 { 409 if (!validate_instantiation(data , "BView")) 410 return NULL; 411 412 return new BView(data); 413 } 414 415 416 status_t 417 BView::Archive(BMessage *data, bool deep) const 418 { 419 status_t ret = BHandler::Archive(data, deep); 420 if (ret != B_OK) 421 return ret; 422 423 if (fState->archiving_flags & B_VIEW_FRAME_BIT) 424 ret = data->AddRect("_frame", Bounds().OffsetToCopy(fParentOffset)); 425 426 if (ret == B_OK) 427 ret = data->AddInt32("_resize_mode", ResizingMode()); 428 429 if (ret == B_OK) 430 ret = data->AddInt32("_flags", Flags()); 431 432 if (ret == B_OK && fState->archiving_flags & B_VIEW_EVENT_MASK_BIT) { 433 ret = data->AddInt32("_evmask", fEventMask); 434 if (ret == B_OK) 435 ret = data->AddInt32("_evmask", fEventOptions); 436 } 437 438 if (ret == B_OK && fState->archiving_flags & B_VIEW_FONT_BIT) { 439 BFont font; 440 GetFont(&font); 441 442 font_family family; 443 font_style style; 444 font.GetFamilyAndStyle(&family, &style); 445 ret = data->AddString("_fname", family); 446 if (ret == B_OK) 447 ret = data->AddString("_fname", style); 448 if (ret == B_OK) 449 ret = data->AddFloat("_fflt", font.Size()); 450 if (ret == B_OK) 451 ret = data->AddFloat("_fflt", font.Shear()); 452 if (ret == B_OK) 453 ret = data->AddFloat("_fflt", font.Rotation()); 454 } 455 456 // colors 457 if (ret == B_OK) 458 ret = data->AddInt32("_color", (const uint32 &)HighColor()); 459 460 if (ret == B_OK) 461 ret = data->AddInt32("_color", (const uint32 &)LowColor()); 462 463 if (ret == B_OK) 464 ret = data->AddInt32("_color", (const uint32 &)ViewColor()); 465 466 // NOTE: we do not use this flag any more 467 // if ( 1 ){ 468 // ret = data->AddInt32("_dbuf", 1); 469 // } 470 471 if (ret == B_OK && fState->archiving_flags & B_VIEW_ORIGIN_BIT) 472 ret = data->AddPoint("_origin", Origin()); 473 474 if (ret == B_OK && fState->archiving_flags & B_VIEW_PEN_SIZE_BIT) 475 ret = data->AddFloat("_psize", PenSize()); 476 477 if (ret == B_OK && fState->archiving_flags & B_VIEW_PEN_LOCATION_BIT) 478 ret = data->AddPoint("_ploc", PenLocation()); 479 480 if (ret == B_OK && fState->archiving_flags & B_VIEW_LINE_MODES_BIT) { 481 ret = data->AddInt16("_lmcapjoin", (int16)LineCapMode()); 482 if (ret == B_OK) 483 ret = data->AddInt16("_lmcapjoin", (int16)LineJoinMode()); 484 if (ret == B_OK) 485 ret = data->AddFloat("_lmmiter", LineMiterLimit()); 486 } 487 488 if (ret == B_OK && fState->archiving_flags & B_VIEW_BLENDING_BIT) { 489 source_alpha alphaSourceMode; 490 alpha_function alphaFunctionMode; 491 GetBlendingMode(&alphaSourceMode, &alphaFunctionMode); 492 493 ret = data->AddInt16("_blend", (int16)alphaSourceMode); 494 if (ret == B_OK) 495 ret = data->AddInt16("_blend", (int16)alphaFunctionMode); 496 } 497 498 if (ret == B_OK && fState->archiving_flags & B_VIEW_DRAWING_MODE_BIT) 499 ret = data->AddInt32("_dmod", DrawingMode()); 500 501 if (deep) { 502 int32 i = 0; 503 BView *child; 504 505 while (ret == B_OK && (child = ChildAt(i++)) != NULL) { 506 BMessage childArchive; 507 508 ret = child->Archive(&childArchive, deep); 509 if (ret == B_OK) 510 ret = data->AddMessage("_views", &childArchive); 511 } 512 } 513 514 if (ret == B_OK) 515 ret = data->AddString("class", "BView"); 516 517 return ret; 518 } 519 520 521 BView::~BView() 522 { 523 STRACE(("BView(%s)::~BView()\n", this->Name())); 524 525 if (fOwner) 526 debugger("Trying to delete a view that belongs to a window. Call RemoveSelf first."); 527 528 RemoveSelf(); 529 530 // TODO: see about BShelf! must I delete it here? is it deleted by the window? 531 532 // we also delete all our children 533 534 BView *child = fFirstChild; 535 while (child) { 536 BView *nextChild = child->fNextSibling; 537 538 delete child; 539 child = nextChild; 540 } 541 542 if (fVerScroller) 543 fVerScroller->SetTarget((BView*)NULL); 544 if (fHorScroller) 545 fHorScroller->SetTarget((BView*)NULL); 546 547 SetName(NULL); 548 549 removeCommArray(); 550 delete fState; 551 } 552 553 554 BRect 555 BView::Bounds() const 556 { 557 // do we need to update our bounds? 558 559 // TODO: why should our frame be out of sync ever? 560 /* 561 if (!fState->IsValid(B_VIEW_FRAME_BIT) && fOwner) { 562 check_lock(); 563 564 fOwner->fLink->StartMessage(AS_LAYER_GET_COORD); 565 566 int32 code; 567 if (fOwner->fLink->FlushWithReply(code) == B_OK 568 && code == B_OK) { 569 fOwner->fLink->Read<BPoint>(const_cast<BPoint *>(&fParentOffset)); 570 fOwner->fLink->Read<BRect>(const_cast<BRect *>(&fBounds)); 571 fState->valid_flags |= B_VIEW_FRAME_BIT; 572 } 573 } 574 */ 575 return fBounds; 576 } 577 578 579 void 580 BView::ConvertToParent(BPoint *point) const 581 { 582 if (!fParent) 583 return; 584 585 check_lock_no_pick(); 586 587 // TODO: handle scale 588 589 // our local coordinate transformation 590 *point -= Origin(); 591 592 // our bounds location within the parent 593 *point += fParentOffset; 594 } 595 596 597 BPoint 598 BView::ConvertToParent(BPoint point) const 599 { 600 ConvertToParent(&point); 601 602 return point; 603 } 604 605 606 void 607 BView::ConvertFromParent(BPoint *point) const 608 { 609 if (!fParent) 610 return; 611 612 check_lock_no_pick(); 613 614 // TODO: handle scale 615 616 // our bounds location within the parent 617 *point -= fParentOffset; 618 619 // our local coordinate transformation 620 *point += Origin(); 621 } 622 623 624 BPoint 625 BView::ConvertFromParent(BPoint point) const 626 { 627 ConvertFromParent(&point); 628 629 return point; 630 } 631 632 633 void 634 BView::ConvertToParent(BRect *rect) const 635 { 636 if (!fParent) 637 return; 638 639 check_lock_no_pick(); 640 641 // TODO: handle scale 642 643 BPoint origin = Origin(); 644 645 // our local coordinate transformation 646 rect->OffsetBy(-origin.x, -origin.y); 647 648 // our bounds location within the parent 649 rect->OffsetBy(fParentOffset); 650 } 651 652 653 BRect 654 BView::ConvertToParent(BRect rect) const 655 { 656 ConvertToParent(&rect); 657 658 return rect; 659 } 660 661 662 void 663 BView::ConvertFromParent(BRect *rect) const 664 { 665 if (!fParent) 666 return; 667 668 check_lock_no_pick(); 669 670 // TODO: handle scale 671 672 // our bounds location within the parent 673 rect->OffsetBy(-fParentOffset.x, -fParentOffset.y); 674 675 // our local coordinate transformation 676 rect->OffsetBy(Origin()); 677 } 678 679 680 BRect 681 BView::ConvertFromParent(BRect rect) const 682 { 683 ConvertFromParent(&rect); 684 685 return rect; 686 } 687 688 689 void 690 BView::ConvertToScreen(BPoint *pt) const 691 { 692 if (!fParent) { 693 if (fOwner) 694 fOwner->ConvertToScreen(pt); 695 696 return; 697 } 698 699 do_owner_check_no_pick(); 700 701 ConvertToParent(pt); 702 fParent->ConvertToScreen(pt); 703 } 704 705 706 BPoint 707 BView::ConvertToScreen(BPoint pt) const 708 { 709 ConvertToScreen(&pt); 710 711 return pt; 712 } 713 714 715 void 716 BView::ConvertFromScreen(BPoint *pt) const 717 { 718 if (!fParent) { 719 if (fOwner) 720 fOwner->ConvertFromScreen(pt); 721 722 return; 723 } 724 725 do_owner_check_no_pick(); 726 727 ConvertFromParent(pt); 728 fParent->ConvertFromScreen(pt); 729 } 730 731 732 BPoint 733 BView::ConvertFromScreen(BPoint pt) const 734 { 735 ConvertFromScreen(&pt); 736 737 return pt; 738 } 739 740 741 void 742 BView::ConvertToScreen(BRect *rect) const 743 { 744 BPoint offset(0.0, 0.0); 745 ConvertToScreen(&offset); 746 rect->OffsetBy(offset); 747 } 748 749 750 BRect 751 BView::ConvertToScreen(BRect rect) const 752 { 753 ConvertToScreen(&rect); 754 755 return rect; 756 } 757 758 759 void 760 BView::ConvertFromScreen(BRect *rect) const 761 { 762 BPoint offset(0.0, 0.0); 763 ConvertFromScreen(&offset); 764 rect->OffsetBy(offset); 765 } 766 767 768 BRect 769 BView::ConvertFromScreen(BRect rect) const 770 { 771 ConvertFromScreen(&rect); 772 773 return rect; 774 } 775 776 777 uint32 778 BView::Flags() const 779 { 780 check_lock_no_pick(); 781 return fFlags & ~_RESIZE_MASK_; 782 } 783 784 785 void 786 BView::SetFlags(uint32 flags) 787 { 788 if (Flags() == flags) 789 return; 790 791 if (fOwner) { 792 if (flags & B_PULSE_NEEDED) { 793 check_lock_no_pick(); 794 if (fOwner->fPulseRunner == NULL) 795 fOwner->SetPulseRate(500000); 796 } 797 798 if (flags & (B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE 799 | B_FRAME_EVENTS | B_SUBPIXEL_PRECISE)) { 800 check_lock(); 801 802 fOwner->fLink->StartMessage(AS_LAYER_SET_FLAGS); 803 fOwner->fLink->Attach<uint32>(flags); 804 } 805 } 806 807 /* Some useful info: 808 fFlags is a unsigned long (32 bits) 809 * bits 1-16 are used for BView's flags 810 * bits 17-32 are used for BView' resize mask 811 * _RESIZE_MASK_ is used for that. Look into View.h to see how 812 it's defined 813 */ 814 fFlags = (flags & ~_RESIZE_MASK_) | (fFlags & _RESIZE_MASK_); 815 816 fState->archiving_flags |= B_VIEW_FLAGS_BIT; 817 } 818 819 820 BRect 821 BView::Frame() const 822 { 823 check_lock_no_pick(); 824 825 return Bounds().OffsetToCopy(fParentOffset.x, fParentOffset.y); 826 } 827 828 829 void 830 BView::Hide() 831 { 832 if (fOwner && fShowLevel == 0) { 833 check_lock(); 834 fOwner->fLink->StartMessage(AS_LAYER_HIDE); 835 } 836 fShowLevel++; 837 } 838 839 840 void 841 BView::Show() 842 { 843 fShowLevel--; 844 if (fOwner && fShowLevel == 0) { 845 check_lock(); 846 fOwner->fLink->StartMessage(AS_LAYER_SHOW); 847 } 848 } 849 850 851 bool 852 BView::IsFocus() const 853 { 854 if (fOwner) { 855 check_lock_no_pick(); 856 return fOwner->CurrentFocus() == this; 857 } else 858 return false; 859 } 860 861 862 bool 863 BView::IsHidden(const BView *lookingFrom) const 864 { 865 if (fShowLevel > 0) 866 return true; 867 868 // may we be egocentric? 869 if (lookingFrom == this) 870 return false; 871 872 // we have the same visibility state as our 873 // parent, if there is one 874 if (fParent) 875 return fParent->IsHidden(lookingFrom); 876 877 // if we're the top view, and we're interested 878 // in the "global" view, we're inheriting the 879 // state of the window's visibility 880 if (fOwner && lookingFrom == NULL) 881 return fOwner->IsHidden(); 882 883 return false; 884 } 885 886 887 bool 888 BView::IsHidden() const 889 { 890 return IsHidden(NULL); 891 } 892 893 894 bool 895 BView::IsPrinting() const 896 { 897 return f_is_printing; 898 } 899 900 901 BPoint 902 BView::LeftTop() const 903 { 904 return Bounds().LeftTop(); 905 } 906 907 908 void 909 BView::SetOrigin(BPoint pt) 910 { 911 SetOrigin(pt.x, pt.y); 912 } 913 914 915 void 916 BView::SetOrigin(float x, float y) 917 { 918 if (fState->IsValid(B_VIEW_ORIGIN_BIT) 919 && x == fState->origin.x && y == fState->origin.y) 920 return; 921 922 if (do_owner_check()) { 923 fOwner->fLink->StartMessage(AS_LAYER_SET_ORIGIN); 924 fOwner->fLink->Attach<float>(x); 925 fOwner->fLink->Attach<float>(y); 926 927 fState->valid_flags |= B_VIEW_ORIGIN_BIT; 928 } 929 930 // our local coord system origin has changed, so when archiving we'll add this too 931 fState->archiving_flags |= B_VIEW_ORIGIN_BIT; 932 } 933 934 935 BPoint 936 BView::Origin() const 937 { 938 if (!fState->IsValid(B_VIEW_ORIGIN_BIT)) { 939 do_owner_check(); 940 941 fOwner->fLink->StartMessage(AS_LAYER_GET_ORIGIN); 942 943 int32 code; 944 if (fOwner->fLink->FlushWithReply(code) == B_OK 945 && code == B_OK) { 946 fOwner->fLink->Read<BPoint>(&fState->origin); 947 948 fState->valid_flags |= B_VIEW_ORIGIN_BIT; 949 } 950 } 951 952 return fState->origin; 953 } 954 955 956 void 957 BView::SetResizingMode(uint32 mode) 958 { 959 if (fOwner) { 960 check_lock(); 961 962 fOwner->fLink->StartMessage(AS_LAYER_RESIZE_MODE); 963 fOwner->fLink->Attach<uint32>(mode); 964 } 965 966 // look at SetFlags() for more info on the below line 967 fFlags = (fFlags & ~_RESIZE_MASK_) | (mode & _RESIZE_MASK_); 968 } 969 970 971 uint32 972 BView::ResizingMode() const 973 { 974 return fFlags & _RESIZE_MASK_; 975 } 976 977 978 void 979 BView::SetViewCursor(const BCursor *cursor, bool sync) 980 { 981 if (cursor == NULL || fOwner == NULL) 982 return; 983 984 check_lock(); 985 986 fOwner->fLink->StartMessage(AS_LAYER_SET_CURSOR); 987 fOwner->fLink->Attach<int32>(cursor->fServerToken); 988 fOwner->fLink->Attach<bool>(sync); 989 990 if (!sync) { 991 cursor->fPendingViewCursor = true; 992 // this avoids a race condition in case the cursor is 993 // immediately deleted after this call, as the deletion 994 // is handled by the application, not the window 995 } else { 996 // make sure the server has processed the 997 // message and "acquired" the cursor in 998 // the window thread before returning from 999 // this function 1000 int32 code; 1001 fOwner->fLink->FlushWithReply(code); 1002 } 1003 } 1004 1005 1006 void 1007 BView::Flush() const 1008 { 1009 if (fOwner) 1010 fOwner->Flush(); 1011 } 1012 1013 1014 void 1015 BView::Sync() const 1016 { 1017 do_owner_check_no_pick(); 1018 if (fOwner) 1019 fOwner->Sync(); 1020 } 1021 1022 1023 BWindow * 1024 BView::Window() const 1025 { 1026 return fOwner; 1027 } 1028 1029 1030 // #pragma mark - 1031 // Hook Functions 1032 1033 1034 void 1035 BView::AttachedToWindow() 1036 { 1037 // Hook function 1038 STRACE(("\tHOOK: BView(%s)::AttachedToWindow()\n", Name())); 1039 } 1040 1041 1042 void 1043 BView::AllAttached() 1044 { 1045 // Hook function 1046 STRACE(("\tHOOK: BView(%s)::AllAttached()\n", Name())); 1047 } 1048 1049 1050 void 1051 BView::DetachedFromWindow() 1052 { 1053 // Hook function 1054 STRACE(("\tHOOK: BView(%s)::DetachedFromWindow()\n", Name())); 1055 } 1056 1057 1058 void 1059 BView::AllDetached() 1060 { 1061 // Hook function 1062 STRACE(("\tHOOK: BView(%s)::AllDetached()\n", Name())); 1063 } 1064 1065 1066 void 1067 BView::Draw(BRect updateRect) 1068 { 1069 // Hook function 1070 STRACE(("\tHOOK: BView(%s)::Draw()\n", Name())); 1071 } 1072 1073 1074 void 1075 BView::DrawAfterChildren(BRect r) 1076 { 1077 // HOOK function 1078 STRACE(("\tHOOK: BView(%s)::DrawAfterChildren()\n", Name())); 1079 } 1080 1081 1082 void 1083 BView::FrameMoved(BPoint newPosition) 1084 { 1085 // Hook function 1086 STRACE(("\tHOOK: BView(%s)::FrameMoved()\n", Name())); 1087 } 1088 1089 1090 void 1091 BView::FrameResized(float newWidth, float newHeight) 1092 { 1093 // Hook function 1094 STRACE(("\tHOOK: BView(%s)::FrameResized()\n", Name())); 1095 } 1096 1097 1098 void 1099 BView::GetPreferredSize(float* _width, float* _height) 1100 { 1101 STRACE(("\tHOOK: BView(%s)::GetPreferredSize()\n", Name())); 1102 1103 *_width = fBounds.Width(); 1104 *_height = fBounds.Height(); 1105 } 1106 1107 1108 void 1109 BView::ResizeToPreferred() 1110 { 1111 STRACE(("\tHOOK: BView(%s)::ResizeToPreferred()\n", Name())); 1112 1113 float width; 1114 float height; 1115 GetPreferredSize(&width, &height); 1116 1117 ResizeTo(width, height); 1118 } 1119 1120 1121 void 1122 BView::KeyDown(const char* bytes, int32 numBytes) 1123 { 1124 // Hook function 1125 STRACE(("\tHOOK: BView(%s)::KeyDown()\n", Name())); 1126 1127 if (Window()) 1128 Window()->_KeyboardNavigation(); 1129 } 1130 1131 1132 void 1133 BView::KeyUp(const char* bytes, int32 numBytes) 1134 { 1135 // Hook function 1136 STRACE(("\tHOOK: BView(%s)::KeyUp()\n", Name())); 1137 } 1138 1139 1140 void 1141 BView::MouseDown(BPoint where) 1142 { 1143 // Hook function 1144 STRACE(("\tHOOK: BView(%s)::MouseDown()\n", Name())); 1145 } 1146 1147 1148 void 1149 BView::MouseUp(BPoint where) 1150 { 1151 // Hook function 1152 STRACE(("\tHOOK: BView(%s)::MouseUp()\n", Name())); 1153 } 1154 1155 1156 void 1157 BView::MouseMoved(BPoint where, uint32 code, const BMessage* a_message) 1158 { 1159 // Hook function 1160 STRACE(("\tHOOK: BView(%s)::MouseMoved()\n", Name())); 1161 } 1162 1163 1164 void 1165 BView::Pulse() 1166 { 1167 // Hook function 1168 STRACE(("\tHOOK: BView(%s)::Pulse()\n", Name())); 1169 } 1170 1171 1172 void 1173 BView::TargetedByScrollView(BScrollView* scroll_view) 1174 { 1175 // Hook function 1176 STRACE(("\tHOOK: BView(%s)::TargetedByScrollView()\n", Name())); 1177 } 1178 1179 1180 void 1181 BView::WindowActivated(bool state) 1182 { 1183 // Hook function 1184 STRACE(("\tHOOK: BView(%s)::WindowActivated()\n", Name())); 1185 } 1186 1187 1188 // #pragma mark - 1189 // Input Functions 1190 1191 1192 void 1193 BView::BeginRectTracking(BRect startRect, uint32 style) 1194 { 1195 if (do_owner_check()) { 1196 fOwner->fLink->StartMessage(AS_LAYER_BEGIN_RECT_TRACK); 1197 fOwner->fLink->Attach<BRect>(startRect); 1198 fOwner->fLink->Attach<int32>(style); 1199 } 1200 } 1201 1202 1203 void 1204 BView::EndRectTracking() 1205 { 1206 if (do_owner_check()) 1207 fOwner->fLink->StartMessage(AS_LAYER_END_RECT_TRACK); 1208 } 1209 1210 1211 void 1212 BView::DragMessage(BMessage *message, BRect dragRect, BHandler *replyTo) 1213 { 1214 if (!message || !dragRect.IsValid()) 1215 return; 1216 1217 do_owner_check_no_pick(); 1218 1219 // calculate the offset 1220 BPoint offset; 1221 uint32 buttons; 1222 BMessage *current = fOwner->CurrentMessage(); 1223 if (!current || current->FindPoint("be:view_where", &offset) != B_OK) 1224 GetMouse(&offset, &buttons, false); 1225 offset -= dragRect.LeftTop(); 1226 1227 // create a drag bitmap for the rect 1228 BBitmap *bitmap = new BBitmap(dragRect, B_RGBA32); 1229 uint32 *bits = (uint32*)bitmap->Bits(); 1230 uint32 bytesPerRow = bitmap->BytesPerRow(); 1231 uint32 width = dragRect.IntegerWidth() + 1; 1232 uint32 height = dragRect.IntegerHeight() + 1; 1233 uint32 lastRow = (height - 1) * width; 1234 1235 memset(bits, 0x00, height * bytesPerRow); 1236 1237 // top 1238 for (uint32 i = 0; i < width; i += 2) 1239 bits[i] = 0xff000000; 1240 1241 // bottom 1242 for (uint32 i = (height % 2 == 0 ? 1 : 0); i < width; i += 2) 1243 bits[lastRow + i] = 0xff000000; 1244 1245 // left 1246 for (uint32 i = 0; i < lastRow; i += width * 2) 1247 bits[i] = 0xff000000; 1248 1249 // right 1250 for (uint32 i = (width % 2 == 0 ? width : 0); i < lastRow; i += width * 2) 1251 bits[width - 1 + i] = 0xff000000; 1252 1253 DragMessage(message, bitmap, B_OP_BLEND, offset, replyTo); 1254 } 1255 1256 1257 void 1258 BView::DragMessage(BMessage *message, BBitmap *image, BPoint offset, 1259 BHandler *replyTo) 1260 { 1261 DragMessage(message, image, B_OP_COPY, offset, replyTo); 1262 } 1263 1264 1265 void 1266 BView::DragMessage(BMessage *message, BBitmap *image, 1267 drawing_mode dragMode, BPoint offset, BHandler *replyTo) 1268 { 1269 // ToDo: is this correct? Isn't \a image allowed to be NULL? 1270 if (message == NULL || image == NULL) 1271 return; 1272 1273 if (replyTo == NULL) 1274 replyTo = this; 1275 1276 if (replyTo->Looper() == NULL) 1277 debugger("DragMessage: warning - the Handler needs a looper"); 1278 1279 do_owner_check_no_pick(); 1280 1281 if (!message->HasInt32("buttons")) { 1282 BMessage *msg = fOwner->CurrentMessage(); 1283 uint32 buttons; 1284 1285 if (msg == NULL || msg->FindInt32("buttons", (int32 *)&buttons) != B_OK) { 1286 BPoint point; 1287 GetMouse(&point, &buttons, false); 1288 } 1289 1290 message->AddInt32("buttons", buttons); 1291 } 1292 1293 BMessage::Private privateMessage(message); 1294 privateMessage.SetReply(BMessenger(replyTo, replyTo->Looper())); 1295 1296 // TODO: create area and flatten message into that area! 1297 // send area info over port, not the actual message! 1298 int32 bufferSize = privateMessage.NativeFlattenedSize(); 1299 char* buffer = new (nothrow) char[bufferSize]; 1300 if (buffer) { 1301 privateMessage.NativeFlatten(buffer, bufferSize); 1302 1303 fOwner->fLink->StartMessage(AS_LAYER_DRAG_IMAGE); 1304 fOwner->fLink->Attach<int32>(image->_ServerToken()); 1305 fOwner->fLink->Attach<int32>((int32)dragMode); 1306 fOwner->fLink->Attach<BPoint>(offset); 1307 fOwner->fLink->Attach<int32>(bufferSize); 1308 fOwner->fLink->Attach(buffer, bufferSize); 1309 1310 // we need to wait for the server 1311 // to actually process this message 1312 // before we can delete the bitmap 1313 int32 code; 1314 fOwner->fLink->FlushWithReply(code); 1315 1316 delete [] buffer; 1317 } else { 1318 fprintf(stderr, "BView::DragMessage() - no memory to flatten drag message\n"); 1319 } 1320 1321 delete image; 1322 } 1323 1324 1325 void 1326 BView::GetMouse(BPoint *location, uint32 *buttons, bool checkMessageQueue) 1327 { 1328 do_owner_check(); 1329 1330 if (checkMessageQueue) { 1331 Window()->UpdateIfNeeded(); 1332 BMessageQueue *queue = Window()->MessageQueue(); 1333 queue->Lock(); 1334 1335 // Look out for mouse update messages 1336 1337 BMessage *msg; 1338 for (int32 i = 0; (msg = queue->FindMessage(i)) != NULL; i++) { 1339 switch (msg->what) { 1340 case B_MOUSE_UP: 1341 case B_MOUSE_DOWN: 1342 case B_MOUSE_MOVED: 1343 msg->FindPoint("screen_where", location); 1344 msg->FindInt32("buttons", (int32 *)buttons); 1345 1346 ConvertFromScreen(location); 1347 1348 queue->RemoveMessage(msg); 1349 delete msg; 1350 1351 queue->Unlock(); 1352 return; 1353 } 1354 } 1355 queue->Unlock(); 1356 } 1357 1358 // If no mouse update message has been found in the message queue, 1359 // we get the current mouse location and buttons from the app_server 1360 1361 fOwner->fLink->StartMessage(AS_GET_MOUSE); 1362 1363 int32 code; 1364 if (fOwner->fLink->FlushWithReply(code) == B_OK 1365 && code == B_OK) { 1366 fOwner->fLink->Read<BPoint>(location); 1367 fOwner->fLink->Read<uint32>(buttons); 1368 1369 // TODO: See above comment about coordinates 1370 ConvertFromScreen(location); 1371 } else 1372 buttons = 0; 1373 } 1374 1375 1376 void 1377 BView::MakeFocus(bool focusState) 1378 { 1379 if (fOwner) { 1380 // TODO: If this view has focus and focusState==false, 1381 // will there really be no other view with focus? No 1382 // cycling to the next one? 1383 BView *focus = fOwner->CurrentFocus(); 1384 if (focusState) { 1385 // Unfocus a previous focus view 1386 if (focus && focus != this) 1387 focus->MakeFocus(false); 1388 // if we want to make this view the current focus view 1389 fOwner->fFocus = this; 1390 fOwner->SetPreferredHandler(this); 1391 } else { 1392 // we want to unfocus this view, but only if it actually has focus 1393 if (focus == this) { 1394 fOwner->fFocus = NULL; 1395 fOwner->SetPreferredHandler(NULL); 1396 } 1397 } 1398 } 1399 } 1400 1401 1402 BScrollBar * 1403 BView::ScrollBar(orientation posture) const 1404 { 1405 switch (posture) { 1406 case B_VERTICAL: 1407 return fVerScroller; 1408 1409 case B_HORIZONTAL: 1410 return fHorScroller; 1411 1412 default: 1413 return NULL; 1414 } 1415 } 1416 1417 1418 void 1419 BView::ScrollBy(float dh, float dv) 1420 { 1421 // scrolling by fractional values is not supported, is it? 1422 dh = roundf(dh); 1423 dv = roundf(dv); 1424 1425 // no reason to process this further if no scroll is intended. 1426 if (dh == 0 && dv == 0) 1427 return; 1428 1429 check_lock(); 1430 1431 // if we're attached to a window tell app_server about this change 1432 if (fOwner) { 1433 fOwner->fLink->StartMessage(AS_LAYER_SCROLL); 1434 fOwner->fLink->Attach<float>(dh); 1435 fOwner->fLink->Attach<float>(dv); 1436 1437 fOwner->fLink->Flush(); 1438 1439 fState->valid_flags &= ~(B_VIEW_FRAME_BIT | B_VIEW_ORIGIN_BIT); 1440 } 1441 1442 // we modify our bounds rectangle by dh/dv coord units hor/ver. 1443 fBounds.OffsetBy(dh, dv); 1444 1445 // then set the new values of the scrollbars 1446 if (fHorScroller) 1447 fHorScroller->SetValue(fBounds.left); 1448 if (fVerScroller) 1449 fVerScroller->SetValue(fBounds.top); 1450 } 1451 1452 1453 void 1454 BView::ScrollTo(BPoint where) 1455 { 1456 ScrollBy(where.x - fBounds.left, where.y - fBounds.top); 1457 } 1458 1459 1460 status_t 1461 BView::SetEventMask(uint32 mask, uint32 options) 1462 { 1463 if (fEventMask == mask && fEventOptions == options) 1464 return B_ERROR; 1465 1466 fEventMask = mask | (fEventMask & 0xFFFF0000); 1467 fEventOptions = options; 1468 1469 fState->archiving_flags |= B_VIEW_EVENT_MASK_BIT; 1470 1471 if (fOwner) { 1472 check_lock(); 1473 1474 fOwner->fLink->StartMessage(AS_LAYER_SET_EVENT_MASK); 1475 fOwner->fLink->Attach<uint32>(mask); 1476 fOwner->fLink->Attach<uint32>(options); 1477 } 1478 1479 return B_OK; 1480 } 1481 1482 1483 uint32 1484 BView::EventMask() 1485 { 1486 return fEventMask; 1487 } 1488 1489 1490 status_t 1491 BView::SetMouseEventMask(uint32 mask, uint32 options) 1492 { 1493 // Just don't do anything if the view is not yet attached 1494 // or we were called outside of BView::MouseDown() 1495 if (fOwner != NULL 1496 && fOwner->CurrentMessage() != NULL 1497 && fOwner->CurrentMessage()->what == B_MOUSE_DOWN) { 1498 check_lock(); 1499 fOwner->fLink->StartMessage(AS_LAYER_SET_MOUSE_EVENT_MASK); 1500 fOwner->fLink->Attach<uint32>(mask); 1501 fOwner->fLink->Attach<uint32>(options); 1502 1503 return B_OK; 1504 } 1505 1506 return B_ERROR; 1507 } 1508 1509 1510 // #pragma mark - 1511 // Graphic State Functions 1512 1513 1514 void 1515 BView::SetLineMode(cap_mode lineCap, join_mode lineJoin, float miterLimit) 1516 { 1517 if (fState->IsValid(B_VIEW_LINE_MODES_BIT) 1518 && lineCap == fState->line_cap && lineJoin == fState->line_join 1519 && miterLimit == fState->miter_limit) 1520 return; 1521 1522 if (fOwner) { 1523 check_lock(); 1524 1525 fOwner->fLink->StartMessage(AS_LAYER_SET_LINE_MODE); 1526 fOwner->fLink->Attach<int8>((int8)lineCap); 1527 fOwner->fLink->Attach<int8>((int8)lineJoin); 1528 fOwner->fLink->Attach<float>(miterLimit); 1529 1530 fState->valid_flags |= B_VIEW_LINE_MODES_BIT; 1531 } 1532 1533 fState->line_cap = lineCap; 1534 fState->line_join = lineJoin; 1535 fState->miter_limit = miterLimit; 1536 1537 fState->archiving_flags |= B_VIEW_LINE_MODES_BIT; 1538 } 1539 1540 1541 join_mode 1542 BView::LineJoinMode() const 1543 { 1544 // This will update the current state, if necessary 1545 if (!fState->IsValid(B_VIEW_LINE_MODES_BIT)) 1546 LineMiterLimit(); 1547 1548 return fState->line_join; 1549 } 1550 1551 1552 cap_mode 1553 BView::LineCapMode() const 1554 { 1555 // This will update the current state, if necessary 1556 if (!fState->IsValid(B_VIEW_LINE_MODES_BIT)) 1557 LineMiterLimit(); 1558 1559 return fState->line_cap; 1560 } 1561 1562 1563 float 1564 BView::LineMiterLimit() const 1565 { 1566 if (!fState->IsValid(B_VIEW_LINE_MODES_BIT) && fOwner) { 1567 check_lock(); 1568 1569 fOwner->fLink->StartMessage(AS_LAYER_GET_LINE_MODE); 1570 1571 int32 code; 1572 if (fOwner->fLink->FlushWithReply(code) == B_OK 1573 && code == B_OK) { 1574 int8 cap, join; 1575 fOwner->fLink->Read<int8>((int8 *)&cap); 1576 fOwner->fLink->Read<int8>((int8 *)&join); 1577 fOwner->fLink->Read<float>(&fState->miter_limit); 1578 1579 fState->line_cap = (cap_mode)cap; 1580 fState->line_join = (join_mode)join; 1581 } 1582 1583 fState->valid_flags |= B_VIEW_LINE_MODES_BIT; 1584 } 1585 1586 return fState->miter_limit; 1587 } 1588 1589 1590 void 1591 BView::PushState() 1592 { 1593 do_owner_check(); 1594 1595 fOwner->fLink->StartMessage(AS_LAYER_PUSH_STATE); 1596 1597 // initialize origin and scale 1598 fState->valid_flags |= B_VIEW_SCALE_BIT | B_VIEW_ORIGIN_BIT; 1599 fState->scale = 1.0f; 1600 fState->origin.Set(0, 0); 1601 } 1602 1603 1604 void 1605 BView::PopState() 1606 { 1607 do_owner_check(); 1608 1609 fOwner->fLink->StartMessage(AS_LAYER_POP_STATE); 1610 1611 // invalidate all flags (except those that are not part of pop/push) 1612 fState->valid_flags = B_VIEW_VIEW_COLOR_BIT; 1613 } 1614 1615 1616 void 1617 BView::SetScale(float scale) const 1618 { 1619 if (fState->IsValid(B_VIEW_SCALE_BIT) && scale == fState->scale) 1620 return; 1621 1622 if (fOwner) { 1623 check_lock(); 1624 1625 fOwner->fLink->StartMessage(AS_LAYER_SET_SCALE); 1626 fOwner->fLink->Attach<float>(scale); 1627 1628 fState->valid_flags |= B_VIEW_SCALE_BIT; 1629 } 1630 1631 fState->scale = scale; 1632 fState->archiving_flags |= B_VIEW_SCALE_BIT; 1633 } 1634 1635 1636 float 1637 BView::Scale() const 1638 { 1639 if (!fState->IsValid(B_VIEW_SCALE_BIT) && fOwner) { 1640 check_lock(); 1641 1642 fOwner->fLink->StartMessage(AS_LAYER_GET_SCALE); 1643 1644 int32 code; 1645 if (fOwner->fLink->FlushWithReply(code) == B_OK 1646 && code == B_OK) 1647 fOwner->fLink->Read<float>(&fState->scale); 1648 1649 fState->valid_flags |= B_VIEW_SCALE_BIT; 1650 } 1651 1652 return fState->scale; 1653 } 1654 1655 1656 void 1657 BView::SetDrawingMode(drawing_mode mode) 1658 { 1659 if (fState->IsValid(B_VIEW_DRAWING_MODE_BIT) 1660 && mode == fState->drawing_mode) 1661 return; 1662 1663 if (fOwner) { 1664 check_lock(); 1665 1666 fOwner->fLink->StartMessage(AS_LAYER_SET_DRAWING_MODE); 1667 fOwner->fLink->Attach<int8>((int8)mode); 1668 1669 fState->valid_flags |= B_VIEW_DRAWING_MODE_BIT; 1670 } 1671 1672 fState->drawing_mode = mode; 1673 fState->archiving_flags |= B_VIEW_DRAWING_MODE_BIT; 1674 } 1675 1676 1677 drawing_mode 1678 BView::DrawingMode() const 1679 { 1680 if (!fState->IsValid(B_VIEW_DRAWING_MODE_BIT) && fOwner) { 1681 check_lock(); 1682 1683 fOwner->fLink->StartMessage(AS_LAYER_GET_DRAWING_MODE); 1684 1685 int32 code; 1686 if (fOwner->fLink->FlushWithReply(code) == B_OK 1687 && code == B_OK) { 1688 int8 drawingMode; 1689 fOwner->fLink->Read<int8>(&drawingMode); 1690 1691 fState->drawing_mode = (drawing_mode)drawingMode; 1692 fState->valid_flags |= B_VIEW_DRAWING_MODE_BIT; 1693 } 1694 } 1695 1696 return fState->drawing_mode; 1697 } 1698 1699 1700 void 1701 BView::SetBlendingMode(source_alpha sourceAlpha, alpha_function alphaFunction) 1702 { 1703 if (fState->IsValid(B_VIEW_BLENDING_BIT) 1704 && sourceAlpha == fState->alpha_source_mode 1705 && alphaFunction == fState->alpha_function_mode) 1706 return; 1707 1708 if (fOwner) { 1709 check_lock(); 1710 1711 fOwner->fLink->StartMessage(AS_LAYER_SET_BLENDING_MODE); 1712 fOwner->fLink->Attach<int8>((int8)sourceAlpha); 1713 fOwner->fLink->Attach<int8>((int8)alphaFunction); 1714 1715 fState->valid_flags |= B_VIEW_BLENDING_BIT; 1716 } 1717 1718 fState->alpha_source_mode = sourceAlpha; 1719 fState->alpha_function_mode = alphaFunction; 1720 1721 fState->archiving_flags |= B_VIEW_BLENDING_BIT; 1722 } 1723 1724 1725 void 1726 BView::GetBlendingMode(source_alpha *_sourceAlpha, 1727 alpha_function *_alphaFunction) const 1728 { 1729 if (!fState->IsValid(B_VIEW_BLENDING_BIT) && fOwner) { 1730 check_lock(); 1731 1732 fOwner->fLink->StartMessage(AS_LAYER_GET_BLENDING_MODE); 1733 1734 int32 code; 1735 if (fOwner->fLink->FlushWithReply(code) == B_OK 1736 && code == B_OK) { 1737 int8 alphaSourceMode, alphaFunctionMode; 1738 fOwner->fLink->Read<int8>(&alphaSourceMode); 1739 fOwner->fLink->Read<int8>(&alphaFunctionMode); 1740 1741 fState->alpha_source_mode = (source_alpha)alphaSourceMode; 1742 fState->alpha_function_mode = (alpha_function)alphaFunctionMode; 1743 1744 fState->valid_flags |= B_VIEW_BLENDING_BIT; 1745 } 1746 } 1747 1748 if (_sourceAlpha) 1749 *_sourceAlpha = fState->alpha_source_mode; 1750 1751 if (_alphaFunction) 1752 *_alphaFunction = fState->alpha_function_mode; 1753 } 1754 1755 1756 void 1757 BView::MovePenTo(BPoint point) 1758 { 1759 MovePenTo(point.x, point.y); 1760 } 1761 1762 1763 void 1764 BView::MovePenTo(float x, float y) 1765 { 1766 if (fState->IsValid(B_VIEW_PEN_LOCATION_BIT) 1767 && x == fState->pen_location.x && y == fState->pen_location.y) 1768 return; 1769 1770 if (fOwner) { 1771 check_lock(); 1772 1773 fOwner->fLink->StartMessage(AS_LAYER_SET_PEN_LOC); 1774 fOwner->fLink->Attach<float>(x); 1775 fOwner->fLink->Attach<float>(y); 1776 1777 fState->valid_flags |= B_VIEW_PEN_LOCATION_BIT; 1778 } 1779 1780 fState->pen_location.x = x; 1781 fState->pen_location.y = y; 1782 1783 fState->archiving_flags |= B_VIEW_PEN_LOCATION_BIT; 1784 } 1785 1786 1787 void 1788 BView::MovePenBy(float x, float y) 1789 { 1790 // this will update the pen location if necessary 1791 if (!fState->IsValid(B_VIEW_PEN_LOCATION_BIT)) 1792 PenLocation(); 1793 1794 MovePenTo(fState->pen_location.x + x, fState->pen_location.y + y); 1795 } 1796 1797 1798 BPoint 1799 BView::PenLocation() const 1800 { 1801 if (!fState->IsValid(B_VIEW_PEN_LOCATION_BIT) && fOwner) { 1802 check_lock(); 1803 1804 fOwner->fLink->StartMessage(AS_LAYER_GET_PEN_LOC); 1805 1806 int32 code; 1807 if (fOwner->fLink->FlushWithReply(code) == B_OK 1808 && code == B_OK) { 1809 fOwner->fLink->Read<BPoint>(&fState->pen_location); 1810 1811 fState->valid_flags |= B_VIEW_PEN_LOCATION_BIT; 1812 } 1813 } 1814 1815 return fState->pen_location; 1816 } 1817 1818 1819 void 1820 BView::SetPenSize(float size) 1821 { 1822 if (fState->IsValid(B_VIEW_PEN_SIZE_BIT) && size == fState->pen_size) 1823 return; 1824 1825 if (fOwner) { 1826 check_lock(); 1827 1828 fOwner->fLink->StartMessage(AS_LAYER_SET_PEN_SIZE); 1829 fOwner->fLink->Attach<float>(size); 1830 1831 fState->valid_flags |= B_VIEW_PEN_SIZE_BIT; 1832 } 1833 1834 fState->pen_size = size; 1835 fState->archiving_flags |= B_VIEW_PEN_SIZE_BIT; 1836 } 1837 1838 1839 float 1840 BView::PenSize() const 1841 { 1842 if (!fState->IsValid(B_VIEW_PEN_SIZE_BIT) && fOwner) { 1843 check_lock(); 1844 1845 fOwner->fLink->StartMessage(AS_LAYER_GET_PEN_SIZE); 1846 1847 int32 code; 1848 if (fOwner->fLink->FlushWithReply(code) == B_OK 1849 && code == B_OK) { 1850 fOwner->fLink->Read<float>(&fState->pen_size); 1851 1852 fState->valid_flags |= B_VIEW_PEN_SIZE_BIT; 1853 } 1854 } 1855 1856 return fState->pen_size; 1857 } 1858 1859 1860 void 1861 BView::SetHighColor(rgb_color color) 1862 { 1863 // are we up-to-date already? 1864 if (fState->IsValid(B_VIEW_HIGH_COLOR_BIT) 1865 && fState->high_color == color) 1866 return; 1867 1868 if (fOwner) { 1869 check_lock(); 1870 1871 fOwner->fLink->StartMessage(AS_LAYER_SET_HIGH_COLOR); 1872 fOwner->fLink->Attach<rgb_color>(color); 1873 1874 fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT; 1875 } 1876 1877 fState->high_color = color; 1878 1879 fState->archiving_flags |= B_VIEW_HIGH_COLOR_BIT; 1880 } 1881 1882 1883 rgb_color 1884 BView::HighColor() const 1885 { 1886 if (!fState->IsValid(B_VIEW_HIGH_COLOR_BIT) && fOwner) { 1887 check_lock(); 1888 1889 fOwner->fLink->StartMessage(AS_LAYER_GET_HIGH_COLOR); 1890 1891 int32 code; 1892 if (fOwner->fLink->FlushWithReply(code) == B_OK 1893 && code == B_OK) { 1894 fOwner->fLink->Read<rgb_color>(&fState->high_color); 1895 1896 fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT; 1897 } 1898 } 1899 1900 return fState->high_color; 1901 } 1902 1903 1904 void 1905 BView::SetLowColor(rgb_color color) 1906 { 1907 if (fState->IsValid(B_VIEW_LOW_COLOR_BIT) 1908 && fState->low_color == color) 1909 return; 1910 1911 if (fOwner) { 1912 check_lock(); 1913 1914 fOwner->fLink->StartMessage(AS_LAYER_SET_LOW_COLOR); 1915 fOwner->fLink->Attach<rgb_color>(color); 1916 1917 fState->valid_flags |= B_VIEW_LOW_COLOR_BIT; 1918 } 1919 1920 fState->low_color = color; 1921 1922 fState->archiving_flags |= B_VIEW_LOW_COLOR_BIT; 1923 } 1924 1925 1926 rgb_color 1927 BView::LowColor() const 1928 { 1929 if (!fState->IsValid(B_VIEW_LOW_COLOR_BIT) && fOwner) { 1930 check_lock(); 1931 1932 fOwner->fLink->StartMessage(AS_LAYER_GET_LOW_COLOR); 1933 1934 int32 code; 1935 if (fOwner->fLink->FlushWithReply(code) == B_OK 1936 && code == B_OK) { 1937 fOwner->fLink->Read<rgb_color>(&fState->low_color); 1938 1939 fState->valid_flags |= B_VIEW_LOW_COLOR_BIT; 1940 } 1941 } 1942 1943 return fState->low_color; 1944 } 1945 1946 1947 void 1948 BView::SetViewColor(rgb_color color) 1949 { 1950 if (fState->IsValid(B_VIEW_VIEW_COLOR_BIT) && fState->view_color == color) 1951 return; 1952 1953 if (fOwner) { 1954 check_lock(); 1955 1956 fOwner->fLink->StartMessage(AS_LAYER_SET_VIEW_COLOR); 1957 fOwner->fLink->Attach<rgb_color>(color); 1958 1959 fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT; 1960 } 1961 1962 fState->view_color = color; 1963 1964 fState->archiving_flags |= B_VIEW_VIEW_COLOR_BIT; 1965 } 1966 1967 1968 rgb_color 1969 BView::ViewColor() const 1970 { 1971 if (!fState->IsValid(B_VIEW_VIEW_COLOR_BIT) && fOwner) { 1972 check_lock(); 1973 1974 fOwner->fLink->StartMessage(AS_LAYER_GET_VIEW_COLOR); 1975 1976 int32 code; 1977 if (fOwner->fLink->FlushWithReply(code) == B_OK 1978 && code == B_OK) { 1979 fOwner->fLink->Read<rgb_color>(&fState->view_color); 1980 1981 fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT; 1982 } 1983 } 1984 1985 return fState->view_color; 1986 } 1987 1988 1989 void 1990 BView::ForceFontAliasing(bool enable) 1991 { 1992 if (fState->IsValid(B_VIEW_FONT_ALIASING_BIT) && enable == fState->font_aliasing) 1993 return; 1994 1995 if (fOwner) { 1996 check_lock(); 1997 1998 fOwner->fLink->StartMessage(AS_LAYER_PRINT_ALIASING); 1999 fOwner->fLink->Attach<bool>(enable); 2000 2001 fState->valid_flags |= B_VIEW_FONT_ALIASING_BIT; 2002 } 2003 2004 fState->font_aliasing = enable; 2005 fState->archiving_flags |= B_VIEW_FONT_ALIASING_BIT; 2006 } 2007 2008 2009 void 2010 BView::SetFont(const BFont* font, uint32 mask) 2011 { 2012 if (!font || mask == 0) 2013 return; 2014 2015 if (mask == B_FONT_ALL) { 2016 fState->font = *font; 2017 } else { 2018 // ToDo: move this into a BFont method 2019 if (mask & B_FONT_FAMILY_AND_STYLE) 2020 fState->font.SetFamilyAndStyle(font->FamilyAndStyle()); 2021 2022 if (mask & B_FONT_SIZE) 2023 fState->font.SetSize(font->Size()); 2024 2025 if (mask & B_FONT_SHEAR) 2026 fState->font.SetShear(font->Shear()); 2027 2028 if (mask & B_FONT_ROTATION) 2029 fState->font.SetRotation(font->Rotation()); 2030 2031 if (mask & B_FONT_SPACING) 2032 fState->font.SetSpacing(font->Spacing()); 2033 2034 if (mask & B_FONT_ENCODING) 2035 fState->font.SetEncoding(font->Encoding()); 2036 2037 if (mask & B_FONT_FACE) 2038 fState->font.SetFace(font->Face()); 2039 2040 if (mask & B_FONT_FLAGS) 2041 fState->font.SetFlags(font->Flags()); 2042 } 2043 2044 fState->font_flags = mask; 2045 2046 if (fOwner) { 2047 check_lock(); 2048 do_owner_check(); 2049 2050 fState->UpdateServerFontState(*fOwner->fLink); 2051 } 2052 } 2053 2054 2055 #if !_PR3_COMPATIBLE_ 2056 void 2057 BView::GetFont(BFont *font) const 2058 #else 2059 void 2060 BView:GetFont(BFont *font) 2061 #endif 2062 { 2063 *font = fState->font; 2064 } 2065 2066 2067 void 2068 BView::GetFontHeight(font_height *height) const 2069 { 2070 fState->font.GetHeight(height); 2071 } 2072 2073 2074 void 2075 BView::SetFontSize(float size) 2076 { 2077 BFont font; 2078 font.SetSize(size); 2079 2080 SetFont(&font, B_FONT_SIZE); 2081 } 2082 2083 2084 float 2085 BView::StringWidth(const char *string) const 2086 { 2087 return fState->font.StringWidth(string); 2088 } 2089 2090 2091 float 2092 BView::StringWidth(const char* string, int32 length) const 2093 { 2094 return fState->font.StringWidth(string, length); 2095 } 2096 2097 2098 void 2099 BView::GetStringWidths(char *stringArray[],int32 lengthArray[], 2100 int32 numStrings, float widthArray[]) const 2101 { 2102 fState->font.GetStringWidths(const_cast<const char **>(stringArray), 2103 const_cast<const int32 *>(lengthArray), numStrings, widthArray); 2104 } 2105 2106 2107 void 2108 BView::TruncateString(BString *in_out, uint32 mode, float width) const 2109 { 2110 fState->font.TruncateString(in_out, mode, width); 2111 } 2112 2113 2114 void 2115 BView::ClipToPicture(BPicture *picture, BPoint where, bool sync) 2116 { 2117 DoPictureClip(picture, where, false, sync); 2118 } 2119 2120 2121 void 2122 BView::ClipToInversePicture(BPicture *picture, 2123 BPoint where, bool sync) 2124 { 2125 DoPictureClip(picture, where, true, sync); 2126 } 2127 2128 2129 void 2130 BView::GetClippingRegion(BRegion* region) const 2131 { 2132 if (!region) 2133 return; 2134 2135 // NOTE: the client has no idea when the clipping in the server 2136 // changed, so it is always read from the serber 2137 region->MakeEmpty(); 2138 2139 if (fOwner && do_owner_check()) { 2140 fOwner->fLink->StartMessage(AS_LAYER_GET_CLIP_REGION); 2141 2142 int32 code; 2143 if (fOwner->fLink->FlushWithReply(code) == B_OK 2144 && code == B_OK) { 2145 int32 count; 2146 fOwner->fLink->Read<int32>(&count); 2147 2148 for (int32 i = 0; i < count; i++) { 2149 BRect rect; 2150 fOwner->fLink->Read<BRect>(&rect); 2151 2152 region->Include(rect); 2153 } 2154 fState->valid_flags |= B_VIEW_CLIP_REGION_BIT; 2155 } 2156 } 2157 } 2158 2159 2160 void 2161 BView::ConstrainClippingRegion(BRegion* region) 2162 { 2163 if (do_owner_check()) { 2164 2165 fOwner->fLink->StartMessage(AS_LAYER_SET_CLIP_REGION); 2166 2167 if (region) { 2168 int32 count = region->CountRects(); 2169 fOwner->fLink->Attach<int32>(count); 2170 for (int32 i = 0; i < count; i++) 2171 fOwner->fLink->Attach<clipping_rect>(region->RectAtInt(i)); 2172 } else { 2173 fOwner->fLink->Attach<int32>(-1); 2174 // '-1' means that in the app_server, there won't be any 'local' 2175 // clipping region (it will be NULL) 2176 } 2177 2178 // we flush here because app_server waits for all the rects 2179 fOwner->fLink->Flush(); 2180 2181 fState->valid_flags &= ~B_VIEW_CLIP_REGION_BIT; 2182 fState->archiving_flags |= B_VIEW_CLIP_REGION_BIT; 2183 } 2184 } 2185 2186 2187 // #pragma mark - Drawing Functions 2188 //--------------------------------------------------------------------------- 2189 2190 2191 void 2192 BView::DrawBitmapAsync(const BBitmap *bitmap, BRect srcRect, BRect dstRect) 2193 { 2194 if (!bitmap || !srcRect.IsValid() || !dstRect.IsValid()) 2195 return; 2196 2197 if (fOwner) { 2198 check_lock(); 2199 2200 fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP); 2201 fOwner->fLink->Attach<int32>(bitmap->_ServerToken()); 2202 fOwner->fLink->Attach<BRect>(dstRect); 2203 fOwner->fLink->Attach<BRect>(srcRect); 2204 2205 _FlushIfNotInTransaction(); 2206 } 2207 } 2208 2209 2210 void 2211 BView::DrawBitmapAsync(const BBitmap *bitmap, BRect dstRect) 2212 { 2213 DrawBitmapAsync(bitmap, bitmap->Bounds(), dstRect); 2214 } 2215 2216 2217 void 2218 BView::DrawBitmapAsync(const BBitmap *bitmap) 2219 { 2220 DrawBitmapAsync(bitmap, PenLocation()); 2221 } 2222 2223 2224 void 2225 BView::DrawBitmapAsync(const BBitmap *bitmap, BPoint where) 2226 { 2227 if (bitmap == NULL) 2228 return; 2229 2230 if (fOwner) { 2231 check_lock(); 2232 2233 fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP); 2234 fOwner->fLink->Attach<int32>(bitmap->_ServerToken()); 2235 BRect src = bitmap->Bounds(); 2236 BRect dst = src.OffsetToCopy(where); 2237 fOwner->fLink->Attach<BRect>(dst); 2238 fOwner->fLink->Attach<BRect>(src); 2239 2240 _FlushIfNotInTransaction(); 2241 } 2242 } 2243 2244 2245 void 2246 BView::DrawBitmap(const BBitmap *bitmap) 2247 { 2248 DrawBitmap(bitmap, PenLocation()); 2249 } 2250 2251 2252 void 2253 BView::DrawBitmap(const BBitmap *bitmap, BPoint where) 2254 { 2255 if (fOwner) { 2256 DrawBitmapAsync(bitmap, where); 2257 Sync(); 2258 } 2259 } 2260 2261 2262 void 2263 BView::DrawBitmap(const BBitmap *bitmap, BRect dstRect) 2264 { 2265 DrawBitmap(bitmap, bitmap->Bounds(), dstRect); 2266 } 2267 2268 2269 void 2270 BView::DrawBitmap(const BBitmap *bitmap, BRect srcRect, BRect dstRect) 2271 { 2272 if (fOwner) { 2273 DrawBitmapAsync(bitmap, srcRect, dstRect); 2274 Sync(); 2275 } 2276 } 2277 2278 2279 void 2280 BView::DrawChar(char c) 2281 { 2282 DrawString(&c, 1, PenLocation()); 2283 } 2284 2285 2286 void 2287 BView::DrawChar(char c, BPoint location) 2288 { 2289 DrawString(&c, 1, location); 2290 } 2291 2292 2293 void 2294 BView::DrawString(const char *string, escapement_delta *delta) 2295 { 2296 if (string == NULL) 2297 return; 2298 2299 DrawString(string, strlen(string), PenLocation(), delta); 2300 } 2301 2302 2303 void 2304 BView::DrawString(const char *string, BPoint location, escapement_delta *delta) 2305 { 2306 if (string == NULL) 2307 return; 2308 2309 DrawString(string, strlen(string), location, delta); 2310 } 2311 2312 2313 void 2314 BView::DrawString(const char *string, int32 length, escapement_delta *delta) 2315 { 2316 DrawString(string, length, PenLocation(), delta); 2317 } 2318 2319 2320 void 2321 BView::DrawString(const char *string, int32 length, BPoint location, 2322 escapement_delta *delta) 2323 { 2324 if (string == NULL || length < 1) 2325 return; 2326 2327 if (fOwner) { 2328 check_lock(); 2329 2330 fOwner->fLink->StartMessage(AS_DRAW_STRING); 2331 fOwner->fLink->Attach<int32>(length); 2332 fOwner->fLink->Attach<BPoint>(location); 2333 2334 // Quite often delta will be NULL, so we have to accomodate this. 2335 if (delta) 2336 fOwner->fLink->Attach<escapement_delta>(*delta); 2337 else { 2338 escapement_delta tdelta; 2339 tdelta.space = 0; 2340 tdelta.nonspace = 0; 2341 2342 fOwner->fLink->Attach<escapement_delta>(tdelta); 2343 } 2344 2345 fOwner->fLink->AttachString(string, length); 2346 2347 _FlushIfNotInTransaction(); 2348 2349 // this modifies our pen location, so we invalidate the flag. 2350 fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT; 2351 } 2352 } 2353 2354 2355 void 2356 BView::StrokeEllipse(BPoint center, float xRadius, float yRadius, 2357 pattern p) 2358 { 2359 StrokeEllipse(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius, 2360 center.y + yRadius), p); 2361 } 2362 2363 2364 void 2365 BView::StrokeEllipse(BRect rect, ::pattern pattern) 2366 { 2367 if (fOwner == NULL) 2368 return; 2369 2370 check_lock(); 2371 _UpdatePattern(pattern); 2372 2373 fOwner->fLink->StartMessage(AS_STROKE_ELLIPSE); 2374 fOwner->fLink->Attach<BRect>(rect); 2375 2376 _FlushIfNotInTransaction(); 2377 } 2378 2379 2380 void 2381 BView::FillEllipse(BPoint center, float xRadius, float yRadius, 2382 ::pattern pattern) 2383 { 2384 FillEllipse(BRect(center.x - xRadius, center.y - yRadius, 2385 center.x + xRadius, center.y + yRadius), pattern); 2386 } 2387 2388 2389 void 2390 BView::FillEllipse(BRect rect, ::pattern pattern) 2391 { 2392 if (fOwner == NULL) 2393 return; 2394 2395 check_lock(); 2396 _UpdatePattern(pattern); 2397 2398 fOwner->fLink->StartMessage(AS_FILL_ELLIPSE); 2399 fOwner->fLink->Attach<BRect>(rect); 2400 2401 _FlushIfNotInTransaction(); 2402 } 2403 2404 2405 void 2406 BView::StrokeArc(BPoint center, float xRadius, float yRadius, 2407 float startAngle, float arcAngle, pattern p) 2408 { 2409 StrokeArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius, 2410 center.y + yRadius), startAngle, arcAngle, p); 2411 } 2412 2413 2414 void 2415 BView::StrokeArc(BRect rect, float startAngle, float arcAngle, 2416 ::pattern pattern) 2417 { 2418 if (fOwner == NULL) 2419 return; 2420 2421 check_lock(); 2422 _UpdatePattern(pattern); 2423 2424 fOwner->fLink->StartMessage(AS_STROKE_ARC); 2425 fOwner->fLink->Attach<BRect>(rect); 2426 fOwner->fLink->Attach<float>(startAngle); 2427 fOwner->fLink->Attach<float>(arcAngle); 2428 2429 _FlushIfNotInTransaction(); 2430 } 2431 2432 2433 void 2434 BView::FillArc(BPoint center,float xRadius, float yRadius, 2435 float startAngle, float arcAngle, ::pattern pattern) 2436 { 2437 FillArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius, 2438 center.y + yRadius), startAngle, arcAngle, pattern); 2439 } 2440 2441 2442 void 2443 BView::FillArc(BRect rect, float startAngle, float arcAngle, 2444 ::pattern pattern) 2445 { 2446 if (fOwner == NULL) 2447 return; 2448 2449 check_lock(); 2450 _UpdatePattern(pattern); 2451 2452 fOwner->fLink->StartMessage(AS_FILL_ARC); 2453 fOwner->fLink->Attach<BRect>(rect); 2454 fOwner->fLink->Attach<float>(startAngle); 2455 fOwner->fLink->Attach<float>(arcAngle); 2456 2457 _FlushIfNotInTransaction(); 2458 } 2459 2460 2461 void 2462 BView::StrokeBezier(BPoint *controlPoints, ::pattern pattern) 2463 { 2464 if (fOwner == NULL) 2465 return; 2466 2467 check_lock(); 2468 _UpdatePattern(pattern); 2469 2470 fOwner->fLink->StartMessage(AS_STROKE_BEZIER); 2471 fOwner->fLink->Attach<BPoint>(controlPoints[0]); 2472 fOwner->fLink->Attach<BPoint>(controlPoints[1]); 2473 fOwner->fLink->Attach<BPoint>(controlPoints[2]); 2474 fOwner->fLink->Attach<BPoint>(controlPoints[3]); 2475 2476 _FlushIfNotInTransaction(); 2477 } 2478 2479 2480 void 2481 BView::FillBezier(BPoint *controlPoints, ::pattern pattern) 2482 { 2483 if (fOwner == NULL) 2484 return; 2485 2486 check_lock(); 2487 _UpdatePattern(pattern); 2488 2489 fOwner->fLink->StartMessage(AS_FILL_BEZIER); 2490 fOwner->fLink->Attach<BPoint>(controlPoints[0]); 2491 fOwner->fLink->Attach<BPoint>(controlPoints[1]); 2492 fOwner->fLink->Attach<BPoint>(controlPoints[2]); 2493 fOwner->fLink->Attach<BPoint>(controlPoints[3]); 2494 2495 _FlushIfNotInTransaction(); 2496 } 2497 2498 2499 void 2500 BView::StrokePolygon(const BPolygon *polygon, bool closed, pattern p) 2501 { 2502 if (!polygon) 2503 return; 2504 2505 StrokePolygon(polygon->fPts, polygon->fCount, polygon->Frame(), closed, p); 2506 } 2507 2508 2509 void 2510 BView::StrokePolygon(const BPoint *ptArray, int32 numPoints, bool closed, pattern p) 2511 { 2512 BPolygon polygon(ptArray, numPoints); 2513 2514 StrokePolygon(polygon.fPts, polygon.fCount, polygon.Frame(), closed, p); 2515 } 2516 2517 2518 void 2519 BView::StrokePolygon(const BPoint *ptArray, int32 numPoints, BRect bounds, 2520 bool closed, ::pattern pattern) 2521 { 2522 if (!ptArray 2523 || numPoints <= 1 2524 || fOwner == NULL) 2525 return; 2526 2527 check_lock(); 2528 _UpdatePattern(pattern); 2529 2530 BPolygon polygon(ptArray, numPoints); 2531 polygon.MapTo(polygon.Frame(), bounds); 2532 2533 if (fOwner->fLink->StartMessage(AS_STROKE_POLYGON, 2534 polygon.fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(bool) + sizeof(int32)) 2535 == B_OK) { 2536 fOwner->fLink->Attach<BRect>(polygon.Frame()); 2537 fOwner->fLink->Attach<bool>(closed); 2538 fOwner->fLink->Attach<int32>(polygon.fCount); 2539 fOwner->fLink->Attach(polygon.fPts, polygon.fCount * sizeof(BPoint)); 2540 2541 _FlushIfNotInTransaction(); 2542 } else { 2543 // TODO: send via an area 2544 fprintf(stderr, "ERROR: polygon to big for BPortLink!\n"); 2545 } 2546 } 2547 2548 2549 void 2550 BView::FillPolygon(const BPolygon *polygon, ::pattern pattern) 2551 { 2552 if (polygon == NULL 2553 || polygon->fCount <= 2 2554 || fOwner == NULL) 2555 return; 2556 2557 check_lock(); 2558 _UpdatePattern(pattern); 2559 2560 if (fOwner->fLink->StartMessage(AS_FILL_POLYGON, 2561 polygon->fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(int32)) == B_OK) { 2562 fOwner->fLink->Attach<BRect>(polygon->Frame()); 2563 fOwner->fLink->Attach<int32>(polygon->fCount); 2564 fOwner->fLink->Attach(polygon->fPts, polygon->fCount * sizeof(BPoint)); 2565 2566 _FlushIfNotInTransaction(); 2567 } else { 2568 // TODO: send via an area 2569 fprintf(stderr, "ERROR: polygon to big for BPortLink!\n"); 2570 } 2571 } 2572 2573 2574 void 2575 BView::FillPolygon(const BPoint *ptArray, int32 numPts, ::pattern pattern) 2576 { 2577 if (!ptArray) 2578 return; 2579 2580 BPolygon polygon(ptArray, numPts); 2581 FillPolygon(&polygon, pattern); 2582 } 2583 2584 2585 void 2586 BView::FillPolygon(const BPoint *ptArray, int32 numPts, BRect bounds, 2587 pattern p) 2588 { 2589 if (!ptArray) 2590 return; 2591 2592 BPolygon polygon(ptArray, numPts); 2593 2594 polygon.MapTo(polygon.Frame(), bounds); 2595 FillPolygon(&polygon, p); 2596 } 2597 2598 2599 void 2600 BView::StrokeRect(BRect rect, ::pattern pattern) 2601 { 2602 if (fOwner == NULL) 2603 return; 2604 2605 check_lock(); 2606 _UpdatePattern(pattern); 2607 2608 fOwner->fLink->StartMessage(AS_STROKE_RECT); 2609 fOwner->fLink->Attach<BRect>(rect); 2610 2611 _FlushIfNotInTransaction(); 2612 } 2613 2614 2615 void 2616 BView::FillRect(BRect rect, ::pattern pattern) 2617 { 2618 if (fOwner == NULL) 2619 return; 2620 2621 check_lock(); 2622 _UpdatePattern(pattern); 2623 2624 fOwner->fLink->StartMessage(AS_FILL_RECT); 2625 fOwner->fLink->Attach<BRect>(rect); 2626 2627 _FlushIfNotInTransaction(); 2628 } 2629 2630 2631 void 2632 BView::StrokeRoundRect(BRect rect, float xRadius, float yRadius, 2633 ::pattern pattern) 2634 { 2635 if (fOwner == NULL) 2636 return; 2637 2638 check_lock(); 2639 _UpdatePattern(pattern); 2640 2641 fOwner->fLink->StartMessage(AS_STROKE_ROUNDRECT); 2642 fOwner->fLink->Attach<BRect>(rect); 2643 fOwner->fLink->Attach<float>(xRadius); 2644 fOwner->fLink->Attach<float>(yRadius); 2645 2646 _FlushIfNotInTransaction(); 2647 } 2648 2649 2650 void 2651 BView::FillRoundRect(BRect rect, float xRadius, float yRadius, 2652 ::pattern pattern) 2653 { 2654 if (fOwner == NULL) 2655 return; 2656 2657 check_lock(); 2658 2659 _UpdatePattern(pattern); 2660 2661 fOwner->fLink->StartMessage(AS_FILL_ROUNDRECT); 2662 fOwner->fLink->Attach<BRect>(rect); 2663 fOwner->fLink->Attach<float>(xRadius); 2664 fOwner->fLink->Attach<float>(yRadius); 2665 2666 _FlushIfNotInTransaction(); 2667 } 2668 2669 2670 void 2671 BView::FillRegion(BRegion *region, ::pattern pattern) 2672 { 2673 if (region == NULL || fOwner == NULL) 2674 return; 2675 2676 check_lock(); 2677 2678 _UpdatePattern(pattern); 2679 2680 fOwner->fLink->StartMessage(AS_FILL_REGION); 2681 fOwner->fLink->AttachRegion(*region); 2682 // TODO: make this automatically chose 2683 // to send over area or handle failure here? 2684 2685 _FlushIfNotInTransaction(); 2686 } 2687 2688 2689 void 2690 BView::StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3, 2691 BRect bounds, ::pattern pattern) 2692 { 2693 if (fOwner == NULL) 2694 return; 2695 2696 check_lock(); 2697 2698 _UpdatePattern(pattern); 2699 2700 fOwner->fLink->StartMessage(AS_STROKE_TRIANGLE); 2701 fOwner->fLink->Attach<BPoint>(pt1); 2702 fOwner->fLink->Attach<BPoint>(pt2); 2703 fOwner->fLink->Attach<BPoint>(pt3); 2704 fOwner->fLink->Attach<BRect>(bounds); 2705 2706 _FlushIfNotInTransaction(); 2707 } 2708 2709 2710 void 2711 BView::StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3, pattern p) 2712 { 2713 if (fOwner) { 2714 // we construct the smallest rectangle that contains the 3 points 2715 // for the 1st point 2716 BRect bounds(pt1, pt1); 2717 2718 // for the 2nd point 2719 if (pt2.x < bounds.left) 2720 bounds.left = pt2.x; 2721 2722 if (pt2.y < bounds.top) 2723 bounds.top = pt2.y; 2724 2725 if (pt2.x > bounds.right) 2726 bounds.right = pt2.x; 2727 2728 if (pt2.y > bounds.bottom) 2729 bounds.bottom = pt2.y; 2730 2731 // for the 3rd point 2732 if (pt3.x < bounds.left) 2733 bounds.left = pt3.x; 2734 2735 if (pt3.y < bounds.top) 2736 bounds.top = pt3.y; 2737 2738 if (pt3.x > bounds.right) 2739 bounds.right = pt3.x; 2740 2741 if (pt3.y > bounds.bottom) 2742 bounds.bottom = pt3.y; 2743 2744 StrokeTriangle(pt1, pt2, pt3, bounds, p); 2745 } 2746 } 2747 2748 2749 void 2750 BView::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, pattern p) 2751 { 2752 if (fOwner) { 2753 // we construct the smallest rectangle that contains the 3 points 2754 // for the 1st point 2755 BRect bounds(pt1, pt1); 2756 2757 // for the 2nd point 2758 if (pt2.x < bounds.left) 2759 bounds.left = pt2.x; 2760 2761 if (pt2.y < bounds.top) 2762 bounds.top = pt2.y; 2763 2764 if (pt2.x > bounds.right) 2765 bounds.right = pt2.x; 2766 2767 if (pt2.y > bounds.bottom) 2768 bounds.bottom = pt2.y; 2769 2770 // for the 3rd point 2771 if (pt3.x < bounds.left) 2772 bounds.left = pt3.x; 2773 2774 if (pt3.y < bounds.top) 2775 bounds.top = pt3.y; 2776 2777 if (pt3.x > bounds.right) 2778 bounds.right = pt3.x; 2779 2780 if (pt3.y > bounds.bottom) 2781 bounds.bottom = pt3.y; 2782 2783 FillTriangle(pt1, pt2, pt3, bounds, p); 2784 } 2785 } 2786 2787 2788 void 2789 BView::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, 2790 BRect bounds, ::pattern pattern) 2791 { 2792 if (fOwner == NULL) 2793 return; 2794 2795 check_lock(); 2796 _UpdatePattern(pattern); 2797 2798 fOwner->fLink->StartMessage(AS_FILL_TRIANGLE); 2799 fOwner->fLink->Attach<BPoint>(pt1); 2800 fOwner->fLink->Attach<BPoint>(pt2); 2801 fOwner->fLink->Attach<BPoint>(pt3); 2802 fOwner->fLink->Attach<BRect>(bounds); 2803 2804 _FlushIfNotInTransaction(); 2805 } 2806 2807 2808 void 2809 BView::StrokeLine(BPoint toPt, pattern p) 2810 { 2811 StrokeLine(PenLocation(), toPt, p); 2812 } 2813 2814 2815 void 2816 BView::StrokeLine(BPoint pt0, BPoint pt1, ::pattern pattern) 2817 { 2818 if (fOwner == NULL) 2819 return; 2820 2821 check_lock(); 2822 _UpdatePattern(pattern); 2823 2824 fOwner->fLink->StartMessage(AS_STROKE_LINE); 2825 fOwner->fLink->Attach<BPoint>(pt0); 2826 fOwner->fLink->Attach<BPoint>(pt1); 2827 2828 _FlushIfNotInTransaction(); 2829 2830 // this modifies our pen location, so we invalidate the flag. 2831 fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT; 2832 } 2833 2834 2835 void 2836 BView::StrokeShape(BShape *shape, ::pattern pattern) 2837 { 2838 if (shape == NULL || fOwner == NULL) 2839 return; 2840 2841 shape_data *sd = (shape_data *)shape->fPrivateData; 2842 if (sd->opCount == 0 || sd->ptCount == 0) 2843 return; 2844 2845 check_lock(); 2846 _UpdatePattern(pattern); 2847 2848 if ((sd->opCount * sizeof(uint32)) + (sd->ptCount * sizeof(BPoint)) < MAX_ATTACHMENT_SIZE) { 2849 fOwner->fLink->StartMessage(AS_STROKE_SHAPE); 2850 fOwner->fLink->Attach<BRect>(shape->Bounds()); 2851 fOwner->fLink->Attach<int32>(sd->opCount); 2852 fOwner->fLink->Attach<int32>(sd->ptCount); 2853 fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(uint32)); 2854 fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint)); 2855 2856 _FlushIfNotInTransaction(); 2857 } else { 2858 // TODO: send via an area 2859 } 2860 } 2861 2862 2863 void 2864 BView::FillShape(BShape *shape, ::pattern pattern) 2865 { 2866 if (shape == NULL || fOwner == NULL) 2867 return; 2868 2869 shape_data *sd = (shape_data *)(shape->fPrivateData); 2870 if (sd->opCount == 0 || sd->ptCount == 0) 2871 return; 2872 2873 check_lock(); 2874 _UpdatePattern(pattern); 2875 2876 if ((sd->opCount * sizeof(uint32)) + (sd->ptCount * sizeof(BPoint)) < MAX_ATTACHMENT_SIZE) { 2877 fOwner->fLink->StartMessage(AS_FILL_SHAPE); 2878 fOwner->fLink->Attach<BRect>(shape->Bounds()); 2879 fOwner->fLink->Attach<int32>(sd->opCount); 2880 fOwner->fLink->Attach<int32>(sd->ptCount); 2881 fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(int32)); 2882 fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint)); 2883 2884 _FlushIfNotInTransaction(); 2885 } else { 2886 // TODO: send via an area 2887 // BTW, in a perfect world, the fLink API would take care of that -- axeld. 2888 } 2889 } 2890 2891 2892 void 2893 BView::BeginLineArray(int32 count) 2894 { 2895 if (fOwner == NULL) 2896 return; 2897 2898 if (count <= 0) 2899 debugger("Calling BeginLineArray with a count <= 0"); 2900 2901 check_lock_no_pick(); 2902 2903 if (comm) { 2904 debugger("Can't nest BeginLineArray calls"); 2905 // not fatal, but it helps during 2906 // development of your app and is in 2907 // line with R5... 2908 delete [] comm->array; 2909 delete comm; 2910 } 2911 2912 comm = new _array_data_; 2913 2914 comm->maxCount = count; 2915 comm->count = 0; 2916 comm->array = new _array_hdr_[count]; 2917 } 2918 2919 2920 void 2921 BView::AddLine(BPoint pt0, BPoint pt1, rgb_color col) 2922 { 2923 if (fOwner == NULL) 2924 return; 2925 2926 if (!comm) 2927 debugger("BeginLineArray must be called before using AddLine"); 2928 2929 check_lock_no_pick(); 2930 2931 if (comm->count < comm->maxCount) { 2932 comm->array[comm->count].startX = pt0.x; 2933 comm->array[comm->count].startY = pt0.y; 2934 comm->array[comm->count].endX = pt1.x; 2935 comm->array[comm->count].endY = pt1.y; 2936 comm->array[comm->count].color = col; 2937 2938 comm->count++; 2939 } 2940 } 2941 2942 2943 void 2944 BView::EndLineArray() 2945 { 2946 if (fOwner == NULL) 2947 return; 2948 2949 if (!comm) 2950 debugger("Can't call EndLineArray before BeginLineArray"); 2951 2952 check_lock(); 2953 2954 fOwner->fLink->StartMessage(AS_STROKE_LINEARRAY); 2955 fOwner->fLink->Attach<int32>(comm->count); 2956 fOwner->fLink->Attach(comm->array, comm->count * sizeof(_array_hdr_)); 2957 2958 _FlushIfNotInTransaction(); 2959 2960 removeCommArray(); 2961 } 2962 2963 2964 void 2965 BView::BeginPicture(BPicture *picture) 2966 { 2967 if (do_owner_check() && picture && picture->usurped == NULL) { 2968 picture->usurp(cpicture); 2969 cpicture = picture; 2970 2971 fOwner->fLink->StartMessage(AS_LAYER_BEGIN_PICTURE); 2972 } 2973 } 2974 2975 2976 void 2977 BView::AppendToPicture(BPicture *picture) 2978 { 2979 check_lock(); 2980 2981 if (picture && picture->usurped == NULL) { 2982 int32 token = picture->token; 2983 2984 if (token == -1) { 2985 BeginPicture(picture); 2986 } else { 2987 picture->usurped = cpicture; 2988 picture->set_token(-1); 2989 fOwner->fLink->StartMessage(AS_LAYER_APPEND_TO_PICTURE); 2990 fOwner->fLink->Attach<int32>(token); 2991 } 2992 } 2993 } 2994 2995 2996 BPicture * 2997 BView::EndPicture() 2998 { 2999 if (do_owner_check() && cpicture) { 3000 int32 token; 3001 3002 fOwner->fLink->StartMessage(AS_LAYER_END_PICTURE); 3003 3004 int32 code; 3005 if (fOwner->fLink->FlushWithReply(code) == B_OK 3006 && code == B_OK 3007 && fOwner->fLink->Read<int32>(&token) == B_OK) { 3008 BPicture *picture = cpicture; 3009 cpicture = picture->step_down(); 3010 picture->set_token(token); 3011 3012 return picture; 3013 } 3014 } 3015 3016 return NULL; 3017 } 3018 3019 3020 void 3021 BView::SetViewBitmap(const BBitmap *bitmap, BRect srcRect, BRect dstRect, 3022 uint32 followFlags, uint32 options) 3023 { 3024 _SetViewBitmap(bitmap, srcRect, dstRect, followFlags, options); 3025 } 3026 3027 3028 void 3029 BView::SetViewBitmap(const BBitmap *bitmap, uint32 followFlags, uint32 options) 3030 { 3031 BRect rect; 3032 if (bitmap) 3033 rect = bitmap->Bounds(); 3034 3035 rect.OffsetTo(0, 0); 3036 3037 _SetViewBitmap(bitmap, rect, rect, followFlags, options); 3038 } 3039 3040 3041 void 3042 BView::ClearViewBitmap() 3043 { 3044 _SetViewBitmap(NULL, BRect(), BRect(), 0, 0); 3045 } 3046 3047 3048 status_t 3049 BView::SetViewOverlay(const BBitmap *overlay, BRect srcRect, BRect dstRect, 3050 rgb_color *colorKey, uint32 followFlags, uint32 options) 3051 { 3052 if ((overlay->fFlags & B_BITMAP_WILL_OVERLAY) == 0) 3053 return B_BAD_VALUE; 3054 3055 status_t status = _SetViewBitmap(overlay, srcRect, dstRect, followFlags, 3056 options | AS_REQUEST_COLOR_KEY); 3057 if (status == B_OK) { 3058 // read the color that will be treated as transparent 3059 fOwner->fLink->Read<rgb_color>(colorKey); 3060 } 3061 3062 return status; 3063 } 3064 3065 3066 status_t 3067 BView::SetViewOverlay(const BBitmap *overlay, rgb_color *colorKey, 3068 uint32 followFlags, uint32 options) 3069 { 3070 BRect rect; 3071 if (overlay != NULL) { 3072 rect = overlay->Bounds(); 3073 rect.OffsetTo(B_ORIGIN); 3074 } 3075 3076 return SetViewOverlay(overlay, rect, rect, colorKey, followFlags, options); 3077 } 3078 3079 3080 void 3081 BView::ClearViewOverlay() 3082 { 3083 _SetViewBitmap(NULL, BRect(), BRect(), 0, 0); 3084 } 3085 3086 3087 void 3088 BView::CopyBits(BRect src, BRect dst) 3089 { 3090 if (!src.IsValid() || !dst.IsValid()) 3091 return; 3092 3093 if (do_owner_check()) { 3094 fOwner->fLink->StartMessage(AS_LAYER_COPY_BITS); 3095 fOwner->fLink->Attach<BRect>(src); 3096 fOwner->fLink->Attach<BRect>(dst); 3097 3098 _FlushIfNotInTransaction(); 3099 } 3100 } 3101 3102 3103 void 3104 BView::DrawPicture(const BPicture *picture) 3105 { 3106 if (picture == NULL) 3107 return; 3108 3109 DrawPictureAsync(picture, PenLocation()); 3110 Sync(); 3111 } 3112 3113 3114 void 3115 BView::DrawPicture(const BPicture *picture, BPoint where) 3116 { 3117 if (picture == NULL) 3118 return; 3119 3120 DrawPictureAsync(picture, where); 3121 Sync(); 3122 } 3123 3124 3125 void 3126 BView::DrawPicture(const char *filename, long offset, BPoint where) 3127 { 3128 if (!filename) 3129 return; 3130 3131 DrawPictureAsync(filename, offset, where); 3132 Sync(); 3133 } 3134 3135 3136 void 3137 BView::DrawPictureAsync(const BPicture *picture) 3138 { 3139 if (picture == NULL) 3140 return; 3141 3142 DrawPictureAsync(picture, PenLocation()); 3143 } 3144 3145 3146 void 3147 BView::DrawPictureAsync(const BPicture *picture, BPoint where) 3148 { 3149 if (picture == NULL) 3150 return; 3151 3152 if (do_owner_check() && picture->token > 0) { 3153 fOwner->fLink->StartMessage(AS_LAYER_DRAW_PICTURE); 3154 fOwner->fLink->Attach<int32>(picture->token); 3155 fOwner->fLink->Attach<BPoint>(where); 3156 3157 _FlushIfNotInTransaction(); 3158 } 3159 } 3160 3161 3162 void 3163 BView::DrawPictureAsync(const char *filename, long offset, BPoint where) 3164 { 3165 if (!filename) 3166 return; 3167 3168 // TODO: Test 3169 BFile file(filename, B_READ_ONLY); 3170 if (file.InitCheck() < B_OK) 3171 return; 3172 3173 file.Seek(offset, SEEK_SET); 3174 3175 BPicture picture; 3176 if (picture.Unflatten(&file) < B_OK) 3177 return; 3178 3179 DrawPictureAsync(&picture, where); 3180 } 3181 3182 3183 void 3184 BView::Invalidate(BRect invalRect) 3185 { 3186 if (!invalRect.IsValid() || fOwner == NULL) 3187 return; 3188 3189 check_lock(); 3190 3191 fOwner->fLink->StartMessage(AS_LAYER_INVALIDATE_RECT); 3192 fOwner->fLink->Attach<BRect>(invalRect); 3193 fOwner->fLink->Flush(); 3194 } 3195 3196 3197 void 3198 BView::Invalidate(const BRegion *invalRegion) 3199 { 3200 if (invalRegion == NULL || fOwner == NULL) 3201 return; 3202 3203 check_lock(); 3204 3205 int32 count = 0; 3206 count = const_cast<BRegion*>(invalRegion)->CountRects(); 3207 3208 fOwner->fLink->StartMessage(AS_LAYER_INVALIDATE_REGION); 3209 fOwner->fLink->Attach<int32>(count); 3210 3211 for (int32 i = 0; i < count; i++) 3212 fOwner->fLink->Attach<BRect>( const_cast<BRegion *>(invalRegion)->RectAt(i)); 3213 3214 fOwner->fLink->Flush(); 3215 } 3216 3217 3218 void 3219 BView::Invalidate() 3220 { 3221 Invalidate(Bounds()); 3222 } 3223 3224 3225 void 3226 BView::InvertRect(BRect rect) 3227 { 3228 if (fOwner) { 3229 check_lock(); 3230 3231 fOwner->fLink->StartMessage(AS_LAYER_INVERT_RECT); 3232 fOwner->fLink->Attach<BRect>(rect); 3233 3234 _FlushIfNotInTransaction(); 3235 } 3236 } 3237 3238 3239 // #pragma mark - 3240 // View Hierarchy Functions 3241 3242 3243 void 3244 BView::AddChild(BView *child, BView *before) 3245 { 3246 STRACE(("BView(%s)::AddChild(child='%s' before='%s')\n", 3247 this->Name() ? this->Name(): "NULL", 3248 child && child->Name() ? child->Name(): "NULL", 3249 before && before->Name() ? before->Name(): "NULL")); 3250 3251 if (!child) 3252 return; 3253 3254 if (child->fParent != NULL) 3255 debugger("AddChild failed - the view already has a parent."); 3256 3257 bool lockedOwner = false; 3258 if (fOwner && !fOwner->IsLocked()) { 3259 fOwner->Lock(); 3260 lockedOwner = true; 3261 } 3262 3263 if (!_AddChildToList(child, before)) 3264 debugger("AddChild failed!"); 3265 3266 if (fOwner) { 3267 check_lock(); 3268 3269 child->_SetOwner(fOwner); 3270 child->_CreateSelf(); 3271 child->_Attach(); 3272 3273 if (lockedOwner) 3274 fOwner->Unlock(); 3275 } 3276 } 3277 3278 3279 bool 3280 BView::RemoveChild(BView *child) 3281 { 3282 STRACE(("BView(%s)::RemoveChild(%s)\n", Name(), child->Name())); 3283 3284 if (!child) 3285 return false; 3286 3287 return child->RemoveSelf(); 3288 } 3289 3290 3291 int32 3292 BView::CountChildren() const 3293 { 3294 check_lock_no_pick(); 3295 3296 uint32 count = 0; 3297 BView *child = fFirstChild; 3298 3299 while (child != NULL) { 3300 count++; 3301 child = child->fNextSibling; 3302 } 3303 3304 return count; 3305 } 3306 3307 3308 BView * 3309 BView::ChildAt(int32 index) const 3310 { 3311 check_lock_no_pick(); 3312 3313 BView *child = fFirstChild; 3314 while (child != NULL && index-- > 0) { 3315 child = child->fNextSibling; 3316 } 3317 3318 return child; 3319 } 3320 3321 3322 BView * 3323 BView::NextSibling() const 3324 { 3325 return fNextSibling; 3326 } 3327 3328 3329 BView * 3330 BView::PreviousSibling() const 3331 { 3332 return fPreviousSibling; 3333 } 3334 3335 3336 bool 3337 BView::RemoveSelf() 3338 { 3339 STRACE(("BView(%s)::RemoveSelf()...\n", Name())); 3340 3341 // Remove this child from its parent 3342 3343 BWindow* owner = fOwner; 3344 check_lock_no_pick(); 3345 3346 if (owner != NULL) { 3347 _UpdateStateForRemove(); 3348 _Detach(); 3349 } 3350 3351 if (!fParent || !fParent->_RemoveChildFromList(this)) 3352 return false; 3353 3354 if (owner != NULL && !fTopLevelView) { 3355 // the top level view is deleted by the app_server automatically 3356 owner->fLink->StartMessage(AS_LAYER_DELETE); 3357 owner->fLink->Attach<int32>(_get_object_token_(this)); 3358 } 3359 3360 STRACE(("DONE: BView(%s)::RemoveSelf()\n", Name())); 3361 3362 return true; 3363 } 3364 3365 3366 BView * 3367 BView::Parent() const 3368 { 3369 if (fParent && fParent->fTopLevelView) 3370 return NULL; 3371 3372 return fParent; 3373 } 3374 3375 3376 BView * 3377 BView::FindView(const char *name) const 3378 { 3379 if (name == NULL) 3380 return NULL; 3381 3382 if (Name() != NULL && !strcmp(Name(), name)) 3383 return const_cast<BView *>(this); 3384 3385 BView *child = fFirstChild; 3386 while (child != NULL) { 3387 BView *view = child->FindView(name); 3388 if (view != NULL) 3389 return view; 3390 3391 child = child->fNextSibling; 3392 } 3393 3394 return NULL; 3395 } 3396 3397 3398 void 3399 BView::MoveBy(float deltaX, float deltaY) 3400 { 3401 MoveTo(fParentOffset.x + deltaX, fParentOffset.y + deltaY); 3402 } 3403 3404 3405 void 3406 BView::MoveTo(BPoint where) 3407 { 3408 MoveTo(where.x, where.y); 3409 } 3410 3411 3412 void 3413 BView::MoveTo(float x, float y) 3414 { 3415 if (x == fParentOffset.x && y == fParentOffset.y) 3416 return; 3417 3418 // BeBook says we should do this. And it makes sense. 3419 x = roundf(x); 3420 y = roundf(y); 3421 3422 if (fOwner) { 3423 check_lock(); 3424 fOwner->fLink->StartMessage(AS_LAYER_MOVE_TO); 3425 fOwner->fLink->Attach<float>(x); 3426 fOwner->fLink->Attach<float>(y); 3427 3428 fState->valid_flags |= B_VIEW_FRAME_BIT; 3429 3430 _FlushIfNotInTransaction(); 3431 } 3432 3433 _MoveTo((int32)x, (int32)y); 3434 } 3435 3436 3437 void 3438 BView::ResizeBy(float deltaWidth, float deltaHeight) 3439 { 3440 // TODO: this doesn't look like it would work correctly with scrolled views 3441 3442 // NOTE: I think this check makes sense, but I didn't 3443 // test what R5 does. 3444 if (fBounds.right + deltaWidth < 0) 3445 deltaWidth = -fBounds.right; 3446 if (fBounds.bottom + deltaHeight < 0) 3447 deltaHeight = -fBounds.bottom; 3448 3449 // BeBook says we should do this. And it makes sense. 3450 deltaWidth = roundf(deltaWidth); 3451 deltaHeight = roundf(deltaHeight); 3452 3453 if (deltaWidth == 0 && deltaHeight == 0) 3454 return; 3455 3456 if (fOwner) { 3457 check_lock(); 3458 fOwner->fLink->StartMessage(AS_LAYER_RESIZE_TO); 3459 3460 fOwner->fLink->Attach<float>(fBounds.right + deltaWidth); 3461 fOwner->fLink->Attach<float>(fBounds.bottom + deltaHeight); 3462 3463 fState->valid_flags |= B_VIEW_FRAME_BIT; 3464 3465 _FlushIfNotInTransaction(); 3466 } 3467 3468 _ResizeBy((int32)deltaWidth, (int32)deltaHeight); 3469 } 3470 3471 3472 void 3473 BView::ResizeTo(float width, float height) 3474 { 3475 ResizeBy(width - fBounds.Width(), height - fBounds.Height()); 3476 } 3477 3478 3479 // #pragma mark - 3480 // Inherited Methods (from BHandler) 3481 3482 3483 status_t 3484 BView::GetSupportedSuites(BMessage *data) 3485 { 3486 if (data == NULL) 3487 return B_BAD_VALUE; 3488 3489 status_t status = data->AddString("Suites", "suite/vnd.Be-view"); 3490 if (status == B_OK) { 3491 BPropertyInfo propertyInfo(sViewPropInfo); 3492 3493 status = data->AddFlat("message", &propertyInfo); 3494 if (status == B_OK) 3495 status = BHandler::GetSupportedSuites(data); 3496 } 3497 return status; 3498 } 3499 3500 3501 BHandler * 3502 BView::ResolveSpecifier(BMessage *msg, int32 index, BMessage *specifier, 3503 int32 what, const char *property) 3504 { 3505 if (msg->what == B_WINDOW_MOVE_BY 3506 || msg->what == B_WINDOW_MOVE_TO) 3507 return this; 3508 3509 BPropertyInfo propertyInfo(sViewPropInfo); 3510 3511 switch (propertyInfo.FindMatch(msg, index, specifier, what, property)) { 3512 case B_ERROR: 3513 break; 3514 3515 case 0: 3516 case 1: 3517 case 2: 3518 case 3: 3519 case 5: 3520 return this; 3521 3522 case 4: 3523 if (fShelf) { 3524 msg->PopSpecifier(); 3525 return fShelf; 3526 } else { 3527 BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD); 3528 3529 replyMsg.AddInt32("error", B_NAME_NOT_FOUND); 3530 replyMsg.AddString("message", "This window doesn't have a shelf"); 3531 msg->SendReply(&replyMsg); 3532 return NULL; 3533 } 3534 break; 3535 3536 case 6: 3537 case 7: 3538 case 8: 3539 { 3540 if (fFirstChild) { 3541 BView *child; 3542 switch (msg->what) { 3543 case B_INDEX_SPECIFIER: 3544 { 3545 int32 index; 3546 msg->FindInt32("data", &index); 3547 child = ChildAt(index); 3548 break; 3549 } 3550 case B_REVERSE_INDEX_SPECIFIER: 3551 { 3552 int32 rindex; 3553 msg->FindInt32("data", &rindex); 3554 child = ChildAt(CountChildren() - rindex); 3555 break; 3556 } 3557 case B_NAME_SPECIFIER: 3558 { 3559 const char *name; 3560 msg->FindString("data", &name); 3561 child = FindView(name); 3562 break; 3563 } 3564 3565 default: 3566 child = NULL; 3567 break; 3568 } 3569 3570 if (child != NULL) { 3571 msg->PopSpecifier(); 3572 return child; 3573 } else { 3574 BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD); 3575 replyMsg.AddInt32("error", B_BAD_INDEX); 3576 replyMsg.AddString("message", "Cannot find view at/with specified index/name."); 3577 msg->SendReply(&replyMsg); 3578 return NULL; 3579 } 3580 } else { 3581 BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD); 3582 replyMsg.AddInt32("error", B_NAME_NOT_FOUND); 3583 replyMsg.AddString("message", "This window doesn't have children."); 3584 msg->SendReply(&replyMsg); 3585 return NULL; 3586 } 3587 break; 3588 } 3589 3590 default: 3591 break; 3592 } 3593 3594 return BHandler::ResolveSpecifier(msg, index, specifier, what, property); 3595 } 3596 3597 3598 void 3599 BView::MessageReceived(BMessage *msg) 3600 { 3601 BMessage specifier; 3602 int32 what; 3603 const char *prop; 3604 int32 index; 3605 status_t err; 3606 3607 if (!msg->HasSpecifiers()) { 3608 switch (msg->what) { 3609 case B_VIEW_RESIZED: 3610 // By the time the message arrives, the bounds may have 3611 // changed already, that's why we don't use the values 3612 // in the message itself. 3613 FrameResized(fBounds.Width(), fBounds.Height()); 3614 break; 3615 3616 case B_VIEW_MOVED: 3617 FrameMoved(fParentOffset); 3618 break; 3619 3620 case B_MOUSE_WHEEL_CHANGED: 3621 { 3622 float deltaX = 0.0f, deltaY = 0.0f; 3623 3624 BScrollBar *horizontal = ScrollBar(B_HORIZONTAL); 3625 if (horizontal != NULL) 3626 msg->FindFloat("be:wheel_delta_x", &deltaX); 3627 3628 BScrollBar *vertical = ScrollBar(B_VERTICAL); 3629 if (vertical != NULL) 3630 msg->FindFloat("be:wheel_delta_y", &deltaY); 3631 3632 if (deltaX == 0.0f && deltaY == 0.0f) 3633 return; 3634 3635 float smallStep, largeStep; 3636 if (horizontal != NULL) { 3637 horizontal->GetSteps(&smallStep, &largeStep); 3638 3639 // pressing the option key scrolls faster 3640 if (modifiers() & B_OPTION_KEY) 3641 deltaX *= largeStep; 3642 else 3643 deltaX *= smallStep * 3; 3644 3645 horizontal->SetValue(horizontal->Value() + deltaX); 3646 } 3647 3648 if (vertical != NULL) { 3649 vertical->GetSteps(&smallStep, &largeStep); 3650 3651 // pressing the option key scrolls faster 3652 if (modifiers() & B_OPTION_KEY) 3653 deltaY *= largeStep; 3654 else 3655 deltaY *= smallStep * 3; 3656 3657 vertical->SetValue(vertical->Value() + deltaY); 3658 } 3659 break; 3660 } 3661 3662 default: 3663 BHandler::MessageReceived(msg); 3664 break; 3665 } 3666 3667 return; 3668 } 3669 3670 err = msg->GetCurrentSpecifier(&index, &specifier, &what, &prop); 3671 if (err == B_OK) { 3672 BMessage replyMsg; 3673 3674 switch (msg->what) { 3675 case B_GET_PROPERTY: 3676 { 3677 replyMsg.what = B_NO_ERROR; 3678 replyMsg.AddInt32("error", B_OK); 3679 3680 if (strcmp(prop, "Frame") == 0) 3681 replyMsg.AddRect("result", Frame()); 3682 else if (strcmp(prop, "Hidden") == 0) 3683 replyMsg.AddBool( "result", IsHidden()); 3684 break; 3685 } 3686 3687 case B_SET_PROPERTY: 3688 { 3689 if (strcmp(prop, "Frame") == 0) { 3690 BRect newFrame; 3691 if (msg->FindRect("data", &newFrame) == B_OK) { 3692 MoveTo(newFrame.LeftTop()); 3693 ResizeTo(newFrame.right, newFrame.bottom); 3694 3695 replyMsg.what = B_NO_ERROR; 3696 replyMsg.AddInt32("error", B_OK); 3697 } else { 3698 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 3699 replyMsg.AddInt32("error", B_BAD_SCRIPT_SYNTAX); 3700 replyMsg.AddString("message", "Didn't understand the specifier(s)"); 3701 } 3702 } else if (strcmp(prop, "Hidden") == 0) { 3703 bool newHiddenState; 3704 if (msg->FindBool("data", &newHiddenState) == B_OK) { 3705 if (!IsHidden() && newHiddenState == true) { 3706 Hide(); 3707 3708 replyMsg.what = B_NO_ERROR; 3709 replyMsg.AddInt32( "error", B_OK); 3710 } 3711 else if (IsHidden() && newHiddenState == false) { 3712 Show(); 3713 3714 replyMsg.what = B_NO_ERROR; 3715 replyMsg.AddInt32("error", B_OK); 3716 } else { 3717 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 3718 replyMsg.AddInt32("error", B_BAD_SCRIPT_SYNTAX); 3719 replyMsg.AddString("message", "Didn't understand the specifier(s)"); 3720 } 3721 } else { 3722 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 3723 replyMsg.AddInt32("error", B_BAD_SCRIPT_SYNTAX); 3724 replyMsg.AddString("message", "Didn't understand the specifier(s)"); 3725 } 3726 } 3727 break; 3728 } 3729 3730 case B_COUNT_PROPERTIES: 3731 if (strcmp(prop, "View") == 0) { 3732 replyMsg.what = B_NO_ERROR; 3733 replyMsg.AddInt32("error", B_OK); 3734 replyMsg.AddInt32("result", CountChildren()); 3735 } 3736 break; 3737 } 3738 3739 msg->SendReply(&replyMsg); 3740 } else { 3741 BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD); 3742 replyMsg.AddInt32("error" , B_BAD_SCRIPT_SYNTAX); 3743 replyMsg.AddString("message", "Didn't understand the specifier(s)"); 3744 3745 msg->SendReply(&replyMsg); 3746 } 3747 } 3748 3749 3750 status_t 3751 BView::Perform(perform_code d, void* arg) 3752 { 3753 return B_BAD_VALUE; 3754 } 3755 3756 3757 // #pragma mark - 3758 // Private Functions 3759 3760 3761 void 3762 BView::_InitData(BRect frame, const char *name, uint32 resizingMode, uint32 flags) 3763 { 3764 // Info: The name of the view is set by BHandler constructor 3765 3766 STRACE(("BView::InitData: enter\n")); 3767 3768 // initialize members 3769 fFlags = (resizingMode & _RESIZE_MASK_) | (flags & ~_RESIZE_MASK_); 3770 3771 // handle rounding 3772 frame.left = roundf(frame.left); 3773 frame.top = roundf(frame.top); 3774 frame.right = roundf(frame.right); 3775 frame.bottom = roundf(frame.bottom); 3776 3777 fParentOffset.Set(frame.left, frame.top); 3778 3779 fOwner = NULL; 3780 fParent = NULL; 3781 fNextSibling = NULL; 3782 fPreviousSibling = NULL; 3783 fFirstChild = NULL; 3784 3785 fShowLevel = 0; 3786 fTopLevelView = false; 3787 3788 cpicture = NULL; 3789 comm = NULL; 3790 3791 fVerScroller = NULL; 3792 fHorScroller = NULL; 3793 3794 f_is_printing = false; 3795 fAttached = false; 3796 3797 fState = new BPrivate::ViewState; 3798 3799 fBounds = frame.OffsetToCopy(B_ORIGIN); 3800 fShelf = NULL; 3801 3802 fEventMask = 0; 3803 fEventOptions = 0; 3804 } 3805 3806 3807 void 3808 BView::removeCommArray() 3809 { 3810 if (comm) { 3811 delete [] comm->array; 3812 delete comm; 3813 comm = NULL; 3814 } 3815 } 3816 3817 3818 void 3819 BView::_SetOwner(BWindow *newOwner) 3820 { 3821 if (!newOwner) 3822 removeCommArray(); 3823 3824 if (fOwner != newOwner && fOwner) { 3825 if (fOwner->fFocus == this) 3826 MakeFocus(false); 3827 3828 if (fOwner->fLastMouseMovedView == this) 3829 fOwner->fLastMouseMovedView = NULL; 3830 3831 fOwner->RemoveHandler(this); 3832 if (fShelf) 3833 fOwner->RemoveHandler(fShelf); 3834 } 3835 3836 if (newOwner && newOwner != fOwner) { 3837 newOwner->AddHandler(this); 3838 if (fShelf) 3839 newOwner->AddHandler(fShelf); 3840 3841 if (fTopLevelView) 3842 SetNextHandler(newOwner); 3843 else 3844 SetNextHandler(fParent); 3845 } 3846 3847 fOwner = newOwner; 3848 3849 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) 3850 child->_SetOwner(newOwner); 3851 } 3852 3853 3854 void 3855 BView::DoPictureClip(BPicture *picture, BPoint where, 3856 bool invert, bool sync) 3857 { 3858 if (!picture) 3859 return; 3860 3861 if (do_owner_check()) { 3862 fOwner->fLink->StartMessage(AS_LAYER_CLIP_TO_PICTURE); 3863 fOwner->fLink->Attach<int32>(picture->token); 3864 fOwner->fLink->Attach<BPoint>(where); 3865 fOwner->fLink->Attach<bool>(invert); 3866 3867 // TODO: I think that "sync" means another thing here: 3868 // the bebook, at least, says so. 3869 if (sync) 3870 fOwner->fLink->Flush(); 3871 3872 fState->valid_flags &= ~B_VIEW_CLIP_REGION_BIT; 3873 } 3874 3875 fState->archiving_flags |= B_VIEW_CLIP_REGION_BIT; 3876 } 3877 3878 3879 bool 3880 BView::_RemoveChildFromList(BView* child) 3881 { 3882 if (child->fParent != this) 3883 return false; 3884 3885 if (fFirstChild == child) { 3886 // it's the first view in the list 3887 fFirstChild = child->fNextSibling; 3888 } else { 3889 // there must be a previous sibling 3890 child->fPreviousSibling->fNextSibling = child->fNextSibling; 3891 } 3892 3893 if (child->fNextSibling) 3894 child->fNextSibling->fPreviousSibling = child->fPreviousSibling; 3895 3896 child->fParent = NULL; 3897 child->fNextSibling = NULL; 3898 child->fPreviousSibling = NULL; 3899 3900 return true; 3901 } 3902 3903 3904 bool 3905 BView::_AddChildToList(BView* child, BView* before) 3906 { 3907 if (!child) 3908 return false; 3909 if (child->fParent != NULL) { 3910 debugger("View already belongs to someone else"); 3911 return false; 3912 } 3913 if (before != NULL && before->fParent != this) { 3914 debugger("Invalid before view"); 3915 return false; 3916 } 3917 3918 if (before != NULL) { 3919 // add view before this one 3920 child->fNextSibling = before; 3921 child->fPreviousSibling = before->fPreviousSibling; 3922 if (child->fPreviousSibling != NULL) 3923 child->fPreviousSibling->fNextSibling = child; 3924 3925 before->fPreviousSibling = child; 3926 if (fFirstChild == before) 3927 fFirstChild = child; 3928 } else { 3929 // add view to the end of the list 3930 BView *last = fFirstChild; 3931 while (last != NULL && last->fNextSibling != NULL) { 3932 last = last->fNextSibling; 3933 } 3934 3935 if (last != NULL) { 3936 last->fNextSibling = child; 3937 child->fPreviousSibling = last; 3938 } else { 3939 fFirstChild = child; 3940 child->fPreviousSibling = NULL; 3941 } 3942 3943 child->fNextSibling = NULL; 3944 } 3945 3946 child->fParent = this; 3947 return true; 3948 } 3949 3950 3951 /*! \brief Creates the server counterpart of this view. 3952 This is only done for views that are part of the view hierarchy, ie. when 3953 they are attached to a window. 3954 RemoveSelf() deletes the server object again. 3955 */ 3956 bool 3957 BView::_CreateSelf() 3958 { 3959 // AS_LAYER_CREATE & AS_LAYER_CREATE_ROOT do not use the 3960 // current view mechanism via check_lock() - the token 3961 // of the view and its parent are both send to the server. 3962 3963 if (fTopLevelView) 3964 fOwner->fLink->StartMessage(AS_LAYER_CREATE_ROOT); 3965 else 3966 fOwner->fLink->StartMessage(AS_LAYER_CREATE); 3967 3968 fOwner->fLink->Attach<int32>(_get_object_token_(this)); 3969 fOwner->fLink->AttachString(Name()); 3970 fOwner->fLink->Attach<BRect>(Frame()); 3971 fOwner->fLink->Attach<BPoint>(LeftTop()); 3972 fOwner->fLink->Attach<uint32>(ResizingMode()); 3973 fOwner->fLink->Attach<uint32>(fEventMask); 3974 fOwner->fLink->Attach<uint32>(fEventOptions); 3975 fOwner->fLink->Attach<uint32>(Flags()); 3976 fOwner->fLink->Attach<bool>(IsHidden(this)); 3977 fOwner->fLink->Attach<rgb_color>(fState->view_color); 3978 if (fTopLevelView) 3979 fOwner->fLink->Attach<int32>(B_NULL_TOKEN); 3980 else 3981 fOwner->fLink->Attach<int32>(_get_object_token_(fParent)); 3982 fOwner->fLink->Flush(); 3983 3984 do_owner_check(); 3985 fState->UpdateServerState(*fOwner->fLink); 3986 3987 // we create all its children, too 3988 3989 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 3990 child->_CreateSelf(); 3991 } 3992 3993 fOwner->fLink->Flush(); 3994 return true; 3995 } 3996 3997 3998 /*! 3999 Sets the new view position. 4000 It doesn't contact the server, though - the only case where this 4001 is called outside of MoveTo() is as reaction of moving a view 4002 in the server (a.k.a. B_WINDOW_RESIZED). 4003 It also calls the BView's FrameMoved() hook. 4004 */ 4005 void 4006 BView::_MoveTo(int32 x, int32 y) 4007 { 4008 fParentOffset.Set(x, y); 4009 4010 if (Window() != NULL && fFlags & B_FRAME_EVENTS) { 4011 BMessage moved(B_VIEW_MOVED); 4012 moved.AddInt64("when", system_time()); 4013 moved.AddPoint("where", BPoint(x, y)); 4014 4015 BMessenger target(this); 4016 target.SendMessage(&moved); 4017 } 4018 } 4019 4020 4021 /*! 4022 Computes the actual new frame size and recalculates the size of 4023 the children as well. 4024 It doesn't contact the server, though - the only case where this 4025 is called outside of ResizeBy() is as reaction of resizing a view 4026 in the server (a.k.a. B_WINDOW_RESIZED). 4027 It also calls the BView's FrameResized() hook. 4028 */ 4029 void 4030 BView::_ResizeBy(int32 deltaWidth, int32 deltaHeight) 4031 { 4032 fBounds.right += deltaWidth; 4033 fBounds.bottom += deltaHeight; 4034 4035 if (Window() == NULL) { 4036 // we're not supposed to exercise the resizing code in case 4037 // we haven't been attached to a window yet 4038 return; 4039 } 4040 4041 // layout the children 4042 for (BView* child = fFirstChild; child; child = child->fNextSibling) 4043 child->_ParentResizedBy(deltaWidth, deltaHeight); 4044 4045 if (fFlags & B_FRAME_EVENTS) { 4046 BMessage resized(B_VIEW_RESIZED); 4047 resized.AddInt64("when", system_time()); 4048 resized.AddFloat("width", fBounds.Width()); 4049 resized.AddFloat("height", fBounds.Height()); 4050 4051 BMessenger target(this); 4052 target.SendMessage(&resized); 4053 } 4054 } 4055 4056 4057 /*! 4058 Relayouts the view according to its resizing mode. 4059 */ 4060 void 4061 BView::_ParentResizedBy(int32 x, int32 y) 4062 { 4063 uint32 resizingMode = fFlags & _RESIZE_MASK_; 4064 BRect newFrame = Frame(); 4065 4066 // follow with left side 4067 if ((resizingMode & 0x0F00U) == _VIEW_RIGHT_ << 8) 4068 newFrame.left += x; 4069 else if ((resizingMode & 0x0F00U) == _VIEW_CENTER_ << 8) 4070 newFrame.left += x / 2; 4071 4072 // follow with right side 4073 if ((resizingMode & 0x000FU) == _VIEW_RIGHT_) 4074 newFrame.right += x; 4075 else if ((resizingMode & 0x000FU) == _VIEW_CENTER_) 4076 newFrame.right += x / 2; 4077 4078 // follow with top side 4079 if ((resizingMode & 0xF000U) == _VIEW_BOTTOM_ << 12) 4080 newFrame.top += y; 4081 else if ((resizingMode & 0xF000U) == _VIEW_CENTER_ << 12) 4082 newFrame.top += y / 2; 4083 4084 // follow with bottom side 4085 if ((resizingMode & 0x00F0U) == _VIEW_BOTTOM_ << 4) 4086 newFrame.bottom += y; 4087 else if ((resizingMode & 0x00F0U) == _VIEW_CENTER_ << 4) 4088 newFrame.bottom += y / 2; 4089 4090 if (newFrame.LeftTop() != fParentOffset) { 4091 // move view 4092 _MoveTo((int32)roundf(newFrame.left), (int32)roundf(newFrame.top)); 4093 } 4094 4095 if (newFrame != Frame()) { 4096 // resize view 4097 int32 widthDiff = (int32)(newFrame.Width() - fBounds.Width()); 4098 int32 heightDiff = (int32)(newFrame.Height() - fBounds.Height()); 4099 _ResizeBy(widthDiff, heightDiff); 4100 } 4101 } 4102 4103 4104 void 4105 BView::_Activate(bool active) 4106 { 4107 WindowActivated(active); 4108 4109 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 4110 child->_Activate(active); 4111 } 4112 } 4113 4114 4115 void 4116 BView::_Attach() 4117 { 4118 AttachedToWindow(); 4119 fAttached = true; 4120 4121 // after giving the view a chance to do this itself, 4122 // check for the B_PULSE_NEEDED flag and make sure the 4123 // window set's up the pulse messaging 4124 if (fOwner) { 4125 if (fFlags & B_PULSE_NEEDED) { 4126 check_lock_no_pick(); 4127 if (fOwner->fPulseRunner == NULL) 4128 fOwner->SetPulseRate(500000); 4129 } 4130 4131 if (!fOwner->IsHidden()) 4132 Invalidate(); 4133 } 4134 4135 for (BView* child = fFirstChild; child != NULL; child = child->fNextSibling) { 4136 // we need to check for fAttached as new views could have been 4137 // added in AttachedToWindow() - and those are already attached 4138 if (!child->fAttached) 4139 child->_Attach(); 4140 } 4141 4142 AllAttached(); 4143 } 4144 4145 4146 void 4147 BView::_Detach() 4148 { 4149 DetachedFromWindow(); 4150 fAttached = false; 4151 4152 for (BView* child = fFirstChild; child != NULL; child = child->fNextSibling) { 4153 child->_Detach(); 4154 } 4155 4156 AllDetached(); 4157 4158 if (fOwner) { 4159 check_lock_no_pick(); 4160 4161 if (!fOwner->IsHidden()) 4162 Invalidate(); 4163 4164 // make sure our owner doesn't need us anymore 4165 4166 if (fOwner->CurrentFocus() == this) 4167 MakeFocus(false); 4168 4169 if (fOwner->fDefaultButton == this) 4170 fOwner->SetDefaultButton(NULL); 4171 4172 if (fOwner->fKeyMenuBar == this) 4173 fOwner->fKeyMenuBar = NULL; 4174 4175 if (fOwner->fLastMouseMovedView == this) 4176 fOwner->fLastMouseMovedView = NULL; 4177 4178 if (fOwner->fLastViewToken == _get_object_token_(this)) 4179 fOwner->fLastViewToken = B_NULL_TOKEN; 4180 4181 _SetOwner(NULL); 4182 } 4183 } 4184 4185 4186 void 4187 BView::_Draw(BRect updateRectScreen) 4188 { 4189 if (IsHidden(this)) 4190 return; 4191 4192 check_lock(); 4193 4194 ConvertFromScreen(&updateRectScreen); 4195 BRect updateRect = Bounds() & updateRectScreen; 4196 4197 if (Flags() & B_WILL_DRAW) { 4198 // TODO: make states robust 4199 PushState(); 4200 Draw(updateRect); 4201 PopState(); 4202 Flush(); 4203 // } else { 4204 // ViewColor() == B_TRANSPARENT_COLOR and no B_WILL_DRAW 4205 // -> View is simply not drawn at all 4206 } 4207 4208 // for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 4209 // BRect rect = child->Frame(); 4210 // if (!updateRect.Intersects(rect)) 4211 // continue; 4212 // 4213 // // get new update rect in child coordinates 4214 // rect = updateRect & rect; 4215 // child->ConvertFromParent(&rect); 4216 // 4217 // child->_Draw(rect); 4218 // } 4219 // 4220 // if (Flags() & B_DRAW_ON_CHILDREN) { 4221 // // TODO: Since we have hard clipping in the app_server, 4222 // // a view can never draw "on top of it's child views" as 4223 // // the BeBook describes. 4224 // // (TODO: Test if this is really possible in BeOS.) 4225 // PushState(); 4226 // DrawAfterChildren(updateRect); 4227 // PopState(); 4228 // Flush(); 4229 // } 4230 } 4231 4232 4233 void 4234 BView::_Pulse() 4235 { 4236 if (Flags() & B_PULSE_NEEDED) 4237 Pulse(); 4238 4239 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 4240 child->_Pulse(); 4241 } 4242 } 4243 4244 4245 void 4246 BView::_UpdateStateForRemove() 4247 { 4248 if (!do_owner_check()) 4249 return; 4250 4251 fState->UpdateFrom(*fOwner->fLink); 4252 if (!fState->IsValid(B_VIEW_FRAME_BIT)) { 4253 fOwner->fLink->StartMessage(AS_LAYER_GET_COORD); 4254 4255 status_t code; 4256 if (fOwner->fLink->FlushWithReply(code) == B_OK 4257 && code == B_OK) { 4258 fOwner->fLink->Read<BPoint>(&fParentOffset); 4259 fOwner->fLink->Read<BRect>(&fBounds); 4260 fState->valid_flags |= B_VIEW_FRAME_BIT; 4261 } 4262 } 4263 4264 // update children as well 4265 4266 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 4267 if (child->fOwner) 4268 child->_UpdateStateForRemove(); 4269 } 4270 } 4271 4272 4273 inline void 4274 BView::_UpdatePattern(::pattern pattern) 4275 { 4276 if (fState->IsValid(B_VIEW_PATTERN_BIT) && pattern == fState->pattern) 4277 return; 4278 4279 if (fOwner) { 4280 check_lock(); 4281 4282 fOwner->fLink->StartMessage(AS_LAYER_SET_PATTERN); 4283 fOwner->fLink->Attach< ::pattern>(pattern); 4284 4285 fState->valid_flags |= B_VIEW_PATTERN_BIT; 4286 } 4287 4288 fState->pattern = pattern; 4289 } 4290 4291 4292 void 4293 BView::_FlushIfNotInTransaction() 4294 { 4295 if (!fOwner->fInTransaction) { 4296 fOwner->Flush(); 4297 } 4298 } 4299 4300 4301 BShelf * 4302 BView::_Shelf() const 4303 { 4304 return fShelf; 4305 } 4306 4307 4308 void 4309 BView::_SetShelf(BShelf *shelf) 4310 { 4311 if (fShelf != NULL && fOwner != NULL) 4312 fOwner->RemoveHandler(fShelf); 4313 4314 fShelf = shelf; 4315 4316 if (fShelf != NULL && fOwner != NULL) 4317 fOwner->AddHandler(fShelf); 4318 } 4319 4320 4321 status_t 4322 BView::_SetViewBitmap(const BBitmap* bitmap, BRect srcRect, 4323 BRect dstRect, uint32 followFlags, uint32 options) 4324 { 4325 if (!do_owner_check()) 4326 return B_ERROR; 4327 4328 int32 serverToken = bitmap ? bitmap->_ServerToken() : -1; 4329 4330 fOwner->fLink->StartMessage(AS_LAYER_SET_VIEW_BITMAP); 4331 fOwner->fLink->Attach<int32>(serverToken); 4332 fOwner->fLink->Attach<BRect>(srcRect); 4333 fOwner->fLink->Attach<BRect>(dstRect); 4334 fOwner->fLink->Attach<int32>(followFlags); 4335 fOwner->fLink->Attach<int32>(options); 4336 4337 status_t status = B_ERROR; 4338 fOwner->fLink->FlushWithReply(status); 4339 4340 return status; 4341 } 4342 4343 4344 bool 4345 BView::do_owner_check() const 4346 { 4347 STRACE(("BView(%s)::do_owner_check()...", Name())); 4348 4349 int32 serverToken = _get_object_token_(this); 4350 4351 if (fOwner == NULL) { 4352 debugger("View method requires owner and doesn't have one."); 4353 return false; 4354 } 4355 4356 fOwner->check_lock(); 4357 4358 if (fOwner->fLastViewToken != serverToken) { 4359 STRACE(("contacting app_server... sending token: %ld\n", serverToken)); 4360 fOwner->fLink->StartMessage(AS_SET_CURRENT_LAYER); 4361 fOwner->fLink->Attach<int32>(serverToken); 4362 4363 fOwner->fLastViewToken = serverToken; 4364 } else 4365 STRACE(("this is the lastViewToken\n")); 4366 4367 return true; 4368 } 4369 4370 4371 void 4372 BView::check_lock() const 4373 { 4374 STRACE(("BView(%s)::check_lock()...", Name() ? Name(): "NULL")); 4375 4376 if (!fOwner) 4377 return; 4378 4379 fOwner->check_lock(); 4380 4381 int32 serverToken = _get_object_token_(this); 4382 4383 if (fOwner->fLastViewToken != serverToken) { 4384 STRACE(("contacting app_server... sending token: %ld\n", serverToken)); 4385 fOwner->fLink->StartMessage(AS_SET_CURRENT_LAYER); 4386 fOwner->fLink->Attach<int32>(serverToken); 4387 4388 fOwner->fLastViewToken = serverToken; 4389 } else { 4390 STRACE(("quiet2\n")); 4391 } 4392 } 4393 4394 4395 void 4396 BView::check_lock_no_pick() const 4397 { 4398 if (fOwner) 4399 fOwner->check_lock(); 4400 } 4401 4402 4403 bool 4404 BView::do_owner_check_no_pick() const 4405 { 4406 if (fOwner) { 4407 fOwner->check_lock(); 4408 return true; 4409 } else { 4410 debugger("View method requires owner and doesn't have one."); 4411 return false; 4412 } 4413 } 4414 4415 4416 void BView::_ReservedView2(){} 4417 void BView::_ReservedView3(){} 4418 void BView::_ReservedView4(){} 4419 void BView::_ReservedView5(){} 4420 void BView::_ReservedView6(){} 4421 void BView::_ReservedView7(){} 4422 void BView::_ReservedView8(){} 4423 void BView::_ReservedView9(){} 4424 void BView::_ReservedView10(){} 4425 void BView::_ReservedView11(){} 4426 void BView::_ReservedView12(){} 4427 void BView::_ReservedView13(){} 4428 void BView::_ReservedView14(){} 4429 void BView::_ReservedView15(){} 4430 void BView::_ReservedView16(){} 4431 4432 4433 BView::BView(const BView &other) 4434 : BHandler() 4435 { 4436 // this is private and not functional, but exported 4437 } 4438 4439 4440 BView & 4441 BView::operator=(const BView &other) 4442 { 4443 // this is private and not functional, but exported 4444 return *this; 4445 } 4446 4447 4448 void 4449 BView::PrintToStream() 4450 { 4451 printf("BView::PrintToStream()\n"); 4452 printf("\tName: %s\ 4453 \tParent: %s\ 4454 \tFirstChild: %s\ 4455 \tNextSibling: %s\ 4456 \tPrevSibling: %s\ 4457 \tOwner(Window): %s\ 4458 \tToken: %ld\ 4459 \tFlags: %ld\ 4460 \tView origin: (%f,%f)\ 4461 \tView Bounds rectangle: (%f,%f,%f,%f)\ 4462 \tShow level: %d\ 4463 \tTopView?: %s\ 4464 \tBPicture: %s\ 4465 \tVertical Scrollbar %s\ 4466 \tHorizontal Scrollbar %s\ 4467 \tIs Printing?: %s\ 4468 \tShelf?: %s\ 4469 \tEventMask: %ld\ 4470 \tEventOptions: %ld\n", 4471 Name(), 4472 fParent ? fParent->Name() : "NULL", 4473 fFirstChild ? fFirstChild->Name() : "NULL", 4474 fNextSibling ? fNextSibling->Name() : "NULL", 4475 fPreviousSibling ? fPreviousSibling->Name() : "NULL", 4476 fOwner ? fOwner->Name() : "NULL", 4477 _get_object_token_(this), 4478 fFlags, 4479 fParentOffset.x, fParentOffset.y, 4480 fBounds.left, fBounds.top, fBounds.right, fBounds.bottom, 4481 fShowLevel, 4482 fTopLevelView ? "YES" : "NO", 4483 cpicture? "YES" : "NULL", 4484 fVerScroller? "YES" : "NULL", 4485 fHorScroller? "YES" : "NULL", 4486 f_is_printing? "YES" : "NO", 4487 fShelf? "YES" : "NO", 4488 fEventMask, 4489 fEventOptions); 4490 4491 printf("\tState status:\ 4492 \t\tLocalCoordianteSystem: (%f,%f)\ 4493 \t\tPenLocation: (%f,%f)\ 4494 \t\tPenSize: %f\ 4495 \t\tHighColor: [%d,%d,%d,%d]\ 4496 \t\tLowColor: [%d,%d,%d,%d]\ 4497 \t\tViewColor: [%d,%d,%d,%d]\ 4498 \t\tPattern: %llx\ 4499 \t\tDrawingMode: %d\ 4500 \t\tLineJoinMode: %d\ 4501 \t\tLineCapMode: %d\ 4502 \t\tMiterLimit: %f\ 4503 \t\tAlphaSource: %d\ 4504 \t\tAlphaFuntion: %d\ 4505 \t\tScale: %f\ 4506 \t\t(Print)FontAliasing: %s\ 4507 \t\tFont Info:\n", 4508 fState->origin.x, fState->origin.y, 4509 fState->pen_location.x, fState->pen_location.y, 4510 fState->pen_size, 4511 fState->high_color.red, fState->high_color.blue, fState->high_color.green, fState->high_color.alpha, 4512 fState->low_color.red, fState->low_color.blue, fState->low_color.green, fState->low_color.alpha, 4513 fState->view_color.red, fState->view_color.blue, fState->view_color.green, fState->view_color.alpha, 4514 *((uint64*)&(fState->pattern)), 4515 fState->drawing_mode, 4516 fState->line_join, 4517 fState->line_cap, 4518 fState->miter_limit, 4519 fState->alpha_source_mode, 4520 fState->alpha_function_mode, 4521 fState->scale, 4522 fState->font_aliasing? "YES" : "NO"); 4523 4524 fState->font.PrintToStream(); 4525 4526 // TODO: also print the line array. 4527 } 4528 4529 4530 void 4531 BView::PrintTree() 4532 { 4533 int32 spaces = 2; 4534 BView *c = fFirstChild; //c = short for: current 4535 printf( "'%s'\n", Name() ); 4536 if (c != NULL) { 4537 while(true) { 4538 // action block 4539 { 4540 for (int i = 0; i < spaces; i++) 4541 printf(" "); 4542 4543 printf( "'%s'\n", c->Name() ); 4544 } 4545 4546 // go deep 4547 if (c->fFirstChild) { 4548 c = c->fFirstChild; 4549 spaces += 2; 4550 } else { 4551 // go right 4552 if (c->fNextSibling) { 4553 c = c->fNextSibling; 4554 } else { 4555 // go up 4556 while (!c->fParent->fNextSibling && c->fParent != this) { 4557 c = c->fParent; 4558 spaces -= 2; 4559 } 4560 4561 // that enough! We've reached this view. 4562 if (c->fParent == this) 4563 break; 4564 4565 c = c->fParent->fNextSibling; 4566 spaces -= 2; 4567 } 4568 } 4569 } 4570 } 4571 } 4572 4573 4574 /* TODO: 4575 -implement SetDiskMode(). What's with this method? What does it do? test! 4576 does it has something to do with DrawPictureAsync( filename* .. )? 4577 -implement DrawAfterChildren() 4578 */ 4579