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