1 /* 2 * Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <ScrollView.h> 8 9 #include <ControlLook.h> 10 #include <LayoutUtils.h> 11 #include <Message.h> 12 #include <Region.h> 13 #include <Window.h> 14 15 #include <binary_compatibility/Interface.h> 16 17 static const float kFancyBorderSize = 2; 18 static const float kPlainBorderSize = 1; 19 20 21 BScrollView::BScrollView(const char *name, BView *target, uint32 resizingMode, 22 uint32 flags, bool horizontal, bool vertical, border_style border) 23 : BView(_ComputeFrame(target, horizontal, vertical, border), name, 24 resizingMode, _ModifyFlags(flags, border)), 25 fTarget(target), 26 fBorder(border) 27 { 28 _Init(horizontal, vertical); 29 } 30 31 32 BScrollView::BScrollView(const char* name, BView* target, uint32 flags, 33 bool horizontal, bool vertical, border_style border) 34 : BView(name, _ModifyFlags(flags, border)), 35 fTarget(target), 36 fBorder(border) 37 { 38 _Init(horizontal, vertical); 39 } 40 41 42 BScrollView::BScrollView(BMessage *archive) 43 : BView(archive), 44 fHighlighted(false) 45 { 46 int32 border; 47 fBorder = archive->FindInt32("_style", &border) == B_OK ? 48 (border_style)border : B_FANCY_BORDER; 49 50 // In a shallow archive, we may not have a target anymore. We must 51 // be prepared for this case 52 53 // don't confuse our scroll bars with our (eventual) target 54 int32 firstBar = 0; 55 if (!archive->FindBool("_no_target_")) { 56 fTarget = ChildAt(0); 57 firstBar++; 58 } else 59 fTarget = NULL; 60 61 // search for our scroll bars 62 63 fHorizontalScrollBar = NULL; 64 fVerticalScrollBar = NULL; 65 66 BView *view; 67 while ((view = ChildAt(firstBar++)) != NULL) { 68 BScrollBar *bar = dynamic_cast<BScrollBar *>(view); 69 if (bar == NULL) 70 continue; 71 72 if (bar->Orientation() == B_HORIZONTAL) 73 fHorizontalScrollBar = bar; 74 else if (bar->Orientation() == B_VERTICAL) 75 fVerticalScrollBar = bar; 76 } 77 78 fPreviousWidth = uint16(Bounds().Width()); 79 fPreviousHeight = uint16(Bounds().Height()); 80 } 81 82 83 BScrollView::~BScrollView() 84 { 85 } 86 87 88 // #pragma mark - 89 90 91 BArchivable* 92 BScrollView::Instantiate(BMessage* archive) 93 { 94 if (validate_instantiation(archive, "BScrollView")) 95 return new BScrollView(archive); 96 97 return NULL; 98 } 99 100 101 status_t 102 BScrollView::Archive(BMessage* archive, bool deep) const 103 { 104 status_t status = BView::Archive(archive, deep); 105 if (status != B_OK) 106 return status; 107 108 // If this is a deep archive, the BView class will take care 109 // of our children. 110 111 if (status == B_OK && fBorder != B_FANCY_BORDER) 112 status = archive->AddInt32("_style", fBorder); 113 if (status == B_OK && fTarget == NULL) 114 status = archive->AddBool("_no_target_", true); 115 116 // The highlighted state is not archived, but since it is 117 // usually (or should be) used to indicate focus, this 118 // is probably the right thing to do. 119 120 return status; 121 } 122 123 124 void 125 BScrollView::AttachedToWindow() 126 { 127 BView::AttachedToWindow(); 128 129 if ((fHorizontalScrollBar == NULL && fVerticalScrollBar == NULL) 130 || (fHorizontalScrollBar != NULL && fVerticalScrollBar != NULL) 131 || Window()->Look() != B_DOCUMENT_WINDOW_LOOK) 132 return; 133 134 // If we have only one bar, we need to check if we are in the 135 // bottom right edge of a window with the B_DOCUMENT_LOOK to 136 // adjust the size of the bar to acknowledge the resize knob. 137 138 BRect bounds = ConvertToScreen(Bounds()); 139 BRect windowBounds = Window()->Frame(); 140 141 if (bounds.right - _BorderSize() != windowBounds.right 142 || bounds.bottom - _BorderSize() != windowBounds.bottom) 143 return; 144 145 if (fHorizontalScrollBar) 146 fHorizontalScrollBar->ResizeBy(-B_V_SCROLL_BAR_WIDTH, 0); 147 else if (fVerticalScrollBar) 148 fVerticalScrollBar->ResizeBy(0, -B_H_SCROLL_BAR_HEIGHT); 149 } 150 151 152 void 153 BScrollView::DetachedFromWindow() 154 { 155 BView::DetachedFromWindow(); 156 } 157 158 159 void 160 BScrollView::AllAttached() 161 { 162 BView::AllAttached(); 163 } 164 165 166 void 167 BScrollView::AllDetached() 168 { 169 BView::AllDetached(); 170 } 171 172 173 void 174 BScrollView::Draw(BRect updateRect) 175 { 176 if (be_control_look != NULL) { 177 uint32 flags = 0; 178 if (fHighlighted && Window()->IsActive()) 179 flags |= BControlLook::B_FOCUSED; 180 BRect rect(Bounds()); 181 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); 182 183 BRect verticalScrollBarFrame(0, 0, -1, -1); 184 if (fVerticalScrollBar) 185 verticalScrollBarFrame = fVerticalScrollBar->Frame(); 186 BRect horizontalScrollBarFrame(0, 0, -1, -1); 187 if (fHorizontalScrollBar) 188 horizontalScrollBarFrame = fHorizontalScrollBar->Frame(); 189 190 be_control_look->DrawScrollViewFrame(this, rect, updateRect, 191 verticalScrollBarFrame, horizontalScrollBarFrame, base, fBorder, 192 flags); 193 194 return; 195 } 196 197 if (fBorder == B_PLAIN_BORDER) { 198 SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 199 B_DARKEN_2_TINT)); 200 StrokeRect(Bounds()); 201 return; 202 } else if (fBorder != B_FANCY_BORDER) 203 return; 204 205 BRect bounds = Bounds(); 206 SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 207 B_DARKEN_2_TINT)); 208 StrokeRect(bounds.InsetByCopy(1, 1)); 209 210 if (fHighlighted && Window()->IsActive()) { 211 SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); 212 StrokeRect(bounds); 213 } else { 214 SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 215 B_DARKEN_1_TINT)); 216 StrokeLine(bounds.LeftBottom(), bounds.LeftTop()); 217 bounds.left++; 218 StrokeLine(bounds.LeftTop(), bounds.RightTop()); 219 220 SetHighColor(ui_color(B_SHINE_COLOR)); 221 StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); 222 bounds.top++; 223 bounds.bottom--; 224 StrokeLine(bounds.RightBottom(), bounds.RightTop()); 225 } 226 } 227 228 229 // #pragma mark - 230 231 232 void 233 BScrollView::WindowActivated(bool active) 234 { 235 if (fHighlighted) 236 Invalidate(); 237 238 BView::WindowActivated(active); 239 } 240 241 242 void 243 BScrollView::MakeFocus(bool state) 244 { 245 BView::MakeFocus(state); 246 } 247 248 249 // #pragma mark - 250 251 252 void 253 BScrollView::GetPreferredSize(float *_width, float *_height) 254 { 255 BSize size = PreferredSize(); 256 257 if (_width) 258 *_width = size.width; 259 if (_height) 260 *_height = size.height; 261 } 262 263 264 BSize 265 BScrollView::MinSize() 266 { 267 BSize size = _ComputeSize(fTarget != NULL ? fTarget->MinSize() 268 : BSize(16, 16)); 269 270 return BLayoutUtils::ComposeSize(ExplicitMinSize(), size); 271 } 272 273 274 BSize 275 BScrollView::MaxSize() 276 { 277 BSize size = _ComputeSize(fTarget != NULL ? fTarget->MaxSize() 278 : BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); 279 280 return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size); 281 } 282 283 284 BSize 285 BScrollView::PreferredSize() 286 { 287 BSize size = _ComputeSize(fTarget != NULL ? fTarget->PreferredSize() 288 : BSize(32, 32)); 289 290 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), size); 291 } 292 293 294 void 295 BScrollView::ResizeToPreferred() 296 { 297 if (Window() == NULL) 298 return; 299 BView::ResizeToPreferred(); 300 } 301 302 303 void 304 BScrollView::FrameMoved(BPoint position) 305 { 306 BView::FrameMoved(position); 307 } 308 309 310 void 311 BScrollView::FrameResized(float width, float height) 312 { 313 BView::FrameResized(width, height); 314 315 if (fBorder == B_NO_BORDER) 316 return; 317 318 BRect bounds = Bounds(); 319 float border = _BorderSize() - 1; 320 321 if (be_control_look && fHorizontalScrollBar && fVerticalScrollBar) { 322 BRect scrollCorner(bounds); 323 scrollCorner.left = min_c( 324 fPreviousWidth - fVerticalScrollBar->Frame().Height(), 325 fHorizontalScrollBar->Frame().right + 1); 326 scrollCorner.top = min_c( 327 fPreviousHeight - fHorizontalScrollBar->Frame().Width(), 328 fVerticalScrollBar->Frame().bottom + 1); 329 Invalidate(scrollCorner); 330 } 331 332 // changes in width 333 334 if (bounds.Width() > fPreviousWidth) { 335 // invalidate the region between the old and the new right border 336 BRect rect = bounds; 337 rect.left += fPreviousWidth - border; 338 rect.right--; 339 Invalidate(rect); 340 } else if (bounds.Width() < fPreviousWidth) { 341 // invalidate the region of the new right border 342 BRect rect = bounds; 343 rect.left = rect.right - border; 344 Invalidate(rect); 345 } 346 347 // changes in height 348 349 if (bounds.Height() > fPreviousHeight) { 350 // invalidate the region between the old and the new bottom border 351 BRect rect = bounds; 352 rect.top += fPreviousHeight - border; 353 rect.bottom--; 354 Invalidate(rect); 355 } else if (bounds.Height() < fPreviousHeight) { 356 // invalidate the region of the new bottom border 357 BRect rect = bounds; 358 rect.top = rect.bottom - border; 359 Invalidate(rect); 360 } 361 362 fPreviousWidth = uint16(bounds.Width()); 363 fPreviousHeight = uint16(bounds.Height()); 364 } 365 366 367 // #pragma mark - 368 369 370 void 371 BScrollView::MessageReceived(BMessage* message) 372 { 373 switch (message->what) { 374 default: 375 BView::MessageReceived(message); 376 } 377 } 378 379 380 void 381 BScrollView::MouseDown(BPoint point) 382 { 383 BView::MouseDown(point); 384 } 385 386 387 void 388 BScrollView::MouseUp(BPoint point) 389 { 390 BView::MouseUp(point); 391 } 392 393 394 void 395 BScrollView::MouseMoved(BPoint point, uint32 code, const BMessage *dragMessage) 396 { 397 BView::MouseMoved(point, code, dragMessage); 398 } 399 400 401 // #pragma mark - 402 403 404 BScrollBar* 405 BScrollView::ScrollBar(orientation posture) const 406 { 407 if (posture == B_HORIZONTAL) 408 return fHorizontalScrollBar; 409 410 return fVerticalScrollBar; 411 } 412 413 414 void 415 BScrollView::SetBorder(border_style border) 416 { 417 if (fBorder == border) 418 return; 419 420 if (Flags() & B_SUPPORTS_LAYOUT) { 421 fBorder = border; 422 SetFlags(_ModifyFlags(Flags(), border)); 423 424 DoLayout(); 425 426 BRect bounds(Bounds()); 427 Invalidate(BRect(bounds.LeftTop(), bounds.RightBottom())); 428 Invalidate(BRect(bounds.LeftBottom(), bounds.RightBottom())); 429 return; 430 } 431 432 float offset = _BorderSize() - _BorderSize(border); 433 float resize = 2 * offset; 434 435 float horizontalGap = 0, verticalGap = 0; 436 float change = 0; 437 if (border == B_NO_BORDER || fBorder == B_NO_BORDER) { 438 if (fHorizontalScrollBar != NULL) 439 verticalGap = border != B_NO_BORDER ? 1 : -1; 440 if (fVerticalScrollBar != NULL) 441 horizontalGap = border != B_NO_BORDER ? 1 : -1; 442 443 change = border != B_NO_BORDER ? -1 : 1; 444 if (fHorizontalScrollBar == NULL || fVerticalScrollBar == NULL) 445 change *= 2; 446 } 447 448 fBorder = border; 449 450 int32 savedResizingMode = 0; 451 if (fTarget != NULL) { 452 savedResizingMode = fTarget->ResizingMode(); 453 fTarget->SetResizingMode(B_FOLLOW_NONE); 454 } 455 456 MoveBy(offset, offset); 457 ResizeBy(-resize - horizontalGap, -resize - verticalGap); 458 459 if (fTarget != NULL) { 460 fTarget->MoveBy(-offset, -offset); 461 fTarget->SetResizingMode(savedResizingMode); 462 } 463 464 if (fHorizontalScrollBar != NULL) { 465 fHorizontalScrollBar->MoveBy(-offset - verticalGap, offset + verticalGap); 466 fHorizontalScrollBar->ResizeBy(resize + horizontalGap - change, 0); 467 } 468 if (fVerticalScrollBar != NULL) { 469 fVerticalScrollBar->MoveBy(offset + horizontalGap, -offset - horizontalGap); 470 fVerticalScrollBar->ResizeBy(0, resize + verticalGap - change); 471 } 472 473 SetFlags(_ModifyFlags(Flags(), border)); 474 } 475 476 477 border_style 478 BScrollView::Border() const 479 { 480 return fBorder; 481 } 482 483 484 status_t 485 BScrollView::SetBorderHighlighted(bool state) 486 { 487 if (fHighlighted == state) 488 return B_OK; 489 490 if (fBorder != B_FANCY_BORDER) 491 // highlighting only works for B_FANCY_BORDER 492 return B_ERROR; 493 494 fHighlighted = state; 495 496 if (fHorizontalScrollBar != NULL) 497 fHorizontalScrollBar->SetBorderHighlighted(state); 498 if (fVerticalScrollBar != NULL) 499 fVerticalScrollBar->SetBorderHighlighted(state); 500 501 BRect bounds = Bounds(); 502 if (be_control_look != NULL) 503 bounds.InsetBy(1, 1); 504 505 Invalidate(BRect(bounds.left, bounds.top, bounds.right, bounds.top)); 506 Invalidate(BRect(bounds.left, bounds.top + 1, bounds.left, 507 bounds.bottom - 1)); 508 Invalidate(BRect(bounds.right, bounds.top + 1, bounds.right, 509 bounds.bottom - 1)); 510 Invalidate(BRect(bounds.left, bounds.bottom, bounds.right, bounds.bottom)); 511 512 return B_OK; 513 } 514 515 516 bool 517 BScrollView::IsBorderHighlighted() const 518 { 519 return fHighlighted; 520 } 521 522 523 void 524 BScrollView::SetTarget(BView *target) 525 { 526 if (fTarget == target) 527 return; 528 529 if (fTarget != NULL) { 530 fTarget->TargetedByScrollView(NULL); 531 RemoveChild(fTarget); 532 533 // we are not supposed to delete the view 534 } 535 536 fTarget = target; 537 if (fHorizontalScrollBar != NULL) 538 fHorizontalScrollBar->SetTarget(target); 539 if (fVerticalScrollBar != NULL) 540 fVerticalScrollBar->SetTarget(target); 541 542 if (target != NULL) { 543 target->MoveTo(_BorderSize(), _BorderSize()); 544 BRect innerFrame = _InnerFrame(); 545 target->ResizeTo(innerFrame.Width() - 1, innerFrame.Height() - 1); 546 target->TargetedByScrollView(this); 547 548 AddChild(target, ChildAt(0)); 549 // This way, we are making sure that the target will 550 // be added top most in the list (which is important 551 // for unarchiving) 552 } 553 } 554 555 556 BView* 557 BScrollView::Target() const 558 { 559 return fTarget; 560 } 561 562 563 // #pragma mark - 564 565 566 567 BHandler* 568 BScrollView::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier, 569 int32 form, const char* property) 570 { 571 return BView::ResolveSpecifier(msg, index, specifier, form, property); 572 } 573 574 575 status_t 576 BScrollView::GetSupportedSuites(BMessage *data) 577 { 578 return BView::GetSupportedSuites(data); 579 } 580 581 582 status_t 583 BScrollView::Perform(perform_code code, void* _data) 584 { 585 switch (code) { 586 case PERFORM_CODE_MIN_SIZE: 587 ((perform_data_min_size*)_data)->return_value 588 = BScrollView::MinSize(); 589 return B_OK; 590 case PERFORM_CODE_MAX_SIZE: 591 ((perform_data_max_size*)_data)->return_value 592 = BScrollView::MaxSize(); 593 return B_OK; 594 case PERFORM_CODE_PREFERRED_SIZE: 595 ((perform_data_preferred_size*)_data)->return_value 596 = BScrollView::PreferredSize(); 597 return B_OK; 598 case PERFORM_CODE_LAYOUT_ALIGNMENT: 599 ((perform_data_layout_alignment*)_data)->return_value 600 = BScrollView::LayoutAlignment(); 601 return B_OK; 602 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH: 603 ((perform_data_has_height_for_width*)_data)->return_value 604 = BScrollView::HasHeightForWidth(); 605 return B_OK; 606 case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH: 607 { 608 perform_data_get_height_for_width* data 609 = (perform_data_get_height_for_width*)_data; 610 BScrollView::GetHeightForWidth(data->width, &data->min, &data->max, 611 &data->preferred); 612 return B_OK; 613 } 614 case PERFORM_CODE_SET_LAYOUT: 615 { 616 perform_data_set_layout* data = (perform_data_set_layout*)_data; 617 BScrollView::SetLayout(data->layout); 618 return B_OK; 619 } 620 case PERFORM_CODE_LAYOUT_INVALIDATED: 621 { 622 perform_data_layout_invalidated* data 623 = (perform_data_layout_invalidated*)_data; 624 BScrollView::LayoutInvalidated(data->descendants); 625 return B_OK; 626 } 627 case PERFORM_CODE_DO_LAYOUT: 628 { 629 BScrollView::DoLayout(); 630 return B_OK; 631 } 632 } 633 634 return BView::Perform(code, _data); 635 } 636 637 638 void 639 BScrollView::LayoutInvalidated(bool descendants) 640 { 641 } 642 643 644 void 645 BScrollView::DoLayout() 646 { 647 if (!(Flags() & B_SUPPORTS_LAYOUT)) 648 return; 649 650 // If the user set a layout, we let the base class version call its hook. 651 if (GetLayout()) { 652 BView::DoLayout(); 653 return; 654 } 655 656 BRect innerFrame = _InnerFrame(); 657 658 if (fTarget != NULL) { 659 fTarget->MoveTo(innerFrame.left, innerFrame.top); 660 fTarget->ResizeTo(innerFrame.Width(), innerFrame.Height()); 661 662 //BLayoutUtils::AlignInFrame(fTarget, fTarget->Bounds()); 663 } 664 665 _AlignScrollBars(fHorizontalScrollBar != NULL, fVerticalScrollBar != NULL, 666 innerFrame); 667 } 668 669 670 671 672 // #pragma mark - 673 674 675 void 676 BScrollView::_Init(bool horizontal, bool vertical) 677 { 678 fHorizontalScrollBar = NULL; 679 fVerticalScrollBar = NULL; 680 fHighlighted = false; 681 682 if (be_control_look != NULL) 683 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 684 685 if (horizontal) { 686 fHorizontalScrollBar = new BScrollBar(BRect(0, 0, 14, 14), "_HSB_", 687 fTarget, 0, 1000, B_HORIZONTAL); 688 AddChild(fHorizontalScrollBar); 689 } 690 691 if (vertical) { 692 fVerticalScrollBar = new BScrollBar(BRect(0, 0, 14, 14), "_VSB_", 693 fTarget, 0, 1000, B_VERTICAL); 694 AddChild(fVerticalScrollBar); 695 } 696 697 BRect targetFrame; 698 if (fTarget) { 699 // layout target and add it 700 fTarget->TargetedByScrollView(this); 701 fTarget->MoveTo(B_ORIGIN); 702 703 if (fBorder != B_NO_BORDER) 704 fTarget->MoveBy(_BorderSize(), _BorderSize()); 705 706 AddChild(fTarget); 707 targetFrame = fTarget->Frame(); 708 } else { 709 // no target specified 710 targetFrame = Bounds(); 711 if (horizontal) 712 targetFrame.bottom -= B_H_SCROLL_BAR_HEIGHT + 1; 713 if (vertical) 714 targetFrame.right -= B_V_SCROLL_BAR_WIDTH + 1; 715 if (fBorder == B_FANCY_BORDER) { 716 targetFrame.bottom--; 717 targetFrame.right--; 718 } 719 } 720 721 _AlignScrollBars(horizontal, vertical, targetFrame); 722 723 fPreviousWidth = uint16(Bounds().Width()); 724 fPreviousHeight = uint16(Bounds().Height()); 725 } 726 727 728 float 729 BScrollView::_BorderSize() const 730 { 731 return _BorderSize(fBorder); 732 } 733 734 735 BRect 736 BScrollView::_InnerFrame() const 737 { 738 BRect frame = Bounds(); 739 740 float borderSize = _BorderSize(); 741 frame.InsetBy(borderSize, borderSize); 742 743 if (fHorizontalScrollBar != NULL) { 744 frame.bottom -= B_H_SCROLL_BAR_HEIGHT; 745 if (borderSize == 0) 746 frame.bottom--; 747 } 748 if (fVerticalScrollBar != NULL) { 749 frame.right -= B_V_SCROLL_BAR_WIDTH; 750 if (borderSize == 0) 751 frame.right--; 752 } 753 754 return frame; 755 } 756 757 758 BSize 759 BScrollView::_ComputeSize(BSize targetSize) const 760 { 761 BRect frame = _ComputeFrame( 762 BRect(0, 0, targetSize.width, targetSize.height)); 763 764 return BSize(frame.Width(), frame.Height()); 765 } 766 767 768 BRect 769 BScrollView::_ComputeFrame(BRect targetRect) const 770 { 771 return _ComputeFrame(targetRect, fHorizontalScrollBar != NULL, 772 fVerticalScrollBar != NULL, fBorder); 773 } 774 775 776 void 777 BScrollView::_AlignScrollBars(bool horizontal, bool vertical, BRect targetFrame) 778 { 779 if (horizontal) { 780 BRect rect = targetFrame; 781 rect.top = rect.bottom + 1; 782 rect.bottom = rect.top + B_H_SCROLL_BAR_HEIGHT; 783 if (fBorder != B_NO_BORDER || vertical) { 784 // extend scrollbar so that it overlaps one pixel with vertical 785 // scrollbar 786 rect.right++; 787 } 788 789 if (fBorder != B_NO_BORDER) { 790 // the scrollbar draws part of the surrounding frame on the left 791 rect.left--; 792 } 793 794 fHorizontalScrollBar->MoveTo(rect.left, rect.top); 795 fHorizontalScrollBar->ResizeTo(rect.Width(), rect.Height()); 796 } 797 798 if (vertical) { 799 BRect rect = targetFrame; 800 rect.left = rect.right + 1; 801 rect.right = rect.left + B_V_SCROLL_BAR_WIDTH; 802 if (fBorder != B_NO_BORDER || horizontal) { 803 // extend scrollbar so that it overlaps one pixel with vertical 804 // scrollbar 805 rect.bottom++; 806 } 807 808 if (fBorder != B_NO_BORDER) { 809 // the scrollbar draws part of the surrounding frame on the left 810 rect.top--; 811 } 812 813 fVerticalScrollBar->MoveTo(rect.left, rect.top); 814 fVerticalScrollBar->ResizeTo(rect.Width(), rect.Height()); 815 } 816 } 817 818 819 /*! This static method is used to calculate the frame that the 820 ScrollView will cover depending on the frame of its target 821 and which border style is used. 822 It is used in the constructor and at other places. 823 */ 824 /*static*/ BRect 825 BScrollView::_ComputeFrame(BRect frame, bool horizontal, bool vertical, 826 border_style border) 827 { 828 if (vertical) 829 frame.right += B_V_SCROLL_BAR_WIDTH; 830 if (horizontal) 831 frame.bottom += B_H_SCROLL_BAR_HEIGHT; 832 833 float borderSize = _BorderSize(border); 834 frame.InsetBy(-borderSize, -borderSize); 835 836 if (borderSize == 0) { 837 if (vertical) 838 frame.right++; 839 if (horizontal) 840 frame.bottom++; 841 } 842 843 return frame; 844 } 845 846 847 /*static*/ BRect 848 BScrollView::_ComputeFrame(BView *target, bool horizontal, bool vertical, 849 border_style border) 850 { 851 return _ComputeFrame(target != NULL ? target->Frame() 852 : BRect(0, 0, 16, 16), horizontal, vertical, border); 853 } 854 855 856 /*! This method returns the size of the specified border. 857 */ 858 /*static*/ float 859 BScrollView::_BorderSize(border_style border) 860 { 861 if (border == B_FANCY_BORDER) 862 return kFancyBorderSize; 863 if (border == B_PLAIN_BORDER) 864 return kPlainBorderSize; 865 866 return 0; 867 } 868 869 870 /*! This method changes the "flags" argument as passed on to 871 the BView constructor. 872 */ 873 /*static*/ int32 874 BScrollView::_ModifyFlags(int32 flags, border_style border) 875 { 876 // We either need B_FULL_UPDATE_ON_RESIZE or 877 // B_FRAME_EVENTS if we have to draw a border 878 if (border != B_NO_BORDER) 879 return flags | B_WILL_DRAW | (flags & B_FULL_UPDATE_ON_RESIZE ? 0 : B_FRAME_EVENTS); 880 881 return flags & ~(B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE); 882 } 883 884 885 // #pragma mark - 886 887 888 BScrollView & 889 BScrollView::operator=(const BScrollView &) 890 { 891 return *this; 892 } 893 894 895 void BScrollView::_ReservedScrollView1() {} 896 void BScrollView::_ReservedScrollView2() {} 897 void BScrollView::_ReservedScrollView3() {} 898 void BScrollView::_ReservedScrollView4() {} 899 900 901 extern "C" void 902 B_IF_GCC_2(InvalidateLayout__11BScrollViewb, 903 _ZN11BScrollView16InvalidateLayoutEb)(BScrollView* view, bool descendants) 904 { 905 perform_data_layout_invalidated data; 906 data.descendants = descendants; 907 908 view->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data); 909 } 910 911