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 STRACE(("\tHOOK: BView(%s)::DrawAfterChildren()\n", Name())); 1136 } 1137 1138 1139 void 1140 BView::FrameMoved(BPoint newPosition) 1141 { 1142 // Hook function 1143 STRACE(("\tHOOK: BView(%s)::FrameMoved()\n", Name())); 1144 } 1145 1146 1147 void 1148 BView::FrameResized(float newWidth, float newHeight) 1149 { 1150 // Hook function 1151 STRACE(("\tHOOK: BView(%s)::FrameResized()\n", Name())); 1152 } 1153 1154 1155 void 1156 BView::GetPreferredSize(float* _width, float* _height) 1157 { 1158 STRACE(("\tHOOK: BView(%s)::GetPreferredSize()\n", Name())); 1159 1160 *_width = fBounds.Width(); 1161 *_height = fBounds.Height(); 1162 } 1163 1164 1165 void 1166 BView::ResizeToPreferred() 1167 { 1168 STRACE(("\tHOOK: BView(%s)::ResizeToPreferred()\n", Name())); 1169 1170 float width; 1171 float height; 1172 GetPreferredSize(&width, &height); 1173 1174 ResizeTo(width, height); 1175 } 1176 1177 1178 void 1179 BView::KeyDown(const char* bytes, int32 numBytes) 1180 { 1181 // Hook function 1182 STRACE(("\tHOOK: BView(%s)::KeyDown()\n", Name())); 1183 1184 if (Window()) 1185 Window()->_KeyboardNavigation(); 1186 } 1187 1188 1189 void 1190 BView::KeyUp(const char* bytes, int32 numBytes) 1191 { 1192 // Hook function 1193 STRACE(("\tHOOK: BView(%s)::KeyUp()\n", Name())); 1194 } 1195 1196 1197 void 1198 BView::MouseDown(BPoint where) 1199 { 1200 // Hook function 1201 STRACE(("\tHOOK: BView(%s)::MouseDown()\n", Name())); 1202 } 1203 1204 1205 void 1206 BView::MouseUp(BPoint where) 1207 { 1208 // Hook function 1209 STRACE(("\tHOOK: BView(%s)::MouseUp()\n", Name())); 1210 } 1211 1212 1213 void 1214 BView::MouseMoved(BPoint where, uint32 code, const BMessage* a_message) 1215 { 1216 // Hook function 1217 STRACE(("\tHOOK: BView(%s)::MouseMoved()\n", Name())); 1218 } 1219 1220 1221 void 1222 BView::Pulse() 1223 { 1224 // Hook function 1225 STRACE(("\tHOOK: BView(%s)::Pulse()\n", Name())); 1226 } 1227 1228 1229 void 1230 BView::TargetedByScrollView(BScrollView* scroll_view) 1231 { 1232 // Hook function 1233 STRACE(("\tHOOK: BView(%s)::TargetedByScrollView()\n", Name())); 1234 } 1235 1236 1237 void 1238 BView::WindowActivated(bool state) 1239 { 1240 // Hook function 1241 STRACE(("\tHOOK: BView(%s)::WindowActivated()\n", Name())); 1242 } 1243 1244 1245 // #pragma mark - 1246 // Input Functions 1247 1248 1249 void 1250 BView::BeginRectTracking(BRect startRect, uint32 style) 1251 { 1252 if (do_owner_check()) { 1253 fOwner->fLink->StartMessage(AS_LAYER_BEGIN_RECT_TRACK); 1254 fOwner->fLink->Attach<BRect>(startRect); 1255 fOwner->fLink->Attach<int32>(style); 1256 } 1257 } 1258 1259 1260 void 1261 BView::EndRectTracking() 1262 { 1263 if (do_owner_check()) 1264 fOwner->fLink->StartMessage(AS_LAYER_END_RECT_TRACK); 1265 } 1266 1267 1268 void 1269 BView::DragMessage(BMessage *message, BRect dragRect, BHandler *replyTo) 1270 { 1271 if (!message) 1272 return; 1273 1274 do_owner_check_no_pick(); 1275 1276 // calculate the offset 1277 BPoint offset; 1278 uint32 buttons; 1279 BMessage *current = fOwner->CurrentMessage(); 1280 if (!current || current->FindPoint("be:view_where", &offset) != B_OK) 1281 GetMouse(&offset, &buttons, false); 1282 offset -= dragRect.LeftTop(); 1283 1284 if (!dragRect.IsValid()) { 1285 DragMessage(message, NULL, B_OP_BLEND, offset, replyTo); 1286 return; 1287 } 1288 1289 // TODO: that's not really what should happen - the app_server should take the chance 1290 // *NOT* to need to drag a whole bitmap around but just a frame. 1291 1292 // create a drag bitmap for the rect 1293 BBitmap *bitmap = new BBitmap(dragRect, B_RGBA32); 1294 uint32 *bits = (uint32*)bitmap->Bits(); 1295 uint32 bytesPerRow = bitmap->BytesPerRow(); 1296 uint32 width = dragRect.IntegerWidth() + 1; 1297 uint32 height = dragRect.IntegerHeight() + 1; 1298 uint32 lastRow = (height - 1) * width; 1299 1300 memset(bits, 0x00, height * bytesPerRow); 1301 1302 // top 1303 for (uint32 i = 0; i < width; i += 2) 1304 bits[i] = 0xff000000; 1305 1306 // bottom 1307 for (uint32 i = (height % 2 == 0 ? 1 : 0); i < width; i += 2) 1308 bits[lastRow + i] = 0xff000000; 1309 1310 // left 1311 for (uint32 i = 0; i < lastRow; i += width * 2) 1312 bits[i] = 0xff000000; 1313 1314 // right 1315 for (uint32 i = (width % 2 == 0 ? width : 0); i < lastRow; i += width * 2) 1316 bits[width - 1 + i] = 0xff000000; 1317 1318 DragMessage(message, bitmap, B_OP_BLEND, offset, replyTo); 1319 } 1320 1321 1322 void 1323 BView::DragMessage(BMessage *message, BBitmap *image, BPoint offset, 1324 BHandler *replyTo) 1325 { 1326 DragMessage(message, image, B_OP_COPY, offset, replyTo); 1327 } 1328 1329 1330 void 1331 BView::DragMessage(BMessage *message, BBitmap *image, 1332 drawing_mode dragMode, BPoint offset, BHandler *replyTo) 1333 { 1334 if (message == NULL) 1335 return; 1336 1337 if (image == NULL) { 1338 // TODO: workaround for drags without a bitmap - should not be necessary if 1339 // we move the rectangle dragging into the app_server 1340 image = new (nothrow) BBitmap(BRect(0, 0, 0, 0), B_RGBA32); 1341 if (image == NULL) 1342 return; 1343 } 1344 1345 if (replyTo == NULL) 1346 replyTo = this; 1347 1348 if (replyTo->Looper() == NULL) 1349 debugger("DragMessage: warning - the Handler needs a looper"); 1350 1351 do_owner_check_no_pick(); 1352 1353 if (!message->HasInt32("buttons")) { 1354 BMessage *msg = fOwner->CurrentMessage(); 1355 uint32 buttons; 1356 1357 if (msg == NULL || msg->FindInt32("buttons", (int32 *)&buttons) != B_OK) { 1358 BPoint point; 1359 GetMouse(&point, &buttons, false); 1360 } 1361 1362 message->AddInt32("buttons", buttons); 1363 } 1364 1365 BMessage::Private privateMessage(message); 1366 privateMessage.SetReply(BMessenger(replyTo, replyTo->Looper())); 1367 1368 // TODO: create area and flatten message into that area! 1369 // send area info over port, not the actual message! 1370 int32 bufferSize = privateMessage.NativeFlattenedSize(); 1371 char* buffer = new (nothrow) char[bufferSize]; 1372 if (buffer) { 1373 privateMessage.NativeFlatten(buffer, bufferSize); 1374 1375 fOwner->fLink->StartMessage(AS_LAYER_DRAG_IMAGE); 1376 fOwner->fLink->Attach<int32>(image->_ServerToken()); 1377 fOwner->fLink->Attach<int32>((int32)dragMode); 1378 fOwner->fLink->Attach<BPoint>(offset); 1379 fOwner->fLink->Attach<int32>(bufferSize); 1380 fOwner->fLink->Attach(buffer, bufferSize); 1381 1382 // we need to wait for the server 1383 // to actually process this message 1384 // before we can delete the bitmap 1385 int32 code; 1386 fOwner->fLink->FlushWithReply(code); 1387 1388 delete [] buffer; 1389 } else { 1390 fprintf(stderr, "BView::DragMessage() - no memory to flatten drag message\n"); 1391 } 1392 1393 delete image; 1394 } 1395 1396 1397 void 1398 BView::GetMouse(BPoint *location, uint32 *buttons, bool checkMessageQueue) 1399 { 1400 do_owner_check(); 1401 1402 if (checkMessageQueue) { 1403 Window()->UpdateIfNeeded(); 1404 BMessageQueue *queue = Window()->MessageQueue(); 1405 queue->Lock(); 1406 1407 // Look out for mouse update messages 1408 1409 BMessage *message; 1410 for (int32 i = 0; (message = queue->FindMessage(i)) != NULL; i++) { 1411 switch (message->what) { 1412 case B_MOUSE_MOVED: 1413 case B_MOUSE_UP: 1414 case B_MOUSE_DOWN: 1415 bool deleteMessage; 1416 if (!Window()->_StealMouseMessage(message, deleteMessage)) 1417 continue; 1418 1419 message->FindPoint("screen_where", location); 1420 message->FindInt32("buttons", (int32 *)buttons); 1421 queue->Unlock(); 1422 // we need to hold the queue lock until here, because 1423 // the message might still be used for something else 1424 1425 ConvertFromScreen(location); 1426 1427 if (deleteMessage) 1428 delete message; 1429 1430 return; 1431 } 1432 } 1433 queue->Unlock(); 1434 } 1435 1436 // If no mouse update message has been found in the message queue, 1437 // we get the current mouse location and buttons from the app_server 1438 1439 fOwner->fLink->StartMessage(AS_GET_MOUSE); 1440 1441 int32 code; 1442 if (fOwner->fLink->FlushWithReply(code) == B_OK 1443 && code == B_OK) { 1444 fOwner->fLink->Read<BPoint>(location); 1445 fOwner->fLink->Read<uint32>(buttons); 1446 // TODO: ServerWindow replies with an int32 here 1447 1448 ConvertFromScreen(location); 1449 // TODO: in beos R5, location is already converted to the view local coordinate system, 1450 // so if an app checks the window message queue by itself, it might not find what it expects. 1451 } else 1452 *buttons = 0; 1453 } 1454 1455 1456 void 1457 BView::MakeFocus(bool focusState) 1458 { 1459 if (fOwner) { 1460 // TODO: If this view has focus and focusState==false, 1461 // will there really be no other view with focus? No 1462 // cycling to the next one? 1463 BView *focus = fOwner->CurrentFocus(); 1464 if (focusState) { 1465 // Unfocus a previous focus view 1466 if (focus && focus != this) 1467 focus->MakeFocus(false); 1468 // if we want to make this view the current focus view 1469 fOwner->_SetFocus(this, true); 1470 } else { 1471 // we want to unfocus this view, but only if it actually has focus 1472 if (focus == this) { 1473 fOwner->_SetFocus(NULL, true); 1474 } 1475 } 1476 } 1477 } 1478 1479 1480 BScrollBar * 1481 BView::ScrollBar(orientation posture) const 1482 { 1483 switch (posture) { 1484 case B_VERTICAL: 1485 return fVerScroller; 1486 1487 case B_HORIZONTAL: 1488 return fHorScroller; 1489 1490 default: 1491 return NULL; 1492 } 1493 } 1494 1495 1496 void 1497 BView::ScrollBy(float dh, float dv) 1498 { 1499 // scrolling by fractional values is not supported, is it? 1500 dh = roundf(dh); 1501 dv = roundf(dv); 1502 1503 // no reason to process this further if no scroll is intended. 1504 if (dh == 0 && dv == 0) 1505 return; 1506 1507 check_lock(); 1508 1509 // if we're attached to a window tell app_server about this change 1510 if (fOwner) { 1511 fOwner->fLink->StartMessage(AS_LAYER_SCROLL); 1512 fOwner->fLink->Attach<float>(dh); 1513 fOwner->fLink->Attach<float>(dv); 1514 1515 fOwner->fLink->Flush(); 1516 1517 fState->valid_flags &= ~(B_VIEW_FRAME_BIT | B_VIEW_ORIGIN_BIT); 1518 } 1519 1520 // we modify our bounds rectangle by dh/dv coord units hor/ver. 1521 fBounds.OffsetBy(dh, dv); 1522 1523 // then set the new values of the scrollbars 1524 if (fHorScroller) 1525 fHorScroller->SetValue(fBounds.left); 1526 if (fVerScroller) 1527 fVerScroller->SetValue(fBounds.top); 1528 } 1529 1530 1531 void 1532 BView::ScrollTo(BPoint where) 1533 { 1534 ScrollBy(where.x - fBounds.left, where.y - fBounds.top); 1535 } 1536 1537 1538 status_t 1539 BView::SetEventMask(uint32 mask, uint32 options) 1540 { 1541 if (fEventMask == mask && fEventOptions == options) 1542 return B_OK; 1543 1544 fEventMask = mask | (fEventMask & 0xFFFF0000); 1545 fEventOptions = options; 1546 1547 fState->archiving_flags |= B_VIEW_EVENT_MASK_BIT; 1548 1549 if (fOwner) { 1550 check_lock(); 1551 1552 fOwner->fLink->StartMessage(AS_LAYER_SET_EVENT_MASK); 1553 fOwner->fLink->Attach<uint32>(mask); 1554 fOwner->fLink->Attach<uint32>(options); 1555 } 1556 1557 return B_OK; 1558 } 1559 1560 1561 uint32 1562 BView::EventMask() 1563 { 1564 return fEventMask; 1565 } 1566 1567 1568 status_t 1569 BView::SetMouseEventMask(uint32 mask, uint32 options) 1570 { 1571 // Just don't do anything if the view is not yet attached 1572 // or we were called outside of BView::MouseDown() 1573 if (fOwner != NULL 1574 && fOwner->CurrentMessage() != NULL 1575 && fOwner->CurrentMessage()->what == B_MOUSE_DOWN) { 1576 check_lock(); 1577 fOwner->fLink->StartMessage(AS_LAYER_SET_MOUSE_EVENT_MASK); 1578 fOwner->fLink->Attach<uint32>(mask); 1579 fOwner->fLink->Attach<uint32>(options); 1580 1581 return B_OK; 1582 } 1583 1584 return B_ERROR; 1585 } 1586 1587 1588 // #pragma mark - 1589 // Graphic State Functions 1590 1591 1592 void 1593 BView::SetLineMode(cap_mode lineCap, join_mode lineJoin, float miterLimit) 1594 { 1595 if (fState->IsValid(B_VIEW_LINE_MODES_BIT) 1596 && lineCap == fState->line_cap && lineJoin == fState->line_join 1597 && miterLimit == fState->miter_limit) 1598 return; 1599 1600 if (fOwner) { 1601 check_lock(); 1602 1603 fOwner->fLink->StartMessage(AS_LAYER_SET_LINE_MODE); 1604 fOwner->fLink->Attach<int8>((int8)lineCap); 1605 fOwner->fLink->Attach<int8>((int8)lineJoin); 1606 fOwner->fLink->Attach<float>(miterLimit); 1607 1608 fState->valid_flags |= B_VIEW_LINE_MODES_BIT; 1609 } 1610 1611 fState->line_cap = lineCap; 1612 fState->line_join = lineJoin; 1613 fState->miter_limit = miterLimit; 1614 1615 fState->archiving_flags |= B_VIEW_LINE_MODES_BIT; 1616 } 1617 1618 1619 join_mode 1620 BView::LineJoinMode() const 1621 { 1622 // This will update the current state, if necessary 1623 if (!fState->IsValid(B_VIEW_LINE_MODES_BIT)) 1624 LineMiterLimit(); 1625 1626 return fState->line_join; 1627 } 1628 1629 1630 cap_mode 1631 BView::LineCapMode() const 1632 { 1633 // This will update the current state, if necessary 1634 if (!fState->IsValid(B_VIEW_LINE_MODES_BIT)) 1635 LineMiterLimit(); 1636 1637 return fState->line_cap; 1638 } 1639 1640 1641 float 1642 BView::LineMiterLimit() const 1643 { 1644 if (!fState->IsValid(B_VIEW_LINE_MODES_BIT) && fOwner) { 1645 check_lock(); 1646 1647 fOwner->fLink->StartMessage(AS_LAYER_GET_LINE_MODE); 1648 1649 int32 code; 1650 if (fOwner->fLink->FlushWithReply(code) == B_OK 1651 && code == B_OK) { 1652 int8 cap, join; 1653 fOwner->fLink->Read<int8>((int8 *)&cap); 1654 fOwner->fLink->Read<int8>((int8 *)&join); 1655 fOwner->fLink->Read<float>(&fState->miter_limit); 1656 1657 fState->line_cap = (cap_mode)cap; 1658 fState->line_join = (join_mode)join; 1659 } 1660 1661 fState->valid_flags |= B_VIEW_LINE_MODES_BIT; 1662 } 1663 1664 return fState->miter_limit; 1665 } 1666 1667 1668 void 1669 BView::PushState() 1670 { 1671 do_owner_check(); 1672 1673 fOwner->fLink->StartMessage(AS_LAYER_PUSH_STATE); 1674 1675 // initialize origin and scale 1676 fState->valid_flags |= B_VIEW_SCALE_BIT | B_VIEW_ORIGIN_BIT; 1677 fState->scale = 1.0f; 1678 fState->origin.Set(0, 0); 1679 } 1680 1681 1682 void 1683 BView::PopState() 1684 { 1685 do_owner_check(); 1686 1687 fOwner->fLink->StartMessage(AS_LAYER_POP_STATE); 1688 1689 // invalidate all flags (except those that are not part of pop/push) 1690 fState->valid_flags = B_VIEW_VIEW_COLOR_BIT; 1691 } 1692 1693 1694 void 1695 BView::SetScale(float scale) const 1696 { 1697 if (fState->IsValid(B_VIEW_SCALE_BIT) && scale == fState->scale) 1698 return; 1699 1700 if (fOwner) { 1701 check_lock(); 1702 1703 fOwner->fLink->StartMessage(AS_LAYER_SET_SCALE); 1704 fOwner->fLink->Attach<float>(scale); 1705 1706 fState->valid_flags |= B_VIEW_SCALE_BIT; 1707 } 1708 1709 fState->scale = scale; 1710 fState->archiving_flags |= B_VIEW_SCALE_BIT; 1711 } 1712 1713 1714 float 1715 BView::Scale() const 1716 { 1717 if (!fState->IsValid(B_VIEW_SCALE_BIT) && fOwner) { 1718 check_lock(); 1719 1720 fOwner->fLink->StartMessage(AS_LAYER_GET_SCALE); 1721 1722 int32 code; 1723 if (fOwner->fLink->FlushWithReply(code) == B_OK 1724 && code == B_OK) 1725 fOwner->fLink->Read<float>(&fState->scale); 1726 1727 fState->valid_flags |= B_VIEW_SCALE_BIT; 1728 } 1729 1730 return fState->scale; 1731 } 1732 1733 1734 void 1735 BView::SetDrawingMode(drawing_mode mode) 1736 { 1737 if (fState->IsValid(B_VIEW_DRAWING_MODE_BIT) 1738 && mode == fState->drawing_mode) 1739 return; 1740 1741 if (fOwner) { 1742 check_lock(); 1743 1744 fOwner->fLink->StartMessage(AS_LAYER_SET_DRAWING_MODE); 1745 fOwner->fLink->Attach<int8>((int8)mode); 1746 1747 fState->valid_flags |= B_VIEW_DRAWING_MODE_BIT; 1748 } 1749 1750 fState->drawing_mode = mode; 1751 fState->archiving_flags |= B_VIEW_DRAWING_MODE_BIT; 1752 } 1753 1754 1755 drawing_mode 1756 BView::DrawingMode() const 1757 { 1758 if (!fState->IsValid(B_VIEW_DRAWING_MODE_BIT) && fOwner) { 1759 check_lock(); 1760 1761 fOwner->fLink->StartMessage(AS_LAYER_GET_DRAWING_MODE); 1762 1763 int32 code; 1764 if (fOwner->fLink->FlushWithReply(code) == B_OK 1765 && code == B_OK) { 1766 int8 drawingMode; 1767 fOwner->fLink->Read<int8>(&drawingMode); 1768 1769 fState->drawing_mode = (drawing_mode)drawingMode; 1770 fState->valid_flags |= B_VIEW_DRAWING_MODE_BIT; 1771 } 1772 } 1773 1774 return fState->drawing_mode; 1775 } 1776 1777 1778 void 1779 BView::SetBlendingMode(source_alpha sourceAlpha, alpha_function alphaFunction) 1780 { 1781 if (fState->IsValid(B_VIEW_BLENDING_BIT) 1782 && sourceAlpha == fState->alpha_source_mode 1783 && alphaFunction == fState->alpha_function_mode) 1784 return; 1785 1786 if (fOwner) { 1787 check_lock(); 1788 1789 fOwner->fLink->StartMessage(AS_LAYER_SET_BLENDING_MODE); 1790 fOwner->fLink->Attach<int8>((int8)sourceAlpha); 1791 fOwner->fLink->Attach<int8>((int8)alphaFunction); 1792 1793 fState->valid_flags |= B_VIEW_BLENDING_BIT; 1794 } 1795 1796 fState->alpha_source_mode = sourceAlpha; 1797 fState->alpha_function_mode = alphaFunction; 1798 1799 fState->archiving_flags |= B_VIEW_BLENDING_BIT; 1800 } 1801 1802 1803 void 1804 BView::GetBlendingMode(source_alpha *_sourceAlpha, 1805 alpha_function *_alphaFunction) const 1806 { 1807 if (!fState->IsValid(B_VIEW_BLENDING_BIT) && fOwner) { 1808 check_lock(); 1809 1810 fOwner->fLink->StartMessage(AS_LAYER_GET_BLENDING_MODE); 1811 1812 int32 code; 1813 if (fOwner->fLink->FlushWithReply(code) == B_OK 1814 && code == B_OK) { 1815 int8 alphaSourceMode, alphaFunctionMode; 1816 fOwner->fLink->Read<int8>(&alphaSourceMode); 1817 fOwner->fLink->Read<int8>(&alphaFunctionMode); 1818 1819 fState->alpha_source_mode = (source_alpha)alphaSourceMode; 1820 fState->alpha_function_mode = (alpha_function)alphaFunctionMode; 1821 1822 fState->valid_flags |= B_VIEW_BLENDING_BIT; 1823 } 1824 } 1825 1826 if (_sourceAlpha) 1827 *_sourceAlpha = fState->alpha_source_mode; 1828 1829 if (_alphaFunction) 1830 *_alphaFunction = fState->alpha_function_mode; 1831 } 1832 1833 1834 void 1835 BView::MovePenTo(BPoint point) 1836 { 1837 MovePenTo(point.x, point.y); 1838 } 1839 1840 1841 void 1842 BView::MovePenTo(float x, float y) 1843 { 1844 if (fState->IsValid(B_VIEW_PEN_LOCATION_BIT) 1845 && x == fState->pen_location.x && y == fState->pen_location.y) 1846 return; 1847 1848 if (fOwner) { 1849 check_lock(); 1850 1851 fOwner->fLink->StartMessage(AS_LAYER_SET_PEN_LOC); 1852 fOwner->fLink->Attach<float>(x); 1853 fOwner->fLink->Attach<float>(y); 1854 1855 fState->valid_flags |= B_VIEW_PEN_LOCATION_BIT; 1856 } 1857 1858 fState->pen_location.x = x; 1859 fState->pen_location.y = y; 1860 1861 fState->archiving_flags |= B_VIEW_PEN_LOCATION_BIT; 1862 } 1863 1864 1865 void 1866 BView::MovePenBy(float x, float y) 1867 { 1868 // this will update the pen location if necessary 1869 if (!fState->IsValid(B_VIEW_PEN_LOCATION_BIT)) 1870 PenLocation(); 1871 1872 MovePenTo(fState->pen_location.x + x, fState->pen_location.y + y); 1873 } 1874 1875 1876 BPoint 1877 BView::PenLocation() const 1878 { 1879 if (!fState->IsValid(B_VIEW_PEN_LOCATION_BIT) && fOwner) { 1880 check_lock(); 1881 1882 fOwner->fLink->StartMessage(AS_LAYER_GET_PEN_LOC); 1883 1884 int32 code; 1885 if (fOwner->fLink->FlushWithReply(code) == B_OK 1886 && code == B_OK) { 1887 fOwner->fLink->Read<BPoint>(&fState->pen_location); 1888 1889 fState->valid_flags |= B_VIEW_PEN_LOCATION_BIT; 1890 } 1891 } 1892 1893 return fState->pen_location; 1894 } 1895 1896 1897 void 1898 BView::SetPenSize(float size) 1899 { 1900 if (fState->IsValid(B_VIEW_PEN_SIZE_BIT) && size == fState->pen_size) 1901 return; 1902 1903 if (fOwner) { 1904 check_lock(); 1905 1906 fOwner->fLink->StartMessage(AS_LAYER_SET_PEN_SIZE); 1907 fOwner->fLink->Attach<float>(size); 1908 1909 fState->valid_flags |= B_VIEW_PEN_SIZE_BIT; 1910 } 1911 1912 fState->pen_size = size; 1913 fState->archiving_flags |= B_VIEW_PEN_SIZE_BIT; 1914 } 1915 1916 1917 float 1918 BView::PenSize() const 1919 { 1920 if (!fState->IsValid(B_VIEW_PEN_SIZE_BIT) && fOwner) { 1921 check_lock(); 1922 1923 fOwner->fLink->StartMessage(AS_LAYER_GET_PEN_SIZE); 1924 1925 int32 code; 1926 if (fOwner->fLink->FlushWithReply(code) == B_OK 1927 && code == B_OK) { 1928 fOwner->fLink->Read<float>(&fState->pen_size); 1929 1930 fState->valid_flags |= B_VIEW_PEN_SIZE_BIT; 1931 } 1932 } 1933 1934 return fState->pen_size; 1935 } 1936 1937 1938 void 1939 BView::SetHighColor(rgb_color color) 1940 { 1941 // are we up-to-date already? 1942 if (fState->IsValid(B_VIEW_HIGH_COLOR_BIT) 1943 && fState->high_color == color) 1944 return; 1945 1946 if (fOwner) { 1947 check_lock(); 1948 1949 fOwner->fLink->StartMessage(AS_LAYER_SET_HIGH_COLOR); 1950 fOwner->fLink->Attach<rgb_color>(color); 1951 1952 fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT; 1953 } 1954 1955 fState->high_color = color; 1956 1957 fState->archiving_flags |= B_VIEW_HIGH_COLOR_BIT; 1958 } 1959 1960 1961 rgb_color 1962 BView::HighColor() const 1963 { 1964 if (!fState->IsValid(B_VIEW_HIGH_COLOR_BIT) && fOwner) { 1965 check_lock(); 1966 1967 fOwner->fLink->StartMessage(AS_LAYER_GET_HIGH_COLOR); 1968 1969 int32 code; 1970 if (fOwner->fLink->FlushWithReply(code) == B_OK 1971 && code == B_OK) { 1972 fOwner->fLink->Read<rgb_color>(&fState->high_color); 1973 1974 fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT; 1975 } 1976 } 1977 1978 return fState->high_color; 1979 } 1980 1981 1982 void 1983 BView::SetLowColor(rgb_color color) 1984 { 1985 if (fState->IsValid(B_VIEW_LOW_COLOR_BIT) 1986 && fState->low_color == color) 1987 return; 1988 1989 if (fOwner) { 1990 check_lock(); 1991 1992 fOwner->fLink->StartMessage(AS_LAYER_SET_LOW_COLOR); 1993 fOwner->fLink->Attach<rgb_color>(color); 1994 1995 fState->valid_flags |= B_VIEW_LOW_COLOR_BIT; 1996 } 1997 1998 fState->low_color = color; 1999 2000 fState->archiving_flags |= B_VIEW_LOW_COLOR_BIT; 2001 } 2002 2003 2004 rgb_color 2005 BView::LowColor() const 2006 { 2007 if (!fState->IsValid(B_VIEW_LOW_COLOR_BIT) && fOwner) { 2008 check_lock(); 2009 2010 fOwner->fLink->StartMessage(AS_LAYER_GET_LOW_COLOR); 2011 2012 int32 code; 2013 if (fOwner->fLink->FlushWithReply(code) == B_OK 2014 && code == B_OK) { 2015 fOwner->fLink->Read<rgb_color>(&fState->low_color); 2016 2017 fState->valid_flags |= B_VIEW_LOW_COLOR_BIT; 2018 } 2019 } 2020 2021 return fState->low_color; 2022 } 2023 2024 2025 void 2026 BView::SetViewColor(rgb_color color) 2027 { 2028 if (fState->IsValid(B_VIEW_VIEW_COLOR_BIT) && fState->view_color == color) 2029 return; 2030 2031 if (fOwner) { 2032 check_lock(); 2033 2034 fOwner->fLink->StartMessage(AS_LAYER_SET_VIEW_COLOR); 2035 fOwner->fLink->Attach<rgb_color>(color); 2036 2037 fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT; 2038 } 2039 2040 fState->view_color = color; 2041 2042 fState->archiving_flags |= B_VIEW_VIEW_COLOR_BIT; 2043 } 2044 2045 2046 rgb_color 2047 BView::ViewColor() const 2048 { 2049 if (!fState->IsValid(B_VIEW_VIEW_COLOR_BIT) && fOwner) { 2050 check_lock(); 2051 2052 fOwner->fLink->StartMessage(AS_LAYER_GET_VIEW_COLOR); 2053 2054 int32 code; 2055 if (fOwner->fLink->FlushWithReply(code) == B_OK 2056 && code == B_OK) { 2057 fOwner->fLink->Read<rgb_color>(&fState->view_color); 2058 2059 fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT; 2060 } 2061 } 2062 2063 return fState->view_color; 2064 } 2065 2066 2067 void 2068 BView::ForceFontAliasing(bool enable) 2069 { 2070 if (fState->IsValid(B_VIEW_FONT_ALIASING_BIT) && enable == fState->font_aliasing) 2071 return; 2072 2073 if (fOwner) { 2074 check_lock(); 2075 2076 fOwner->fLink->StartMessage(AS_LAYER_PRINT_ALIASING); 2077 fOwner->fLink->Attach<bool>(enable); 2078 2079 fState->valid_flags |= B_VIEW_FONT_ALIASING_BIT; 2080 } 2081 2082 fState->font_aliasing = enable; 2083 fState->archiving_flags |= B_VIEW_FONT_ALIASING_BIT; 2084 } 2085 2086 2087 void 2088 BView::SetFont(const BFont* font, uint32 mask) 2089 { 2090 if (!font || mask == 0) 2091 return; 2092 2093 if (mask == B_FONT_ALL) { 2094 fState->font = *font; 2095 } else { 2096 // ToDo: move this into a BFont method 2097 if (mask & B_FONT_FAMILY_AND_STYLE) 2098 fState->font.SetFamilyAndStyle(font->FamilyAndStyle()); 2099 2100 if (mask & B_FONT_SIZE) 2101 fState->font.SetSize(font->Size()); 2102 2103 if (mask & B_FONT_SHEAR) 2104 fState->font.SetShear(font->Shear()); 2105 2106 if (mask & B_FONT_ROTATION) 2107 fState->font.SetRotation(font->Rotation()); 2108 2109 if (mask & B_FONT_FALSE_BOLD_WIDTH) 2110 fState->font.SetFalseBoldWidth(font->FalseBoldWidth()); 2111 2112 if (mask & B_FONT_SPACING) 2113 fState->font.SetSpacing(font->Spacing()); 2114 2115 if (mask & B_FONT_ENCODING) 2116 fState->font.SetEncoding(font->Encoding()); 2117 2118 if (mask & B_FONT_FACE) 2119 fState->font.SetFace(font->Face()); 2120 2121 if (mask & B_FONT_FLAGS) 2122 fState->font.SetFlags(font->Flags()); 2123 } 2124 2125 fState->font_flags |= mask; 2126 2127 if (fOwner) { 2128 check_lock(); 2129 do_owner_check(); 2130 2131 fState->UpdateServerFontState(*fOwner->fLink); 2132 } 2133 } 2134 2135 2136 #if !_PR3_COMPATIBLE_ 2137 void 2138 BView::GetFont(BFont *font) const 2139 #else 2140 void 2141 BView:GetFont(BFont *font) 2142 #endif 2143 { 2144 *font = fState->font; 2145 } 2146 2147 2148 void 2149 BView::GetFontHeight(font_height *height) const 2150 { 2151 fState->font.GetHeight(height); 2152 } 2153 2154 2155 void 2156 BView::SetFontSize(float size) 2157 { 2158 BFont font; 2159 font.SetSize(size); 2160 2161 SetFont(&font, B_FONT_SIZE); 2162 } 2163 2164 2165 float 2166 BView::StringWidth(const char *string) const 2167 { 2168 return fState->font.StringWidth(string); 2169 } 2170 2171 2172 float 2173 BView::StringWidth(const char* string, int32 length) const 2174 { 2175 return fState->font.StringWidth(string, length); 2176 } 2177 2178 2179 void 2180 BView::GetStringWidths(char *stringArray[],int32 lengthArray[], 2181 int32 numStrings, float widthArray[]) const 2182 { 2183 fState->font.GetStringWidths(const_cast<const char **>(stringArray), 2184 const_cast<const int32 *>(lengthArray), numStrings, widthArray); 2185 } 2186 2187 2188 void 2189 BView::TruncateString(BString *in_out, uint32 mode, float width) const 2190 { 2191 fState->font.TruncateString(in_out, mode, width); 2192 } 2193 2194 2195 void 2196 BView::ClipToPicture(BPicture *picture, BPoint where, bool sync) 2197 { 2198 DoPictureClip(picture, where, false, sync); 2199 } 2200 2201 2202 void 2203 BView::ClipToInversePicture(BPicture *picture, 2204 BPoint where, bool sync) 2205 { 2206 DoPictureClip(picture, where, true, sync); 2207 } 2208 2209 2210 void 2211 BView::GetClippingRegion(BRegion* region) const 2212 { 2213 if (!region) 2214 return; 2215 2216 // NOTE: the client has no idea when the clipping in the server 2217 // changed, so it is always read from the serber 2218 region->MakeEmpty(); 2219 2220 if (fOwner && do_owner_check()) { 2221 fOwner->fLink->StartMessage(AS_LAYER_GET_CLIP_REGION); 2222 2223 int32 code; 2224 if (fOwner->fLink->FlushWithReply(code) == B_OK 2225 && code == B_OK) { 2226 int32 count; 2227 fOwner->fLink->Read<int32>(&count); 2228 2229 for (int32 i = 0; i < count; i++) { 2230 BRect rect; 2231 fOwner->fLink->Read<BRect>(&rect); 2232 2233 region->Include(rect); 2234 } 2235 fState->valid_flags |= B_VIEW_CLIP_REGION_BIT; 2236 } 2237 } 2238 } 2239 2240 2241 void 2242 BView::ConstrainClippingRegion(BRegion* region) 2243 { 2244 if (do_owner_check()) { 2245 2246 fOwner->fLink->StartMessage(AS_LAYER_SET_CLIP_REGION); 2247 2248 if (region) { 2249 int32 count = region->CountRects(); 2250 fOwner->fLink->Attach<int32>(count); 2251 for (int32 i = 0; i < count; i++) 2252 fOwner->fLink->Attach<clipping_rect>(region->RectAtInt(i)); 2253 } else { 2254 fOwner->fLink->Attach<int32>(-1); 2255 // '-1' means that in the app_server, there won't be any 'local' 2256 // clipping region (it will be NULL) 2257 } 2258 2259 // we flush here because app_server waits for all the rects 2260 fOwner->fLink->Flush(); 2261 2262 fState->valid_flags &= ~B_VIEW_CLIP_REGION_BIT; 2263 fState->archiving_flags |= B_VIEW_CLIP_REGION_BIT; 2264 } 2265 } 2266 2267 2268 // #pragma mark - Drawing Functions 2269 //--------------------------------------------------------------------------- 2270 2271 2272 void 2273 BView::DrawBitmapAsync(const BBitmap *bitmap, BRect srcRect, BRect dstRect) 2274 { 2275 if (!bitmap || !srcRect.IsValid() || !dstRect.IsValid()) 2276 return; 2277 2278 if (fOwner) { 2279 check_lock(); 2280 2281 fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP); 2282 fOwner->fLink->Attach<int32>(bitmap->_ServerToken()); 2283 fOwner->fLink->Attach<BRect>(dstRect); 2284 fOwner->fLink->Attach<BRect>(srcRect); 2285 2286 _FlushIfNotInTransaction(); 2287 } 2288 } 2289 2290 2291 void 2292 BView::DrawBitmapAsync(const BBitmap *bitmap, BRect dstRect) 2293 { 2294 DrawBitmapAsync(bitmap, bitmap->Bounds().OffsetToCopy(B_ORIGIN), dstRect); 2295 } 2296 2297 2298 void 2299 BView::DrawBitmapAsync(const BBitmap *bitmap) 2300 { 2301 DrawBitmapAsync(bitmap, PenLocation()); 2302 } 2303 2304 2305 void 2306 BView::DrawBitmapAsync(const BBitmap *bitmap, BPoint where) 2307 { 2308 if (bitmap == NULL) 2309 return; 2310 2311 if (fOwner) { 2312 check_lock(); 2313 2314 fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP); 2315 fOwner->fLink->Attach<int32>(bitmap->_ServerToken()); 2316 BRect src = bitmap->Bounds().OffsetToCopy(B_ORIGIN); 2317 BRect dst = src.OffsetToCopy(where); 2318 fOwner->fLink->Attach<BRect>(dst); 2319 fOwner->fLink->Attach<BRect>(src); 2320 2321 _FlushIfNotInTransaction(); 2322 } 2323 } 2324 2325 2326 void 2327 BView::DrawBitmap(const BBitmap *bitmap) 2328 { 2329 DrawBitmap(bitmap, PenLocation()); 2330 } 2331 2332 2333 void 2334 BView::DrawBitmap(const BBitmap *bitmap, BPoint where) 2335 { 2336 if (fOwner) { 2337 DrawBitmapAsync(bitmap, where); 2338 Sync(); 2339 } 2340 } 2341 2342 2343 void 2344 BView::DrawBitmap(const BBitmap *bitmap, BRect dstRect) 2345 { 2346 DrawBitmap(bitmap, bitmap->Bounds().OffsetToCopy(B_ORIGIN), dstRect); 2347 } 2348 2349 2350 void 2351 BView::DrawBitmap(const BBitmap *bitmap, BRect srcRect, BRect dstRect) 2352 { 2353 if (fOwner) { 2354 DrawBitmapAsync(bitmap, srcRect, dstRect); 2355 Sync(); 2356 } 2357 } 2358 2359 2360 void 2361 BView::DrawChar(char c) 2362 { 2363 DrawString(&c, 1, PenLocation()); 2364 } 2365 2366 2367 void 2368 BView::DrawChar(char c, BPoint location) 2369 { 2370 DrawString(&c, 1, location); 2371 } 2372 2373 2374 void 2375 BView::DrawString(const char *string, escapement_delta *delta) 2376 { 2377 if (string == NULL) 2378 return; 2379 2380 DrawString(string, strlen(string), PenLocation(), delta); 2381 } 2382 2383 2384 void 2385 BView::DrawString(const char *string, BPoint location, escapement_delta *delta) 2386 { 2387 if (string == NULL) 2388 return; 2389 2390 DrawString(string, strlen(string), location, delta); 2391 } 2392 2393 2394 void 2395 BView::DrawString(const char *string, int32 length, escapement_delta *delta) 2396 { 2397 DrawString(string, length, PenLocation(), delta); 2398 } 2399 2400 2401 void 2402 BView::DrawString(const char *string, int32 length, BPoint location, 2403 escapement_delta *delta) 2404 { 2405 if (string == NULL || length < 1) 2406 return; 2407 2408 if (fOwner) { 2409 check_lock(); 2410 2411 fOwner->fLink->StartMessage(AS_DRAW_STRING); 2412 fOwner->fLink->Attach<int32>(length); 2413 fOwner->fLink->Attach<BPoint>(location); 2414 2415 // Quite often delta will be NULL, so we have to accomodate this. 2416 if (delta) 2417 fOwner->fLink->Attach<escapement_delta>(*delta); 2418 else { 2419 escapement_delta tdelta; 2420 tdelta.space = 0; 2421 tdelta.nonspace = 0; 2422 2423 fOwner->fLink->Attach<escapement_delta>(tdelta); 2424 } 2425 2426 fOwner->fLink->AttachString(string, length); 2427 2428 _FlushIfNotInTransaction(); 2429 2430 // this modifies our pen location, so we invalidate the flag. 2431 fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT; 2432 } 2433 } 2434 2435 2436 void 2437 BView::StrokeEllipse(BPoint center, float xRadius, float yRadius, 2438 pattern p) 2439 { 2440 StrokeEllipse(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius, 2441 center.y + yRadius), p); 2442 } 2443 2444 2445 void 2446 BView::StrokeEllipse(BRect rect, ::pattern pattern) 2447 { 2448 if (fOwner == NULL) 2449 return; 2450 2451 check_lock(); 2452 _UpdatePattern(pattern); 2453 2454 fOwner->fLink->StartMessage(AS_STROKE_ELLIPSE); 2455 fOwner->fLink->Attach<BRect>(rect); 2456 2457 _FlushIfNotInTransaction(); 2458 } 2459 2460 2461 void 2462 BView::FillEllipse(BPoint center, float xRadius, float yRadius, 2463 ::pattern pattern) 2464 { 2465 FillEllipse(BRect(center.x - xRadius, center.y - yRadius, 2466 center.x + xRadius, center.y + yRadius), pattern); 2467 } 2468 2469 2470 void 2471 BView::FillEllipse(BRect rect, ::pattern pattern) 2472 { 2473 if (fOwner == NULL) 2474 return; 2475 2476 check_lock(); 2477 _UpdatePattern(pattern); 2478 2479 fOwner->fLink->StartMessage(AS_FILL_ELLIPSE); 2480 fOwner->fLink->Attach<BRect>(rect); 2481 2482 _FlushIfNotInTransaction(); 2483 } 2484 2485 2486 void 2487 BView::StrokeArc(BPoint center, float xRadius, float yRadius, 2488 float startAngle, float arcAngle, pattern p) 2489 { 2490 StrokeArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius, 2491 center.y + yRadius), startAngle, arcAngle, p); 2492 } 2493 2494 2495 void 2496 BView::StrokeArc(BRect rect, float startAngle, float arcAngle, 2497 ::pattern pattern) 2498 { 2499 if (fOwner == NULL) 2500 return; 2501 2502 check_lock(); 2503 _UpdatePattern(pattern); 2504 2505 fOwner->fLink->StartMessage(AS_STROKE_ARC); 2506 fOwner->fLink->Attach<BRect>(rect); 2507 fOwner->fLink->Attach<float>(startAngle); 2508 fOwner->fLink->Attach<float>(arcAngle); 2509 2510 _FlushIfNotInTransaction(); 2511 } 2512 2513 2514 void 2515 BView::FillArc(BPoint center,float xRadius, float yRadius, 2516 float startAngle, float arcAngle, ::pattern pattern) 2517 { 2518 FillArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius, 2519 center.y + yRadius), startAngle, arcAngle, pattern); 2520 } 2521 2522 2523 void 2524 BView::FillArc(BRect rect, float startAngle, float arcAngle, 2525 ::pattern pattern) 2526 { 2527 if (fOwner == NULL) 2528 return; 2529 2530 check_lock(); 2531 _UpdatePattern(pattern); 2532 2533 fOwner->fLink->StartMessage(AS_FILL_ARC); 2534 fOwner->fLink->Attach<BRect>(rect); 2535 fOwner->fLink->Attach<float>(startAngle); 2536 fOwner->fLink->Attach<float>(arcAngle); 2537 2538 _FlushIfNotInTransaction(); 2539 } 2540 2541 2542 void 2543 BView::StrokeBezier(BPoint *controlPoints, ::pattern pattern) 2544 { 2545 if (fOwner == NULL) 2546 return; 2547 2548 check_lock(); 2549 _UpdatePattern(pattern); 2550 2551 fOwner->fLink->StartMessage(AS_STROKE_BEZIER); 2552 fOwner->fLink->Attach<BPoint>(controlPoints[0]); 2553 fOwner->fLink->Attach<BPoint>(controlPoints[1]); 2554 fOwner->fLink->Attach<BPoint>(controlPoints[2]); 2555 fOwner->fLink->Attach<BPoint>(controlPoints[3]); 2556 2557 _FlushIfNotInTransaction(); 2558 } 2559 2560 2561 void 2562 BView::FillBezier(BPoint *controlPoints, ::pattern pattern) 2563 { 2564 if (fOwner == NULL) 2565 return; 2566 2567 check_lock(); 2568 _UpdatePattern(pattern); 2569 2570 fOwner->fLink->StartMessage(AS_FILL_BEZIER); 2571 fOwner->fLink->Attach<BPoint>(controlPoints[0]); 2572 fOwner->fLink->Attach<BPoint>(controlPoints[1]); 2573 fOwner->fLink->Attach<BPoint>(controlPoints[2]); 2574 fOwner->fLink->Attach<BPoint>(controlPoints[3]); 2575 2576 _FlushIfNotInTransaction(); 2577 } 2578 2579 2580 void 2581 BView::StrokePolygon(const BPolygon *polygon, bool closed, pattern p) 2582 { 2583 if (!polygon) 2584 return; 2585 2586 StrokePolygon(polygon->fPoints, polygon->fCount, polygon->Frame(), closed, p); 2587 } 2588 2589 2590 void 2591 BView::StrokePolygon(const BPoint *ptArray, int32 numPoints, bool closed, pattern p) 2592 { 2593 BPolygon polygon(ptArray, numPoints); 2594 2595 StrokePolygon(polygon.fPoints, polygon.fCount, polygon.Frame(), closed, p); 2596 } 2597 2598 2599 void 2600 BView::StrokePolygon(const BPoint *ptArray, int32 numPoints, BRect bounds, 2601 bool closed, ::pattern pattern) 2602 { 2603 if (!ptArray 2604 || numPoints <= 1 2605 || fOwner == NULL) 2606 return; 2607 2608 check_lock(); 2609 _UpdatePattern(pattern); 2610 2611 BPolygon polygon(ptArray, numPoints); 2612 polygon.MapTo(polygon.Frame(), bounds); 2613 2614 if (fOwner->fLink->StartMessage(AS_STROKE_POLYGON, 2615 polygon.fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(bool) + sizeof(int32)) 2616 == B_OK) { 2617 fOwner->fLink->Attach<BRect>(polygon.Frame()); 2618 fOwner->fLink->Attach<bool>(closed); 2619 fOwner->fLink->Attach<int32>(polygon.fCount); 2620 fOwner->fLink->Attach(polygon.fPoints, polygon.fCount * sizeof(BPoint)); 2621 2622 _FlushIfNotInTransaction(); 2623 } else { 2624 // TODO: send via an area 2625 fprintf(stderr, "ERROR: polygon to big for BPortLink!\n"); 2626 } 2627 } 2628 2629 2630 void 2631 BView::FillPolygon(const BPolygon *polygon, ::pattern pattern) 2632 { 2633 if (polygon == NULL 2634 || polygon->fCount <= 2 2635 || fOwner == NULL) 2636 return; 2637 2638 check_lock(); 2639 _UpdatePattern(pattern); 2640 2641 if (fOwner->fLink->StartMessage(AS_FILL_POLYGON, 2642 polygon->fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(int32)) == B_OK) { 2643 fOwner->fLink->Attach<BRect>(polygon->Frame()); 2644 fOwner->fLink->Attach<int32>(polygon->fCount); 2645 fOwner->fLink->Attach(polygon->fPoints, polygon->fCount * sizeof(BPoint)); 2646 2647 _FlushIfNotInTransaction(); 2648 } else { 2649 // TODO: send via an area 2650 fprintf(stderr, "ERROR: polygon to big for BPortLink!\n"); 2651 } 2652 } 2653 2654 2655 void 2656 BView::FillPolygon(const BPoint *ptArray, int32 numPts, ::pattern pattern) 2657 { 2658 if (!ptArray) 2659 return; 2660 2661 BPolygon polygon(ptArray, numPts); 2662 FillPolygon(&polygon, pattern); 2663 } 2664 2665 2666 void 2667 BView::FillPolygon(const BPoint *ptArray, int32 numPts, BRect bounds, 2668 pattern p) 2669 { 2670 if (!ptArray) 2671 return; 2672 2673 BPolygon polygon(ptArray, numPts); 2674 2675 polygon.MapTo(polygon.Frame(), bounds); 2676 FillPolygon(&polygon, p); 2677 } 2678 2679 2680 void 2681 BView::StrokeRect(BRect rect, ::pattern pattern) 2682 { 2683 if (fOwner == NULL) 2684 return; 2685 2686 check_lock(); 2687 _UpdatePattern(pattern); 2688 2689 fOwner->fLink->StartMessage(AS_STROKE_RECT); 2690 fOwner->fLink->Attach<BRect>(rect); 2691 2692 _FlushIfNotInTransaction(); 2693 } 2694 2695 2696 void 2697 BView::FillRect(BRect rect, ::pattern pattern) 2698 { 2699 if (fOwner == NULL) 2700 return; 2701 2702 // NOTE: ensuring compatibility with R5, 2703 // invalid rects are not filled, they are stroked though! 2704 if (!rect.IsValid()) 2705 return; 2706 2707 check_lock(); 2708 _UpdatePattern(pattern); 2709 2710 fOwner->fLink->StartMessage(AS_FILL_RECT); 2711 fOwner->fLink->Attach<BRect>(rect); 2712 2713 _FlushIfNotInTransaction(); 2714 } 2715 2716 2717 void 2718 BView::StrokeRoundRect(BRect rect, float xRadius, float yRadius, 2719 ::pattern pattern) 2720 { 2721 if (fOwner == NULL) 2722 return; 2723 2724 check_lock(); 2725 _UpdatePattern(pattern); 2726 2727 fOwner->fLink->StartMessage(AS_STROKE_ROUNDRECT); 2728 fOwner->fLink->Attach<BRect>(rect); 2729 fOwner->fLink->Attach<float>(xRadius); 2730 fOwner->fLink->Attach<float>(yRadius); 2731 2732 _FlushIfNotInTransaction(); 2733 } 2734 2735 2736 void 2737 BView::FillRoundRect(BRect rect, float xRadius, float yRadius, 2738 ::pattern pattern) 2739 { 2740 if (fOwner == NULL) 2741 return; 2742 2743 check_lock(); 2744 2745 _UpdatePattern(pattern); 2746 2747 fOwner->fLink->StartMessage(AS_FILL_ROUNDRECT); 2748 fOwner->fLink->Attach<BRect>(rect); 2749 fOwner->fLink->Attach<float>(xRadius); 2750 fOwner->fLink->Attach<float>(yRadius); 2751 2752 _FlushIfNotInTransaction(); 2753 } 2754 2755 2756 void 2757 BView::FillRegion(BRegion *region, ::pattern pattern) 2758 { 2759 if (region == NULL || fOwner == NULL) 2760 return; 2761 2762 check_lock(); 2763 2764 _UpdatePattern(pattern); 2765 2766 fOwner->fLink->StartMessage(AS_FILL_REGION); 2767 fOwner->fLink->AttachRegion(*region); 2768 // TODO: make this automatically chose 2769 // to send over area or handle failure here? 2770 2771 _FlushIfNotInTransaction(); 2772 } 2773 2774 2775 void 2776 BView::StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3, 2777 BRect bounds, ::pattern pattern) 2778 { 2779 if (fOwner == NULL) 2780 return; 2781 2782 check_lock(); 2783 2784 _UpdatePattern(pattern); 2785 2786 fOwner->fLink->StartMessage(AS_STROKE_TRIANGLE); 2787 fOwner->fLink->Attach<BPoint>(pt1); 2788 fOwner->fLink->Attach<BPoint>(pt2); 2789 fOwner->fLink->Attach<BPoint>(pt3); 2790 fOwner->fLink->Attach<BRect>(bounds); 2791 2792 _FlushIfNotInTransaction(); 2793 } 2794 2795 2796 void 2797 BView::StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3, pattern p) 2798 { 2799 if (fOwner) { 2800 // we construct the smallest rectangle that contains the 3 points 2801 // for the 1st point 2802 BRect bounds(pt1, pt1); 2803 2804 // for the 2nd point 2805 if (pt2.x < bounds.left) 2806 bounds.left = pt2.x; 2807 2808 if (pt2.y < bounds.top) 2809 bounds.top = pt2.y; 2810 2811 if (pt2.x > bounds.right) 2812 bounds.right = pt2.x; 2813 2814 if (pt2.y > bounds.bottom) 2815 bounds.bottom = pt2.y; 2816 2817 // for the 3rd point 2818 if (pt3.x < bounds.left) 2819 bounds.left = pt3.x; 2820 2821 if (pt3.y < bounds.top) 2822 bounds.top = pt3.y; 2823 2824 if (pt3.x > bounds.right) 2825 bounds.right = pt3.x; 2826 2827 if (pt3.y > bounds.bottom) 2828 bounds.bottom = pt3.y; 2829 2830 StrokeTriangle(pt1, pt2, pt3, bounds, p); 2831 } 2832 } 2833 2834 2835 void 2836 BView::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, pattern p) 2837 { 2838 if (fOwner) { 2839 // we construct the smallest rectangle that contains the 3 points 2840 // for the 1st point 2841 BRect bounds(pt1, pt1); 2842 2843 // for the 2nd point 2844 if (pt2.x < bounds.left) 2845 bounds.left = pt2.x; 2846 2847 if (pt2.y < bounds.top) 2848 bounds.top = pt2.y; 2849 2850 if (pt2.x > bounds.right) 2851 bounds.right = pt2.x; 2852 2853 if (pt2.y > bounds.bottom) 2854 bounds.bottom = pt2.y; 2855 2856 // for the 3rd point 2857 if (pt3.x < bounds.left) 2858 bounds.left = pt3.x; 2859 2860 if (pt3.y < bounds.top) 2861 bounds.top = pt3.y; 2862 2863 if (pt3.x > bounds.right) 2864 bounds.right = pt3.x; 2865 2866 if (pt3.y > bounds.bottom) 2867 bounds.bottom = pt3.y; 2868 2869 FillTriangle(pt1, pt2, pt3, bounds, p); 2870 } 2871 } 2872 2873 2874 void 2875 BView::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, 2876 BRect bounds, ::pattern pattern) 2877 { 2878 if (fOwner == NULL) 2879 return; 2880 2881 check_lock(); 2882 _UpdatePattern(pattern); 2883 2884 fOwner->fLink->StartMessage(AS_FILL_TRIANGLE); 2885 fOwner->fLink->Attach<BPoint>(pt1); 2886 fOwner->fLink->Attach<BPoint>(pt2); 2887 fOwner->fLink->Attach<BPoint>(pt3); 2888 fOwner->fLink->Attach<BRect>(bounds); 2889 2890 _FlushIfNotInTransaction(); 2891 } 2892 2893 2894 void 2895 BView::StrokeLine(BPoint toPt, pattern p) 2896 { 2897 StrokeLine(PenLocation(), toPt, p); 2898 } 2899 2900 2901 void 2902 BView::StrokeLine(BPoint pt0, BPoint pt1, ::pattern pattern) 2903 { 2904 if (fOwner == NULL) 2905 return; 2906 2907 check_lock(); 2908 _UpdatePattern(pattern); 2909 2910 fOwner->fLink->StartMessage(AS_STROKE_LINE); 2911 fOwner->fLink->Attach<BPoint>(pt0); 2912 fOwner->fLink->Attach<BPoint>(pt1); 2913 2914 _FlushIfNotInTransaction(); 2915 2916 // this modifies our pen location, so we invalidate the flag. 2917 fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT; 2918 } 2919 2920 2921 void 2922 BView::StrokeShape(BShape *shape, ::pattern pattern) 2923 { 2924 if (shape == NULL || fOwner == NULL) 2925 return; 2926 2927 shape_data *sd = (shape_data *)shape->fPrivateData; 2928 if (sd->opCount == 0 || sd->ptCount == 0) 2929 return; 2930 2931 check_lock(); 2932 _UpdatePattern(pattern); 2933 2934 if ((sd->opCount * sizeof(uint32)) + (sd->ptCount * sizeof(BPoint)) < MAX_ATTACHMENT_SIZE) { 2935 fOwner->fLink->StartMessage(AS_STROKE_SHAPE); 2936 fOwner->fLink->Attach<BRect>(shape->Bounds()); 2937 fOwner->fLink->Attach<int32>(sd->opCount); 2938 fOwner->fLink->Attach<int32>(sd->ptCount); 2939 fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(uint32)); 2940 fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint)); 2941 2942 _FlushIfNotInTransaction(); 2943 } else { 2944 // TODO: send via an area 2945 } 2946 } 2947 2948 2949 void 2950 BView::FillShape(BShape *shape, ::pattern pattern) 2951 { 2952 if (shape == NULL || fOwner == NULL) 2953 return; 2954 2955 shape_data *sd = (shape_data *)(shape->fPrivateData); 2956 if (sd->opCount == 0 || sd->ptCount == 0) 2957 return; 2958 2959 check_lock(); 2960 _UpdatePattern(pattern); 2961 2962 if ((sd->opCount * sizeof(uint32)) + (sd->ptCount * sizeof(BPoint)) < MAX_ATTACHMENT_SIZE) { 2963 fOwner->fLink->StartMessage(AS_FILL_SHAPE); 2964 fOwner->fLink->Attach<BRect>(shape->Bounds()); 2965 fOwner->fLink->Attach<int32>(sd->opCount); 2966 fOwner->fLink->Attach<int32>(sd->ptCount); 2967 fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(int32)); 2968 fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint)); 2969 2970 _FlushIfNotInTransaction(); 2971 } else { 2972 // TODO: send via an area 2973 // BTW, in a perfect world, the fLink API would take care of that -- axeld. 2974 } 2975 } 2976 2977 2978 void 2979 BView::BeginLineArray(int32 count) 2980 { 2981 if (fOwner == NULL) 2982 return; 2983 2984 if (count <= 0) 2985 debugger("Calling BeginLineArray with a count <= 0"); 2986 2987 check_lock_no_pick(); 2988 2989 if (comm) { 2990 debugger("Can't nest BeginLineArray calls"); 2991 // not fatal, but it helps during 2992 // development of your app and is in 2993 // line with R5... 2994 delete [] comm->array; 2995 delete comm; 2996 } 2997 2998 comm = new _array_data_; 2999 3000 comm->maxCount = count; 3001 comm->count = 0; 3002 comm->array = new _array_hdr_[count]; 3003 } 3004 3005 3006 void 3007 BView::AddLine(BPoint pt0, BPoint pt1, rgb_color col) 3008 { 3009 if (fOwner == NULL) 3010 return; 3011 3012 if (!comm) 3013 debugger("BeginLineArray must be called before using AddLine"); 3014 3015 check_lock_no_pick(); 3016 3017 if (comm->count < comm->maxCount) { 3018 comm->array[comm->count].startX = pt0.x; 3019 comm->array[comm->count].startY = pt0.y; 3020 comm->array[comm->count].endX = pt1.x; 3021 comm->array[comm->count].endY = pt1.y; 3022 comm->array[comm->count].color = col; 3023 3024 comm->count++; 3025 } 3026 } 3027 3028 3029 void 3030 BView::EndLineArray() 3031 { 3032 if (fOwner == NULL) 3033 return; 3034 3035 if (!comm) 3036 debugger("Can't call EndLineArray before BeginLineArray"); 3037 3038 check_lock(); 3039 3040 fOwner->fLink->StartMessage(AS_STROKE_LINEARRAY); 3041 fOwner->fLink->Attach<int32>(comm->count); 3042 fOwner->fLink->Attach(comm->array, comm->count * sizeof(_array_hdr_)); 3043 3044 _FlushIfNotInTransaction(); 3045 3046 removeCommArray(); 3047 } 3048 3049 3050 void 3051 BView::BeginPicture(BPicture *picture) 3052 { 3053 if (do_owner_check() && picture && picture->usurped == NULL) { 3054 picture->usurp(cpicture); 3055 cpicture = picture; 3056 3057 fOwner->fLink->StartMessage(AS_LAYER_BEGIN_PICTURE); 3058 } 3059 } 3060 3061 3062 void 3063 BView::AppendToPicture(BPicture *picture) 3064 { 3065 check_lock(); 3066 3067 if (picture && picture->usurped == NULL) { 3068 int32 token = picture->token; 3069 3070 if (token == -1) { 3071 BeginPicture(picture); 3072 } else { 3073 picture->usurped = cpicture; 3074 picture->set_token(-1); 3075 fOwner->fLink->StartMessage(AS_LAYER_APPEND_TO_PICTURE); 3076 fOwner->fLink->Attach<int32>(token); 3077 } 3078 } 3079 } 3080 3081 3082 BPicture * 3083 BView::EndPicture() 3084 { 3085 if (do_owner_check() && cpicture) { 3086 int32 token; 3087 3088 fOwner->fLink->StartMessage(AS_LAYER_END_PICTURE); 3089 3090 int32 code; 3091 if (fOwner->fLink->FlushWithReply(code) == B_OK 3092 && code == B_OK 3093 && fOwner->fLink->Read<int32>(&token) == B_OK) { 3094 BPicture *picture = cpicture; 3095 cpicture = picture->step_down(); 3096 picture->set_token(token); 3097 3098 return picture; 3099 } 3100 } 3101 3102 return NULL; 3103 } 3104 3105 3106 void 3107 BView::SetViewBitmap(const BBitmap *bitmap, BRect srcRect, BRect dstRect, 3108 uint32 followFlags, uint32 options) 3109 { 3110 _SetViewBitmap(bitmap, srcRect, dstRect, followFlags, options); 3111 } 3112 3113 3114 void 3115 BView::SetViewBitmap(const BBitmap *bitmap, uint32 followFlags, uint32 options) 3116 { 3117 BRect rect; 3118 if (bitmap) 3119 rect = bitmap->Bounds(); 3120 3121 rect.OffsetTo(B_ORIGIN); 3122 3123 _SetViewBitmap(bitmap, rect, rect, followFlags, options); 3124 } 3125 3126 3127 void 3128 BView::ClearViewBitmap() 3129 { 3130 _SetViewBitmap(NULL, BRect(), BRect(), 0, 0); 3131 } 3132 3133 3134 status_t 3135 BView::SetViewOverlay(const BBitmap *overlay, BRect srcRect, BRect dstRect, 3136 rgb_color *colorKey, uint32 followFlags, uint32 options) 3137 { 3138 if ((overlay->fFlags & B_BITMAP_WILL_OVERLAY) == 0) 3139 return B_BAD_VALUE; 3140 3141 status_t status = _SetViewBitmap(overlay, srcRect, dstRect, followFlags, 3142 options | AS_REQUEST_COLOR_KEY); 3143 if (status == B_OK) { 3144 // read the color that will be treated as transparent 3145 fOwner->fLink->Read<rgb_color>(colorKey); 3146 } 3147 3148 return status; 3149 } 3150 3151 3152 status_t 3153 BView::SetViewOverlay(const BBitmap *overlay, rgb_color *colorKey, 3154 uint32 followFlags, uint32 options) 3155 { 3156 BRect rect; 3157 if (overlay != NULL) { 3158 rect = overlay->Bounds(); 3159 rect.OffsetTo(B_ORIGIN); 3160 } 3161 3162 return SetViewOverlay(overlay, rect, rect, colorKey, followFlags, options); 3163 } 3164 3165 3166 void 3167 BView::ClearViewOverlay() 3168 { 3169 _SetViewBitmap(NULL, BRect(), BRect(), 0, 0); 3170 } 3171 3172 3173 void 3174 BView::CopyBits(BRect src, BRect dst) 3175 { 3176 if (!src.IsValid() || !dst.IsValid()) 3177 return; 3178 3179 if (do_owner_check()) { 3180 fOwner->fLink->StartMessage(AS_LAYER_COPY_BITS); 3181 fOwner->fLink->Attach<BRect>(src); 3182 fOwner->fLink->Attach<BRect>(dst); 3183 3184 _FlushIfNotInTransaction(); 3185 } 3186 } 3187 3188 3189 void 3190 BView::DrawPicture(const BPicture *picture) 3191 { 3192 if (picture == NULL) 3193 return; 3194 3195 DrawPictureAsync(picture, PenLocation()); 3196 Sync(); 3197 } 3198 3199 3200 void 3201 BView::DrawPicture(const BPicture *picture, BPoint where) 3202 { 3203 if (picture == NULL) 3204 return; 3205 3206 DrawPictureAsync(picture, where); 3207 Sync(); 3208 } 3209 3210 3211 void 3212 BView::DrawPicture(const char *filename, long offset, BPoint where) 3213 { 3214 if (!filename) 3215 return; 3216 3217 DrawPictureAsync(filename, offset, where); 3218 Sync(); 3219 } 3220 3221 3222 void 3223 BView::DrawPictureAsync(const BPicture *picture) 3224 { 3225 if (picture == NULL) 3226 return; 3227 3228 DrawPictureAsync(picture, PenLocation()); 3229 } 3230 3231 3232 void 3233 BView::DrawPictureAsync(const BPicture *picture, BPoint where) 3234 { 3235 if (picture == NULL) 3236 return; 3237 3238 if (do_owner_check() && picture->token > 0) { 3239 fOwner->fLink->StartMessage(AS_LAYER_DRAW_PICTURE); 3240 fOwner->fLink->Attach<int32>(picture->token); 3241 fOwner->fLink->Attach<BPoint>(where); 3242 3243 _FlushIfNotInTransaction(); 3244 } 3245 } 3246 3247 3248 void 3249 BView::DrawPictureAsync(const char *filename, long offset, BPoint where) 3250 { 3251 if (!filename) 3252 return; 3253 3254 // TODO: Test 3255 BFile file(filename, B_READ_ONLY); 3256 if (file.InitCheck() < B_OK) 3257 return; 3258 3259 file.Seek(offset, SEEK_SET); 3260 3261 BPicture picture; 3262 if (picture.Unflatten(&file) < B_OK) 3263 return; 3264 3265 DrawPictureAsync(&picture, where); 3266 } 3267 3268 3269 void 3270 BView::Invalidate(BRect invalRect) 3271 { 3272 if (!invalRect.IsValid() || fOwner == NULL) 3273 return; 3274 3275 check_lock(); 3276 3277 fOwner->fLink->StartMessage(AS_LAYER_INVALIDATE_RECT); 3278 fOwner->fLink->Attach<BRect>(invalRect); 3279 fOwner->fLink->Flush(); 3280 } 3281 3282 3283 void 3284 BView::Invalidate(const BRegion *invalRegion) 3285 { 3286 if (invalRegion == NULL || fOwner == NULL) 3287 return; 3288 3289 check_lock(); 3290 3291 int32 count = 0; 3292 count = const_cast<BRegion*>(invalRegion)->CountRects(); 3293 3294 fOwner->fLink->StartMessage(AS_LAYER_INVALIDATE_REGION); 3295 fOwner->fLink->Attach<int32>(count); 3296 3297 for (int32 i = 0; i < count; i++) 3298 fOwner->fLink->Attach<BRect>( const_cast<BRegion *>(invalRegion)->RectAt(i)); 3299 3300 fOwner->fLink->Flush(); 3301 } 3302 3303 3304 void 3305 BView::Invalidate() 3306 { 3307 Invalidate(Bounds()); 3308 } 3309 3310 3311 void 3312 BView::InvertRect(BRect rect) 3313 { 3314 if (fOwner) { 3315 check_lock(); 3316 3317 fOwner->fLink->StartMessage(AS_LAYER_INVERT_RECT); 3318 fOwner->fLink->Attach<BRect>(rect); 3319 3320 _FlushIfNotInTransaction(); 3321 } 3322 } 3323 3324 3325 // #pragma mark - 3326 // View Hierarchy Functions 3327 3328 3329 void 3330 BView::AddChild(BView *child, BView *before) 3331 { 3332 STRACE(("BView(%s)::AddChild(child='%s' before='%s')\n", 3333 this->Name() ? this->Name(): "NULL", 3334 child && child->Name() ? child->Name(): "NULL", 3335 before && before->Name() ? before->Name(): "NULL")); 3336 3337 if (!_AddChild(child, before)) 3338 return; 3339 3340 if (fLayoutData->fLayout) 3341 fLayoutData->fLayout->AddView(child); 3342 } 3343 3344 3345 bool 3346 BView::AddChild(BLayoutItem* child) 3347 { 3348 if (!fLayoutData->fLayout) 3349 return false; 3350 return fLayoutData->fLayout->AddItem(child); 3351 } 3352 3353 3354 bool 3355 BView::_AddChild(BView *child, BView *before) 3356 { 3357 if (!child) 3358 return false; 3359 3360 if (child->fParent != NULL) { 3361 printf("BView::_AddChild(): child %p already has parent %p\n", child , child->fParent); 3362 debugger("AddChild failed - the view already has a parent."); 3363 return false; 3364 } 3365 3366 bool lockedOwner = false; 3367 if (fOwner && !fOwner->IsLocked()) { 3368 fOwner->Lock(); 3369 lockedOwner = true; 3370 } 3371 3372 if (!_AddChildToList(child, before)) { 3373 debugger("AddChild failed!"); 3374 if (lockedOwner) 3375 fOwner->Unlock(); 3376 return false; 3377 } 3378 3379 if (fOwner) { 3380 check_lock(); 3381 3382 child->_SetOwner(fOwner); 3383 child->_CreateSelf(); 3384 child->_Attach(); 3385 3386 if (lockedOwner) 3387 fOwner->Unlock(); 3388 } 3389 3390 InvalidateLayout(); 3391 3392 return true; 3393 } 3394 3395 3396 bool 3397 BView::RemoveChild(BView *child) 3398 { 3399 STRACE(("BView(%s)::RemoveChild(%s)\n", Name(), child->Name())); 3400 3401 if (!child) 3402 return false; 3403 3404 return child->RemoveSelf(); 3405 } 3406 3407 int32 3408 BView::CountChildren() const 3409 { 3410 check_lock_no_pick(); 3411 3412 uint32 count = 0; 3413 BView *child = fFirstChild; 3414 3415 while (child != NULL) { 3416 count++; 3417 child = child->fNextSibling; 3418 } 3419 3420 return count; 3421 } 3422 3423 3424 BView * 3425 BView::ChildAt(int32 index) const 3426 { 3427 check_lock_no_pick(); 3428 3429 BView *child = fFirstChild; 3430 while (child != NULL && index-- > 0) { 3431 child = child->fNextSibling; 3432 } 3433 3434 return child; 3435 } 3436 3437 3438 BView * 3439 BView::NextSibling() const 3440 { 3441 return fNextSibling; 3442 } 3443 3444 3445 BView * 3446 BView::PreviousSibling() const 3447 { 3448 return fPreviousSibling; 3449 } 3450 3451 3452 bool 3453 BView::RemoveSelf() 3454 { 3455 if (fParent && fParent->fLayoutData->fLayout) 3456 return fParent->fLayoutData->fLayout->RemoveView(this); 3457 else 3458 return _RemoveSelf(); 3459 } 3460 3461 3462 bool 3463 BView::_RemoveSelf() 3464 { 3465 STRACE(("BView(%s)::RemoveSelf()...\n", Name())); 3466 3467 // Remove this child from its parent 3468 3469 BWindow* owner = fOwner; 3470 check_lock_no_pick(); 3471 3472 if (owner != NULL) { 3473 _UpdateStateForRemove(); 3474 _Detach(); 3475 } 3476 3477 BView* parent = fParent; 3478 if (!parent || !parent->_RemoveChildFromList(this)) 3479 return false; 3480 3481 if (owner != NULL && !fTopLevelView) { 3482 // the top level view is deleted by the app_server automatically 3483 owner->fLink->StartMessage(AS_LAYER_DELETE); 3484 owner->fLink->Attach<int32>(_get_object_token_(this)); 3485 } 3486 3487 parent->InvalidateLayout(); 3488 3489 STRACE(("DONE: BView(%s)::RemoveSelf()\n", Name())); 3490 3491 return true; 3492 } 3493 3494 3495 BView * 3496 BView::Parent() const 3497 { 3498 if (fParent && fParent->fTopLevelView) 3499 return NULL; 3500 3501 return fParent; 3502 } 3503 3504 3505 BView * 3506 BView::FindView(const char *name) const 3507 { 3508 if (name == NULL) 3509 return NULL; 3510 3511 if (Name() != NULL && !strcmp(Name(), name)) 3512 return const_cast<BView *>(this); 3513 3514 BView *child = fFirstChild; 3515 while (child != NULL) { 3516 BView *view = child->FindView(name); 3517 if (view != NULL) 3518 return view; 3519 3520 child = child->fNextSibling; 3521 } 3522 3523 return NULL; 3524 } 3525 3526 3527 void 3528 BView::MoveBy(float deltaX, float deltaY) 3529 { 3530 MoveTo(fParentOffset.x + deltaX, fParentOffset.y + deltaY); 3531 } 3532 3533 3534 void 3535 BView::MoveTo(BPoint where) 3536 { 3537 MoveTo(where.x, where.y); 3538 } 3539 3540 3541 void 3542 BView::MoveTo(float x, float y) 3543 { 3544 if (x == fParentOffset.x && y == fParentOffset.y) 3545 return; 3546 3547 // BeBook says we should do this. And it makes sense. 3548 x = roundf(x); 3549 y = roundf(y); 3550 3551 if (fOwner) { 3552 check_lock(); 3553 fOwner->fLink->StartMessage(AS_LAYER_MOVE_TO); 3554 fOwner->fLink->Attach<float>(x); 3555 fOwner->fLink->Attach<float>(y); 3556 3557 fState->valid_flags |= B_VIEW_FRAME_BIT; 3558 3559 _FlushIfNotInTransaction(); 3560 } 3561 3562 _MoveTo((int32)x, (int32)y); 3563 } 3564 3565 3566 void 3567 BView::ResizeBy(float deltaWidth, float deltaHeight) 3568 { 3569 // TODO: this doesn't look like it would work correctly with scrolled views 3570 3571 // NOTE: I think this check makes sense, but I didn't 3572 // test what R5 does. 3573 if (fBounds.right + deltaWidth < 0) 3574 deltaWidth = -fBounds.right; 3575 if (fBounds.bottom + deltaHeight < 0) 3576 deltaHeight = -fBounds.bottom; 3577 3578 // BeBook says we should do this. And it makes sense. 3579 deltaWidth = roundf(deltaWidth); 3580 deltaHeight = roundf(deltaHeight); 3581 3582 if (deltaWidth == 0 && deltaHeight == 0) 3583 return; 3584 3585 if (fOwner) { 3586 check_lock(); 3587 fOwner->fLink->StartMessage(AS_LAYER_RESIZE_TO); 3588 3589 fOwner->fLink->Attach<float>(fBounds.right + deltaWidth); 3590 fOwner->fLink->Attach<float>(fBounds.bottom + deltaHeight); 3591 3592 fState->valid_flags |= B_VIEW_FRAME_BIT; 3593 3594 _FlushIfNotInTransaction(); 3595 } 3596 3597 _ResizeBy((int32)deltaWidth, (int32)deltaHeight); 3598 } 3599 3600 3601 void 3602 BView::ResizeTo(float width, float height) 3603 { 3604 ResizeBy(width - fBounds.Width(), height - fBounds.Height()); 3605 } 3606 3607 3608 // #pragma mark - 3609 // Inherited Methods (from BHandler) 3610 3611 3612 status_t 3613 BView::GetSupportedSuites(BMessage *data) 3614 { 3615 if (data == NULL) 3616 return B_BAD_VALUE; 3617 3618 status_t status = data->AddString("suites", "suite/vnd.Be-view"); 3619 BPropertyInfo propertyInfo(sViewPropInfo); 3620 if (status == B_OK) 3621 status = data->AddFlat("messages", &propertyInfo); 3622 if (status == B_OK) 3623 return BHandler::GetSupportedSuites(data); 3624 return status; 3625 } 3626 3627 3628 BHandler * 3629 BView::ResolveSpecifier(BMessage *msg, int32 index, BMessage *specifier, 3630 int32 what, const char *property) 3631 { 3632 if (msg->what == B_WINDOW_MOVE_BY 3633 || msg->what == B_WINDOW_MOVE_TO) 3634 return this; 3635 3636 BPropertyInfo propertyInfo(sViewPropInfo); 3637 status_t err = B_BAD_SCRIPT_SYNTAX; 3638 BMessage replyMsg(B_REPLY); 3639 3640 switch (propertyInfo.FindMatch(msg, index, specifier, what, property)) { 3641 case 0: 3642 case 1: 3643 case 2: 3644 case 3: 3645 case 5: 3646 return this; 3647 3648 case 4: 3649 if (fShelf) { 3650 msg->PopSpecifier(); 3651 return fShelf; 3652 } 3653 3654 err = B_NAME_NOT_FOUND; 3655 replyMsg.AddString("message", "This window doesn't have a shelf"); 3656 break; 3657 3658 case 6: { 3659 if (!fFirstChild) { 3660 err = B_NAME_NOT_FOUND; 3661 replyMsg.AddString("message", "This window doesn't have children."); 3662 break; 3663 } 3664 BView *child = NULL; 3665 switch (what) { 3666 case B_INDEX_SPECIFIER: { 3667 int32 index; 3668 err = specifier->FindInt32("index", &index); 3669 if (err == B_OK) 3670 child = ChildAt(index); 3671 break; 3672 } 3673 case B_REVERSE_INDEX_SPECIFIER: { 3674 int32 rindex; 3675 err = specifier->FindInt32("index", &rindex); 3676 if (err == B_OK) 3677 child = ChildAt(CountChildren() - rindex); 3678 break; 3679 } 3680 case B_NAME_SPECIFIER: { 3681 const char *name; 3682 err = specifier->FindString("name", &name); 3683 if (err == B_OK) 3684 child = FindView(name); 3685 break; 3686 } 3687 } 3688 3689 if (child != NULL) { 3690 msg->PopSpecifier(); 3691 return child; 3692 } 3693 3694 if (err == B_OK) 3695 err = B_BAD_INDEX; 3696 replyMsg.AddString("message", "Cannot find view at/with specified index/name."); 3697 break; 3698 } 3699 default: 3700 return BHandler::ResolveSpecifier(msg, index, specifier, what, property); 3701 } 3702 3703 if (err < B_OK) { 3704 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 3705 3706 if (err == B_BAD_SCRIPT_SYNTAX) 3707 replyMsg.AddString("message", "Didn't understand the specifier(s)"); 3708 else 3709 replyMsg.AddString("message", strerror(err)); 3710 } 3711 3712 replyMsg.AddInt32("error", err); 3713 msg->SendReply(&replyMsg); 3714 return NULL; 3715 } 3716 3717 3718 void 3719 BView::MessageReceived(BMessage *msg) 3720 { 3721 if (!msg->HasSpecifiers()) { 3722 switch (msg->what) { 3723 case B_VIEW_RESIZED: 3724 // By the time the message arrives, the bounds may have 3725 // changed already, that's why we don't use the values 3726 // in the message itself. 3727 FrameResized(fBounds.Width(), fBounds.Height()); 3728 break; 3729 3730 case B_VIEW_MOVED: 3731 FrameMoved(fParentOffset); 3732 break; 3733 3734 case B_MOUSE_WHEEL_CHANGED: 3735 { 3736 float deltaX = 0.0f, deltaY = 0.0f; 3737 3738 BScrollBar *horizontal = ScrollBar(B_HORIZONTAL); 3739 if (horizontal != NULL) 3740 msg->FindFloat("be:wheel_delta_x", &deltaX); 3741 3742 BScrollBar *vertical = ScrollBar(B_VERTICAL); 3743 if (vertical != NULL) 3744 msg->FindFloat("be:wheel_delta_y", &deltaY); 3745 3746 if (deltaX == 0.0f && deltaY == 0.0f) 3747 return; 3748 3749 float smallStep, largeStep; 3750 if (horizontal != NULL) { 3751 horizontal->GetSteps(&smallStep, &largeStep); 3752 3753 // pressing the option key scrolls faster 3754 if (modifiers() & B_OPTION_KEY) 3755 deltaX *= largeStep; 3756 else 3757 deltaX *= smallStep * 3; 3758 3759 horizontal->SetValue(horizontal->Value() + deltaX); 3760 } 3761 3762 if (vertical != NULL) { 3763 vertical->GetSteps(&smallStep, &largeStep); 3764 3765 // pressing the option key scrolls faster 3766 if (modifiers() & B_OPTION_KEY) 3767 deltaY *= largeStep; 3768 else 3769 deltaY *= smallStep * 3; 3770 3771 vertical->SetValue(vertical->Value() + deltaY); 3772 } 3773 break; 3774 } 3775 3776 default: 3777 return BHandler::MessageReceived(msg); 3778 } 3779 3780 return; 3781 } 3782 3783 // Scripting message 3784 3785 BMessage replyMsg(B_REPLY); 3786 status_t err = B_BAD_SCRIPT_SYNTAX; 3787 int32 index; 3788 BMessage specifier; 3789 int32 what; 3790 const char *prop; 3791 3792 if (msg->GetCurrentSpecifier(&index, &specifier, &what, &prop) != B_OK) 3793 return BHandler::MessageReceived(msg); 3794 3795 BPropertyInfo propertyInfo(sViewPropInfo); 3796 switch (propertyInfo.FindMatch(msg, index, &specifier, what, prop)) { 3797 case 0: 3798 err = replyMsg.AddRect("result", Frame()); 3799 break; 3800 case 1: { 3801 BRect newFrame; 3802 err = msg->FindRect("data", &newFrame); 3803 if (err == B_OK) { 3804 MoveTo(newFrame.LeftTop()); 3805 ResizeTo(newFrame.right, newFrame.bottom); 3806 } 3807 break; 3808 } 3809 case 2: 3810 err = replyMsg.AddBool( "result", IsHidden()); 3811 break; 3812 case 3: { 3813 bool newHiddenState; 3814 err = msg->FindBool("data", &newHiddenState); 3815 if (err == B_OK) { 3816 if (!IsHidden() && newHiddenState == true) 3817 Hide(); 3818 else if (IsHidden() && newHiddenState == false) 3819 Show(); 3820 } 3821 } 3822 case 5: 3823 err = replyMsg.AddInt32("result", CountChildren()); 3824 break; 3825 default: 3826 return BHandler::MessageReceived(msg); 3827 } 3828 3829 if (err < B_OK) { 3830 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 3831 3832 if (err == B_BAD_SCRIPT_SYNTAX) 3833 replyMsg.AddString("message", "Didn't understand the specifier(s)"); 3834 else 3835 replyMsg.AddString("message", strerror(err)); 3836 } 3837 3838 replyMsg.AddInt32("error", err); 3839 msg->SendReply(&replyMsg); 3840 } 3841 3842 3843 status_t 3844 BView::Perform(perform_code d, void* arg) 3845 { 3846 return B_BAD_VALUE; 3847 } 3848 3849 3850 // #pragma mark - Layout Functions 3851 3852 3853 BSize 3854 BView::MinSize() 3855 { 3856 // TODO: make sure this works correctly when some methods are overridden 3857 float width, height; 3858 GetPreferredSize(&width, &height); 3859 3860 return BLayoutUtils::ComposeSize(fLayoutData->fMinSize, 3861 (fLayoutData->fLayout ? fLayoutData->fLayout->MinSize() 3862 : BSize(width, height))); 3863 } 3864 3865 3866 BSize 3867 BView::MaxSize() 3868 { 3869 return BLayoutUtils::ComposeSize(fLayoutData->fMaxSize, 3870 (fLayoutData->fLayout ? fLayoutData->fLayout->MaxSize() 3871 : BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED))); 3872 } 3873 3874 3875 BSize 3876 BView::PreferredSize() 3877 { 3878 // TODO: make sure this works correctly when some methods are overridden 3879 float width, height; 3880 GetPreferredSize(&width, &height); 3881 3882 return BLayoutUtils::ComposeSize(fLayoutData->fPreferredSize, 3883 (fLayoutData->fLayout ? fLayoutData->fLayout->PreferredSize() 3884 : BSize(width, height))); 3885 } 3886 3887 3888 BAlignment 3889 BView::Alignment() 3890 { 3891 return BLayoutUtils::ComposeAlignment(fLayoutData->fAlignment, 3892 (fLayoutData->fLayout ? fLayoutData->fLayout->Alignment() 3893 : BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER))); 3894 } 3895 3896 3897 void 3898 BView::SetExplicitMinSize(BSize size) 3899 { 3900 fLayoutData->fMinSize = size; 3901 InvalidateLayout(); 3902 } 3903 3904 3905 void 3906 BView::SetExplicitMaxSize(BSize size) 3907 { 3908 fLayoutData->fMaxSize = size; 3909 InvalidateLayout(); 3910 } 3911 3912 3913 void 3914 BView::SetExplicitPreferredSize(BSize size) 3915 { 3916 fLayoutData->fPreferredSize = size; 3917 InvalidateLayout(); 3918 } 3919 3920 3921 void 3922 BView::SetExplicitAlignment(BAlignment alignment) 3923 { 3924 fLayoutData->fAlignment = alignment; 3925 InvalidateLayout(); 3926 } 3927 3928 3929 BSize 3930 BView::ExplicitMinSize() const 3931 { 3932 return fLayoutData->fMinSize; 3933 } 3934 3935 3936 BSize 3937 BView::ExplicitMaxSize() const 3938 { 3939 return fLayoutData->fMaxSize; 3940 } 3941 3942 3943 BSize 3944 BView::ExplicitPreferredSize() const 3945 { 3946 return fLayoutData->fPreferredSize; 3947 } 3948 3949 3950 BAlignment 3951 BView::ExplicitAlignment() const 3952 { 3953 return fLayoutData->fAlignment; 3954 } 3955 3956 3957 bool 3958 BView::HasHeightForWidth() 3959 { 3960 return (fLayoutData->fLayout 3961 ? fLayoutData->fLayout->HasHeightForWidth() : false); 3962 } 3963 3964 3965 void 3966 BView::GetHeightForWidth(float width, float* min, float* max, float* preferred) 3967 { 3968 if (fLayoutData->fLayout) 3969 fLayoutData->fLayout->GetHeightForWidth(width, min, max, preferred); 3970 } 3971 3972 3973 void 3974 BView::SetLayout(BLayout* layout) 3975 { 3976 if (layout == fLayoutData->fLayout) 3977 return; 3978 3979 fFlags |= B_SUPPORTS_LAYOUT; 3980 3981 // unset and delete the old layout 3982 if (fLayoutData->fLayout) { 3983 fLayoutData->fLayout->SetView(NULL); 3984 delete fLayoutData->fLayout; 3985 } 3986 3987 fLayoutData->fLayout = layout; 3988 3989 if (fLayoutData->fLayout) { 3990 fLayoutData->fLayout->SetView(this); 3991 3992 // add all children 3993 int count = CountChildren(); 3994 for (int i = 0; i < count; i++) 3995 fLayoutData->fLayout->AddView(ChildAt(i)); 3996 } 3997 3998 InvalidateLayout(); 3999 } 4000 4001 4002 BLayout* 4003 BView::GetLayout() const 4004 { 4005 return fLayoutData->fLayout; 4006 } 4007 4008 4009 void 4010 BView::InvalidateLayout(bool descendants) 4011 { 4012 if (fLayoutData->fLayoutValid && !fLayoutData->fLayoutInProgress 4013 && fLayoutData->fLayoutInvalidationDisabled == 0) { 4014 if (fParent && fParent->fLayoutData->fLayoutValid) 4015 fParent->InvalidateLayout(false); 4016 4017 fLayoutData->fLayoutValid = false; 4018 4019 if (fLayoutData->fLayout) 4020 fLayoutData->fLayout->InvalidateLayout(); 4021 4022 if (descendants) { 4023 int count = CountChildren(); 4024 for (int i = 0; i < count; i++) 4025 ChildAt(i)->InvalidateLayout(descendants); 4026 } 4027 4028 if (fTopLevelView) { 4029 // trigger layout process 4030 if (fOwner) 4031 fOwner->PostMessage(B_LAYOUT_WINDOW); 4032 } 4033 } 4034 } 4035 4036 4037 void 4038 BView::EnableLayoutInvalidation() 4039 { 4040 if (fLayoutData->fLayoutInvalidationDisabled > 0) 4041 fLayoutData->fLayoutInvalidationDisabled--; 4042 } 4043 4044 4045 void 4046 BView::DisableLayoutInvalidation() 4047 { 4048 fLayoutData->fLayoutInvalidationDisabled++; 4049 } 4050 4051 4052 BLayoutContext* 4053 BView::LayoutContext() const 4054 { 4055 return fLayoutData->fLayoutContext; 4056 } 4057 4058 4059 void 4060 BView::Layout(bool force) 4061 { 4062 BLayoutContext context; 4063 _Layout(force, &context); 4064 } 4065 4066 4067 void 4068 BView::Relayout() 4069 { 4070 if (fLayoutData->fLayoutValid && !fLayoutData->fLayoutInProgress) { 4071 fLayoutData->fNeedsRelayout = true; 4072 4073 // Layout() is recursive, that is if the parent view is currently laid 4074 // out, we don't call layout() on this view, but wait for the parent's 4075 // Layout() to do that for us. 4076 if (!fParent || !fParent->fLayoutData->fLayoutInProgress) 4077 Layout(false); 4078 } 4079 } 4080 4081 4082 void 4083 BView::DoLayout() 4084 { 4085 if (fLayoutData->fLayout) 4086 fLayoutData->fLayout->LayoutView(); 4087 } 4088 4089 4090 void 4091 BView::_Layout(bool force, BLayoutContext* context) 4092 { 4093 //printf("%p->BView::_Layout(%d, %p)\n", this, force, context); 4094 //printf(" fNeedsRelayout: %d, fLayoutValid: %d, fLayoutInProgress: %d\n", 4095 //fLayoutData->fNeedsRelayout, fLayoutData->fLayoutValid, fLayoutData->fLayoutInProgress); 4096 if (fLayoutData->fNeedsRelayout || !fLayoutData->fLayoutValid || force) { 4097 fLayoutData->fLayoutValid = false; 4098 4099 if (fLayoutData->fLayoutInProgress) 4100 return; 4101 4102 BLayoutContext* oldContext = fLayoutData->fLayoutContext; 4103 fLayoutData->fLayoutContext = context; 4104 4105 fLayoutData->fLayoutInProgress = true; 4106 DoLayout(); 4107 fLayoutData->fLayoutInProgress = false; 4108 4109 fLayoutData->fLayoutValid = true; 4110 fLayoutData->fNeedsRelayout = false; 4111 4112 // layout children 4113 int32 childCount = CountChildren(); 4114 for (int32 i = 0; i < childCount; i++) { 4115 BView* child = ChildAt(i); 4116 if (!child->IsHidden(child)) 4117 child->_Layout(force, context); 4118 } 4119 4120 fLayoutData->fLayoutContext = oldContext; 4121 4122 // invalidate the drawn content, if requested 4123 if (fFlags & B_INVALIDATE_AFTER_LAYOUT) 4124 Invalidate(); 4125 } 4126 } 4127 4128 4129 // #pragma mark - 4130 // Private Functions 4131 4132 4133 void 4134 BView::_InitData(BRect frame, const char *name, uint32 resizingMode, uint32 flags) 4135 { 4136 // Info: The name of the view is set by BHandler constructor 4137 4138 STRACE(("BView::InitData: enter\n")); 4139 4140 // initialize members 4141 fFlags = (resizingMode & _RESIZE_MASK_) | (flags & ~_RESIZE_MASK_); 4142 4143 // handle rounding 4144 frame.left = roundf(frame.left); 4145 frame.top = roundf(frame.top); 4146 frame.right = roundf(frame.right); 4147 frame.bottom = roundf(frame.bottom); 4148 4149 fParentOffset.Set(frame.left, frame.top); 4150 4151 fOwner = NULL; 4152 fParent = NULL; 4153 fNextSibling = NULL; 4154 fPreviousSibling = NULL; 4155 fFirstChild = NULL; 4156 4157 fShowLevel = 0; 4158 fTopLevelView = false; 4159 4160 cpicture = NULL; 4161 comm = NULL; 4162 4163 fVerScroller = NULL; 4164 fHorScroller = NULL; 4165 4166 f_is_printing = false; 4167 fAttached = false; 4168 4169 fState = new BPrivate::ViewState; 4170 4171 fBounds = frame.OffsetToCopy(B_ORIGIN); 4172 fShelf = NULL; 4173 4174 fEventMask = 0; 4175 fEventOptions = 0; 4176 4177 fLayoutData = new LayoutData; 4178 } 4179 4180 4181 void 4182 BView::removeCommArray() 4183 { 4184 if (comm) { 4185 delete [] comm->array; 4186 delete comm; 4187 comm = NULL; 4188 } 4189 } 4190 4191 4192 void 4193 BView::_SetOwner(BWindow *newOwner) 4194 { 4195 if (!newOwner) 4196 removeCommArray(); 4197 4198 if (fOwner != newOwner && fOwner) { 4199 if (fOwner->fFocus == this) 4200 MakeFocus(false); 4201 4202 if (fOwner->fLastMouseMovedView == this) 4203 fOwner->fLastMouseMovedView = NULL; 4204 4205 fOwner->RemoveHandler(this); 4206 if (fShelf) 4207 fOwner->RemoveHandler(fShelf); 4208 } 4209 4210 if (newOwner && newOwner != fOwner) { 4211 newOwner->AddHandler(this); 4212 if (fShelf) 4213 newOwner->AddHandler(fShelf); 4214 4215 if (fTopLevelView) 4216 SetNextHandler(newOwner); 4217 else 4218 SetNextHandler(fParent); 4219 } 4220 4221 fOwner = newOwner; 4222 4223 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) 4224 child->_SetOwner(newOwner); 4225 } 4226 4227 4228 void 4229 BView::DoPictureClip(BPicture *picture, BPoint where, 4230 bool invert, bool sync) 4231 { 4232 if (!picture) 4233 return; 4234 4235 if (do_owner_check()) { 4236 fOwner->fLink->StartMessage(AS_LAYER_CLIP_TO_PICTURE); 4237 fOwner->fLink->Attach<int32>(picture->token); 4238 fOwner->fLink->Attach<BPoint>(where); 4239 fOwner->fLink->Attach<bool>(invert); 4240 4241 // TODO: I think that "sync" means another thing here: 4242 // the bebook, at least, says so. 4243 if (sync) 4244 fOwner->fLink->Flush(); 4245 4246 fState->valid_flags &= ~B_VIEW_CLIP_REGION_BIT; 4247 } 4248 4249 fState->archiving_flags |= B_VIEW_CLIP_REGION_BIT; 4250 } 4251 4252 4253 bool 4254 BView::_RemoveChildFromList(BView* child) 4255 { 4256 if (child->fParent != this) 4257 return false; 4258 4259 if (fFirstChild == child) { 4260 // it's the first view in the list 4261 fFirstChild = child->fNextSibling; 4262 } else { 4263 // there must be a previous sibling 4264 child->fPreviousSibling->fNextSibling = child->fNextSibling; 4265 } 4266 4267 if (child->fNextSibling) 4268 child->fNextSibling->fPreviousSibling = child->fPreviousSibling; 4269 4270 child->fParent = NULL; 4271 child->fNextSibling = NULL; 4272 child->fPreviousSibling = NULL; 4273 4274 return true; 4275 } 4276 4277 4278 bool 4279 BView::_AddChildToList(BView* child, BView* before) 4280 { 4281 if (!child) 4282 return false; 4283 if (child->fParent != NULL) { 4284 debugger("View already belongs to someone else"); 4285 return false; 4286 } 4287 if (before != NULL && before->fParent != this) { 4288 debugger("Invalid before view"); 4289 return false; 4290 } 4291 4292 if (before != NULL) { 4293 // add view before this one 4294 child->fNextSibling = before; 4295 child->fPreviousSibling = before->fPreviousSibling; 4296 if (child->fPreviousSibling != NULL) 4297 child->fPreviousSibling->fNextSibling = child; 4298 4299 before->fPreviousSibling = child; 4300 if (fFirstChild == before) 4301 fFirstChild = child; 4302 } else { 4303 // add view to the end of the list 4304 BView *last = fFirstChild; 4305 while (last != NULL && last->fNextSibling != NULL) { 4306 last = last->fNextSibling; 4307 } 4308 4309 if (last != NULL) { 4310 last->fNextSibling = child; 4311 child->fPreviousSibling = last; 4312 } else { 4313 fFirstChild = child; 4314 child->fPreviousSibling = NULL; 4315 } 4316 4317 child->fNextSibling = NULL; 4318 } 4319 4320 child->fParent = this; 4321 return true; 4322 } 4323 4324 4325 /*! \brief Creates the server counterpart of this view. 4326 This is only done for views that are part of the view hierarchy, ie. when 4327 they are attached to a window. 4328 RemoveSelf() deletes the server object again. 4329 */ 4330 bool 4331 BView::_CreateSelf() 4332 { 4333 // AS_LAYER_CREATE & AS_LAYER_CREATE_ROOT do not use the 4334 // current view mechanism via check_lock() - the token 4335 // of the view and its parent are both send to the server. 4336 4337 if (fTopLevelView) 4338 fOwner->fLink->StartMessage(AS_LAYER_CREATE_ROOT); 4339 else 4340 fOwner->fLink->StartMessage(AS_LAYER_CREATE); 4341 4342 fOwner->fLink->Attach<int32>(_get_object_token_(this)); 4343 fOwner->fLink->AttachString(Name()); 4344 fOwner->fLink->Attach<BRect>(Frame()); 4345 fOwner->fLink->Attach<BPoint>(LeftTop()); 4346 fOwner->fLink->Attach<uint32>(ResizingMode()); 4347 fOwner->fLink->Attach<uint32>(fEventMask); 4348 fOwner->fLink->Attach<uint32>(fEventOptions); 4349 fOwner->fLink->Attach<uint32>(Flags()); 4350 fOwner->fLink->Attach<bool>(IsHidden(this)); 4351 fOwner->fLink->Attach<rgb_color>(fState->view_color); 4352 if (fTopLevelView) 4353 fOwner->fLink->Attach<int32>(B_NULL_TOKEN); 4354 else 4355 fOwner->fLink->Attach<int32>(_get_object_token_(fParent)); 4356 fOwner->fLink->Flush(); 4357 4358 do_owner_check(); 4359 fState->UpdateServerState(*fOwner->fLink); 4360 4361 // we create all its children, too 4362 4363 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 4364 child->_CreateSelf(); 4365 } 4366 4367 fOwner->fLink->Flush(); 4368 return true; 4369 } 4370 4371 4372 /*! 4373 Sets the new view position. 4374 It doesn't contact the server, though - the only case where this 4375 is called outside of MoveTo() is as reaction of moving a view 4376 in the server (a.k.a. B_WINDOW_RESIZED). 4377 It also calls the BView's FrameMoved() hook. 4378 */ 4379 void 4380 BView::_MoveTo(int32 x, int32 y) 4381 { 4382 fParentOffset.Set(x, y); 4383 4384 if (Window() != NULL && fFlags & B_FRAME_EVENTS) { 4385 BMessage moved(B_VIEW_MOVED); 4386 moved.AddInt64("when", system_time()); 4387 moved.AddPoint("where", BPoint(x, y)); 4388 4389 BMessenger target(this); 4390 target.SendMessage(&moved); 4391 } 4392 } 4393 4394 4395 /*! 4396 Computes the actual new frame size and recalculates the size of 4397 the children as well. 4398 It doesn't contact the server, though - the only case where this 4399 is called outside of ResizeBy() is as reaction of resizing a view 4400 in the server (a.k.a. B_WINDOW_RESIZED). 4401 It also calls the BView's FrameResized() hook. 4402 */ 4403 void 4404 BView::_ResizeBy(int32 deltaWidth, int32 deltaHeight) 4405 { 4406 fBounds.right += deltaWidth; 4407 fBounds.bottom += deltaHeight; 4408 4409 if (Window() == NULL) { 4410 // we're not supposed to exercise the resizing code in case 4411 // we haven't been attached to a window yet 4412 return; 4413 } 4414 4415 // layout the children 4416 if (fFlags & B_SUPPORTS_LAYOUT) { 4417 Relayout(); 4418 } else { 4419 for (BView* child = fFirstChild; child; child = child->fNextSibling) 4420 child->_ParentResizedBy(deltaWidth, deltaHeight); 4421 } 4422 4423 if (fFlags & B_FRAME_EVENTS) { 4424 BMessage resized(B_VIEW_RESIZED); 4425 resized.AddInt64("when", system_time()); 4426 resized.AddFloat("width", fBounds.Width()); 4427 resized.AddFloat("height", fBounds.Height()); 4428 4429 BMessenger target(this); 4430 target.SendMessage(&resized); 4431 } 4432 } 4433 4434 4435 /*! 4436 Relayouts the view according to its resizing mode. 4437 */ 4438 void 4439 BView::_ParentResizedBy(int32 x, int32 y) 4440 { 4441 uint32 resizingMode = fFlags & _RESIZE_MASK_; 4442 BRect newFrame = Frame(); 4443 4444 // follow with left side 4445 if ((resizingMode & 0x0F00U) == _VIEW_RIGHT_ << 8) 4446 newFrame.left += x; 4447 else if ((resizingMode & 0x0F00U) == _VIEW_CENTER_ << 8) 4448 newFrame.left += x / 2; 4449 4450 // follow with right side 4451 if ((resizingMode & 0x000FU) == _VIEW_RIGHT_) 4452 newFrame.right += x; 4453 else if ((resizingMode & 0x000FU) == _VIEW_CENTER_) 4454 newFrame.right += x / 2; 4455 4456 // follow with top side 4457 if ((resizingMode & 0xF000U) == _VIEW_BOTTOM_ << 12) 4458 newFrame.top += y; 4459 else if ((resizingMode & 0xF000U) == _VIEW_CENTER_ << 12) 4460 newFrame.top += y / 2; 4461 4462 // follow with bottom side 4463 if ((resizingMode & 0x00F0U) == _VIEW_BOTTOM_ << 4) 4464 newFrame.bottom += y; 4465 else if ((resizingMode & 0x00F0U) == _VIEW_CENTER_ << 4) 4466 newFrame.bottom += y / 2; 4467 4468 if (newFrame.LeftTop() != fParentOffset) { 4469 // move view 4470 _MoveTo((int32)roundf(newFrame.left), (int32)roundf(newFrame.top)); 4471 } 4472 4473 if (newFrame != Frame()) { 4474 // resize view 4475 int32 widthDiff = (int32)(newFrame.Width() - fBounds.Width()); 4476 int32 heightDiff = (int32)(newFrame.Height() - fBounds.Height()); 4477 _ResizeBy(widthDiff, heightDiff); 4478 } 4479 } 4480 4481 4482 void 4483 BView::_Activate(bool active) 4484 { 4485 WindowActivated(active); 4486 4487 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 4488 child->_Activate(active); 4489 } 4490 } 4491 4492 4493 void 4494 BView::_Attach() 4495 { 4496 AttachedToWindow(); 4497 fAttached = true; 4498 4499 // after giving the view a chance to do this itself, 4500 // check for the B_PULSE_NEEDED flag and make sure the 4501 // window set's up the pulse messaging 4502 if (fOwner) { 4503 if (fFlags & B_PULSE_NEEDED) { 4504 check_lock_no_pick(); 4505 if (fOwner->fPulseRunner == NULL) 4506 fOwner->SetPulseRate(fOwner->PulseRate()); 4507 } 4508 4509 if (!fOwner->IsHidden()) 4510 Invalidate(); 4511 } 4512 4513 for (BView* child = fFirstChild; child != NULL; child = child->fNextSibling) { 4514 // we need to check for fAttached as new views could have been 4515 // added in AttachedToWindow() - and those are already attached 4516 if (!child->fAttached) 4517 child->_Attach(); 4518 } 4519 4520 AllAttached(); 4521 } 4522 4523 4524 void 4525 BView::_Detach() 4526 { 4527 DetachedFromWindow(); 4528 fAttached = false; 4529 4530 for (BView* child = fFirstChild; child != NULL; child = child->fNextSibling) { 4531 child->_Detach(); 4532 } 4533 4534 AllDetached(); 4535 4536 if (fOwner) { 4537 check_lock_no_pick(); 4538 4539 if (!fOwner->IsHidden()) 4540 Invalidate(); 4541 4542 // make sure our owner doesn't need us anymore 4543 4544 if (fOwner->CurrentFocus() == this) 4545 MakeFocus(false); 4546 4547 if (fOwner->fDefaultButton == this) 4548 fOwner->SetDefaultButton(NULL); 4549 4550 if (fOwner->fKeyMenuBar == this) 4551 fOwner->fKeyMenuBar = NULL; 4552 4553 if (fOwner->fLastMouseMovedView == this) 4554 fOwner->fLastMouseMovedView = NULL; 4555 4556 if (fOwner->fLastViewToken == _get_object_token_(this)) 4557 fOwner->fLastViewToken = B_NULL_TOKEN; 4558 4559 _SetOwner(NULL); 4560 } 4561 } 4562 4563 4564 void 4565 BView::_Draw(BRect updateRectScreen) 4566 { 4567 if (IsHidden(this)) 4568 return; 4569 4570 check_lock(); 4571 4572 ConvertFromScreen(&updateRectScreen); 4573 BRect updateRect = Bounds() & updateRectScreen; 4574 4575 if (Flags() & B_WILL_DRAW) { 4576 // TODO: make states robust 4577 PushState(); 4578 Draw(updateRect); 4579 PopState(); 4580 Flush(); 4581 // } else { 4582 // ViewColor() == B_TRANSPARENT_COLOR and no B_WILL_DRAW 4583 // -> View is simply not drawn at all 4584 } 4585 4586 // for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 4587 // BRect rect = child->Frame(); 4588 // if (!updateRect.Intersects(rect)) 4589 // continue; 4590 // 4591 // // get new update rect in child coordinates 4592 // rect = updateRect & rect; 4593 // child->ConvertFromParent(&rect); 4594 // 4595 // child->_Draw(rect); 4596 // } 4597 // 4598 // if (Flags() & B_DRAW_ON_CHILDREN) { 4599 // // TODO: Since we have hard clipping in the app_server, 4600 // // a view can never draw "on top of it's child views" as 4601 // // the BeBook describes. 4602 // // (TODO: Test if this is really possible in BeOS.) 4603 // PushState(); 4604 // DrawAfterChildren(updateRect); 4605 // PopState(); 4606 // Flush(); 4607 // } 4608 } 4609 4610 4611 void 4612 BView::_Pulse() 4613 { 4614 if (Flags() & B_PULSE_NEEDED) 4615 Pulse(); 4616 4617 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 4618 child->_Pulse(); 4619 } 4620 } 4621 4622 4623 void 4624 BView::_UpdateStateForRemove() 4625 { 4626 if (!do_owner_check()) 4627 return; 4628 4629 fState->UpdateFrom(*fOwner->fLink); 4630 if (!fState->IsValid(B_VIEW_FRAME_BIT)) { 4631 fOwner->fLink->StartMessage(AS_LAYER_GET_COORD); 4632 4633 status_t code; 4634 if (fOwner->fLink->FlushWithReply(code) == B_OK 4635 && code == B_OK) { 4636 fOwner->fLink->Read<BPoint>(&fParentOffset); 4637 fOwner->fLink->Read<BRect>(&fBounds); 4638 fState->valid_flags |= B_VIEW_FRAME_BIT; 4639 } 4640 } 4641 4642 // update children as well 4643 4644 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 4645 if (child->fOwner) 4646 child->_UpdateStateForRemove(); 4647 } 4648 } 4649 4650 4651 inline void 4652 BView::_UpdatePattern(::pattern pattern) 4653 { 4654 if (fState->IsValid(B_VIEW_PATTERN_BIT) && pattern == fState->pattern) 4655 return; 4656 4657 if (fOwner) { 4658 check_lock(); 4659 4660 fOwner->fLink->StartMessage(AS_LAYER_SET_PATTERN); 4661 fOwner->fLink->Attach< ::pattern>(pattern); 4662 4663 fState->valid_flags |= B_VIEW_PATTERN_BIT; 4664 } 4665 4666 fState->pattern = pattern; 4667 } 4668 4669 4670 void 4671 BView::_FlushIfNotInTransaction() 4672 { 4673 if (!fOwner->fInTransaction) { 4674 fOwner->Flush(); 4675 } 4676 } 4677 4678 4679 BShelf * 4680 BView::_Shelf() const 4681 { 4682 return fShelf; 4683 } 4684 4685 4686 void 4687 BView::_SetShelf(BShelf *shelf) 4688 { 4689 if (fShelf != NULL && fOwner != NULL) 4690 fOwner->RemoveHandler(fShelf); 4691 4692 fShelf = shelf; 4693 4694 if (fShelf != NULL && fOwner != NULL) 4695 fOwner->AddHandler(fShelf); 4696 } 4697 4698 4699 status_t 4700 BView::_SetViewBitmap(const BBitmap* bitmap, BRect srcRect, 4701 BRect dstRect, uint32 followFlags, uint32 options) 4702 { 4703 if (!do_owner_check()) 4704 return B_ERROR; 4705 4706 int32 serverToken = bitmap ? bitmap->_ServerToken() : -1; 4707 4708 fOwner->fLink->StartMessage(AS_LAYER_SET_VIEW_BITMAP); 4709 fOwner->fLink->Attach<int32>(serverToken); 4710 fOwner->fLink->Attach<BRect>(srcRect); 4711 fOwner->fLink->Attach<BRect>(dstRect); 4712 fOwner->fLink->Attach<int32>(followFlags); 4713 fOwner->fLink->Attach<int32>(options); 4714 4715 status_t status = B_ERROR; 4716 fOwner->fLink->FlushWithReply(status); 4717 4718 return status; 4719 } 4720 4721 4722 bool 4723 BView::do_owner_check() const 4724 { 4725 STRACE(("BView(%s)::do_owner_check()...", Name())); 4726 4727 int32 serverToken = _get_object_token_(this); 4728 4729 if (fOwner == NULL) { 4730 debugger("View method requires owner and doesn't have one."); 4731 return false; 4732 } 4733 4734 fOwner->check_lock(); 4735 4736 if (fOwner->fLastViewToken != serverToken) { 4737 STRACE(("contacting app_server... sending token: %ld\n", serverToken)); 4738 fOwner->fLink->StartMessage(AS_SET_CURRENT_LAYER); 4739 fOwner->fLink->Attach<int32>(serverToken); 4740 4741 fOwner->fLastViewToken = serverToken; 4742 } else 4743 STRACE(("this is the lastViewToken\n")); 4744 4745 return true; 4746 } 4747 4748 4749 void 4750 BView::check_lock() const 4751 { 4752 STRACE(("BView(%s)::check_lock()...", Name() ? Name(): "NULL")); 4753 4754 if (!fOwner) 4755 return; 4756 4757 fOwner->check_lock(); 4758 4759 int32 serverToken = _get_object_token_(this); 4760 4761 if (fOwner->fLastViewToken != serverToken) { 4762 STRACE(("contacting app_server... sending token: %ld\n", serverToken)); 4763 fOwner->fLink->StartMessage(AS_SET_CURRENT_LAYER); 4764 fOwner->fLink->Attach<int32>(serverToken); 4765 4766 fOwner->fLastViewToken = serverToken; 4767 } else { 4768 STRACE(("quiet2\n")); 4769 } 4770 } 4771 4772 4773 void 4774 BView::check_lock_no_pick() const 4775 { 4776 if (fOwner) 4777 fOwner->check_lock(); 4778 } 4779 4780 4781 bool 4782 BView::do_owner_check_no_pick() const 4783 { 4784 if (fOwner) { 4785 fOwner->check_lock(); 4786 return true; 4787 } else { 4788 debugger("View method requires owner and doesn't have one."); 4789 return false; 4790 } 4791 } 4792 4793 extern "C" void _ReservedView1__5BView() {} 4794 extern "C" void _ReservedView2__5BView() {} 4795 extern "C" void _ReservedView3__5BView() {} 4796 extern "C" void _ReservedView4__5BView() {} 4797 extern "C" void _ReservedView5__5BView() {} 4798 extern "C" void _ReservedView6__5BView() {} 4799 extern "C" void _ReservedView7__5BView() {} 4800 extern "C" void _ReservedView8__5BView() {} 4801 extern "C" void _ReservedView9__5BView() {} 4802 void BView::_ReservedView10(){} 4803 void BView::_ReservedView11(){} 4804 void BView::_ReservedView12(){} 4805 void BView::_ReservedView13(){} 4806 void BView::_ReservedView14(){} 4807 void BView::_ReservedView15(){} 4808 void BView::_ReservedView16(){} 4809 4810 4811 BView::BView(const BView &other) 4812 : BHandler() 4813 { 4814 // this is private and not functional, but exported 4815 } 4816 4817 4818 BView & 4819 BView::operator=(const BView &other) 4820 { 4821 // this is private and not functional, but exported 4822 return *this; 4823 } 4824 4825 4826 void 4827 BView::PrintToStream() 4828 { 4829 printf("BView::PrintToStream()\n"); 4830 printf("\tName: %s\ 4831 \tParent: %s\ 4832 \tFirstChild: %s\ 4833 \tNextSibling: %s\ 4834 \tPrevSibling: %s\ 4835 \tOwner(Window): %s\ 4836 \tToken: %ld\ 4837 \tFlags: %ld\ 4838 \tView origin: (%f,%f)\ 4839 \tView Bounds rectangle: (%f,%f,%f,%f)\ 4840 \tShow level: %d\ 4841 \tTopView?: %s\ 4842 \tBPicture: %s\ 4843 \tVertical Scrollbar %s\ 4844 \tHorizontal Scrollbar %s\ 4845 \tIs Printing?: %s\ 4846 \tShelf?: %s\ 4847 \tEventMask: %ld\ 4848 \tEventOptions: %ld\n", 4849 Name(), 4850 fParent ? fParent->Name() : "NULL", 4851 fFirstChild ? fFirstChild->Name() : "NULL", 4852 fNextSibling ? fNextSibling->Name() : "NULL", 4853 fPreviousSibling ? fPreviousSibling->Name() : "NULL", 4854 fOwner ? fOwner->Name() : "NULL", 4855 _get_object_token_(this), 4856 fFlags, 4857 fParentOffset.x, fParentOffset.y, 4858 fBounds.left, fBounds.top, fBounds.right, fBounds.bottom, 4859 fShowLevel, 4860 fTopLevelView ? "YES" : "NO", 4861 cpicture? "YES" : "NULL", 4862 fVerScroller? "YES" : "NULL", 4863 fHorScroller? "YES" : "NULL", 4864 f_is_printing? "YES" : "NO", 4865 fShelf? "YES" : "NO", 4866 fEventMask, 4867 fEventOptions); 4868 4869 printf("\tState status:\ 4870 \t\tLocalCoordianteSystem: (%f,%f)\ 4871 \t\tPenLocation: (%f,%f)\ 4872 \t\tPenSize: %f\ 4873 \t\tHighColor: [%d,%d,%d,%d]\ 4874 \t\tLowColor: [%d,%d,%d,%d]\ 4875 \t\tViewColor: [%d,%d,%d,%d]\ 4876 \t\tPattern: %llx\ 4877 \t\tDrawingMode: %d\ 4878 \t\tLineJoinMode: %d\ 4879 \t\tLineCapMode: %d\ 4880 \t\tMiterLimit: %f\ 4881 \t\tAlphaSource: %d\ 4882 \t\tAlphaFuntion: %d\ 4883 \t\tScale: %f\ 4884 \t\t(Print)FontAliasing: %s\ 4885 \t\tFont Info:\n", 4886 fState->origin.x, fState->origin.y, 4887 fState->pen_location.x, fState->pen_location.y, 4888 fState->pen_size, 4889 fState->high_color.red, fState->high_color.blue, fState->high_color.green, fState->high_color.alpha, 4890 fState->low_color.red, fState->low_color.blue, fState->low_color.green, fState->low_color.alpha, 4891 fState->view_color.red, fState->view_color.blue, fState->view_color.green, fState->view_color.alpha, 4892 *((uint64*)&(fState->pattern)), 4893 fState->drawing_mode, 4894 fState->line_join, 4895 fState->line_cap, 4896 fState->miter_limit, 4897 fState->alpha_source_mode, 4898 fState->alpha_function_mode, 4899 fState->scale, 4900 fState->font_aliasing? "YES" : "NO"); 4901 4902 fState->font.PrintToStream(); 4903 4904 // TODO: also print the line array. 4905 } 4906 4907 4908 void 4909 BView::PrintTree() 4910 { 4911 int32 spaces = 2; 4912 BView *c = fFirstChild; //c = short for: current 4913 printf( "'%s'\n", Name() ); 4914 if (c != NULL) { 4915 while(true) { 4916 // action block 4917 { 4918 for (int i = 0; i < spaces; i++) 4919 printf(" "); 4920 4921 printf( "'%s'\n", c->Name() ); 4922 } 4923 4924 // go deep 4925 if (c->fFirstChild) { 4926 c = c->fFirstChild; 4927 spaces += 2; 4928 } else { 4929 // go right 4930 if (c->fNextSibling) { 4931 c = c->fNextSibling; 4932 } else { 4933 // go up 4934 while (!c->fParent->fNextSibling && c->fParent != this) { 4935 c = c->fParent; 4936 spaces -= 2; 4937 } 4938 4939 // that enough! We've reached this view. 4940 if (c->fParent == this) 4941 break; 4942 4943 c = c->fParent->fNextSibling; 4944 spaces -= 2; 4945 } 4946 } 4947 } 4948 } 4949 } 4950 4951 4952 /* TODO: 4953 -implement SetDiskMode(). What's with this method? What does it do? test! 4954 does it has something to do with DrawPictureAsync( filename* .. )? 4955 -implement DrawAfterChildren() 4956 */ 4957