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