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