vfs: check userland buffers before reading them.
[haiku.git] / src / kits / interface / ScrollView.cpp
blob015dfe0488b8d9c2def6816a6621a97baacd56b5
1 /*
2 * Copyright 2004-2015, Axel Dörfler, axeld@pinc-software.de.
3 * Copyright 2009 Stephan Aßmus, superstippi@gmx.de.
4 * Copyright 2014-2015 Haiku, Inc. All rights reserved.
5 * Distributed under the terms of the MIT License.
7 * Authors:
8 * Stephan Aßmus, superstippi@gmx.de
9 * Axel Dörfler, axeld@pinc-software.de
10 * John Scipione, jscpione@gmail.com
14 #include <ScrollView.h>
16 #include <ControlLook.h>
17 #include <LayoutUtils.h>
18 #include <Message.h>
19 #include <Region.h>
20 #include <Window.h>
22 #include <binary_compatibility/Interface.h>
25 static const float kFancyBorderSize = 2;
26 static const float kPlainBorderSize = 1;
29 BScrollView::BScrollView(const char* name, BView* target, uint32 resizingMode,
30 uint32 flags, bool horizontal, bool vertical, border_style border)
32 BView(_ComputeFrame(target, horizontal, vertical, border,
33 BControlLook::B_ALL_BORDERS), name, resizingMode,
34 _ModifyFlags(flags, border)),
35 fTarget(target),
36 fBorder(border)
38 _Init(horizontal, vertical);
42 BScrollView::BScrollView(const char* name, BView* target, uint32 flags,
43 bool horizontal, bool vertical, border_style border)
45 BView(name, _ModifyFlags(flags, border)),
46 fTarget(target),
47 fBorder(border)
49 _Init(horizontal, vertical);
53 BScrollView::BScrollView(BMessage* archive)
55 BView(archive),
56 fHighlighted(false)
58 int32 border;
59 fBorder = archive->FindInt32("_style", &border) == B_OK ?
60 (border_style)border : B_FANCY_BORDER;
62 // in a shallow archive, we may not have a target anymore. We must
63 // be prepared for this case
65 // don't confuse our scroll bars with our (eventual) target
66 int32 firstBar = 0;
67 if (!archive->FindBool("_no_target_")) {
68 fTarget = ChildAt(0);
69 firstBar++;
70 } else
71 fTarget = NULL;
73 // search for our scroll bars
74 // This will not work for managed archives (when the layout kit is used).
75 // In that case the children are attached later, and we perform the search
76 // again in the AllUnarchived method.
78 fHorizontalScrollBar = NULL;
79 fVerticalScrollBar = NULL;
81 BView* view;
82 while ((view = ChildAt(firstBar++)) != NULL) {
83 BScrollBar *bar = dynamic_cast<BScrollBar *>(view);
84 if (bar == NULL)
85 continue;
87 if (bar->Orientation() == B_HORIZONTAL)
88 fHorizontalScrollBar = bar;
89 else if (bar->Orientation() == B_VERTICAL)
90 fVerticalScrollBar = bar;
93 fPreviousWidth = uint16(Bounds().Width());
94 fPreviousHeight = uint16(Bounds().Height());
99 BScrollView::~BScrollView()
104 // #pragma mark - Archiving
107 BArchivable*
108 BScrollView::Instantiate(BMessage* archive)
110 if (validate_instantiation(archive, "BScrollView"))
111 return new BScrollView(archive);
113 return NULL;
117 status_t
118 BScrollView::Archive(BMessage* archive, bool deep) const
120 status_t status = BView::Archive(archive, deep);
121 if (status != B_OK)
122 return status;
124 // If this is a deep archive, the BView class will take care
125 // of our children.
127 if (status == B_OK && fBorder != B_FANCY_BORDER)
128 status = archive->AddInt32("_style", fBorder);
129 if (status == B_OK && fTarget == NULL)
130 status = archive->AddBool("_no_target_", true);
132 // The highlighted state is not archived, but since it is
133 // usually (or should be) used to indicate focus, this
134 // is probably the right thing to do.
136 return status;
140 status_t
141 BScrollView::AllUnarchived(const BMessage* archive)
143 status_t result = BView::AllUnarchived(archive);
144 if (result != B_OK)
145 return result;
147 // search for our scroll bars and target
148 int32 firstBar = 0;
149 BView* view;
150 while ((view = ChildAt(firstBar++)) != NULL) {
151 BScrollBar *bar = dynamic_cast<BScrollBar *>(view);
152 // We assume that the first non-scrollbar child view is the target.
153 // So the target view can't be a BScrollBar, but who would do that?
154 if (bar == NULL) {
155 // in a shallow archive, we may not have a target anymore. We must
156 // be prepared for this case
157 if (fTarget == NULL && !archive->FindBool("_no_target_"))
158 fTarget = view;
159 continue;
162 if (bar->Orientation() == B_HORIZONTAL)
163 fHorizontalScrollBar = bar;
164 else if (bar->Orientation() == B_VERTICAL)
165 fVerticalScrollBar = bar;
168 // Now connect the bars to the target, and make the target aware of them
169 if (fHorizontalScrollBar)
170 fHorizontalScrollBar->SetTarget(fTarget);
171 if (fVerticalScrollBar)
172 fVerticalScrollBar->SetTarget(fTarget);
174 if (fTarget)
175 fTarget->TargetedByScrollView(this);
177 fPreviousWidth = uint16(Bounds().Width());
178 fPreviousHeight = uint16(Bounds().Height());
180 return B_OK;
184 // #pragma mark - Hook methods
187 void
188 BScrollView::AttachedToWindow()
190 BView::AttachedToWindow();
192 if ((fHorizontalScrollBar == NULL && fVerticalScrollBar == NULL)
193 || (fHorizontalScrollBar != NULL && fVerticalScrollBar != NULL)
194 || Window()->Look() != B_DOCUMENT_WINDOW_LOOK) {
195 return;
198 // If we have only one bar, we need to check if we are in the
199 // bottom right edge of a window with the B_DOCUMENT_LOOK to
200 // adjust the size of the bar to acknowledge the resize knob.
202 BRect bounds = ConvertToScreen(Bounds());
203 BRect windowBounds = Window()->Frame();
205 if (bounds.right - _BorderSize() != windowBounds.right
206 || bounds.bottom - _BorderSize() != windowBounds.bottom) {
207 return;
210 if (fHorizontalScrollBar != NULL)
211 fHorizontalScrollBar->ResizeBy(-B_V_SCROLL_BAR_WIDTH, 0);
212 else if (fVerticalScrollBar != NULL)
213 fVerticalScrollBar->ResizeBy(0, -B_H_SCROLL_BAR_HEIGHT);
217 void
218 BScrollView::DetachedFromWindow()
220 BView::DetachedFromWindow();
224 void
225 BScrollView::AllAttached()
227 BView::AllAttached();
231 void
232 BScrollView::AllDetached()
234 BView::AllDetached();
238 void
239 BScrollView::Draw(BRect updateRect)
241 uint32 flags = 0;
242 if (fHighlighted && Window()->IsActive())
243 flags |= BControlLook::B_FOCUSED;
245 BRect rect(Bounds());
246 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
248 BRect verticalScrollBarFrame(0, 0, -1, -1);
249 if (fVerticalScrollBar)
250 verticalScrollBarFrame = fVerticalScrollBar->Frame();
252 BRect horizontalScrollBarFrame(0, 0, -1, -1);
253 if (fHorizontalScrollBar)
254 horizontalScrollBarFrame = fHorizontalScrollBar->Frame();
256 be_control_look->DrawScrollViewFrame(this, rect, updateRect,
257 verticalScrollBarFrame, horizontalScrollBarFrame, base, fBorder,
258 flags, fBorders);
262 void
263 BScrollView::FrameMoved(BPoint newPosition)
265 BView::FrameMoved(newPosition);
269 void
270 BScrollView::FrameResized(float newWidth, float newHeight)
272 BView::FrameResized(newWidth, newHeight);
274 if (fBorder == B_NO_BORDER)
275 return;
277 BRect bounds = Bounds();
278 float border = _BorderSize() - 1;
280 if (fHorizontalScrollBar != NULL && fVerticalScrollBar != NULL) {
281 BRect scrollCorner(bounds);
282 scrollCorner.left = min_c(
283 fPreviousWidth - fVerticalScrollBar->Frame().Height(),
284 fHorizontalScrollBar->Frame().right + 1);
285 scrollCorner.top = min_c(
286 fPreviousHeight - fHorizontalScrollBar->Frame().Width(),
287 fVerticalScrollBar->Frame().bottom + 1);
288 Invalidate(scrollCorner);
291 // changes in newWidth
293 if (bounds.Width() > fPreviousWidth) {
294 // invalidate the region between the old and the new right border
295 BRect rect = bounds;
296 rect.left += fPreviousWidth - border;
297 rect.right--;
298 Invalidate(rect);
299 } else if (bounds.Width() < fPreviousWidth) {
300 // invalidate the region of the new right border
301 BRect rect = bounds;
302 rect.left = rect.right - border;
303 Invalidate(rect);
306 // changes in newHeight
308 if (bounds.Height() > fPreviousHeight) {
309 // invalidate the region between the old and the new bottom border
310 BRect rect = bounds;
311 rect.top += fPreviousHeight - border;
312 rect.bottom--;
313 Invalidate(rect);
314 } else if (bounds.Height() < fPreviousHeight) {
315 // invalidate the region of the new bottom border
316 BRect rect = bounds;
317 rect.top = rect.bottom - border;
318 Invalidate(rect);
321 fPreviousWidth = uint16(bounds.Width());
322 fPreviousHeight = uint16(bounds.Height());
326 void
327 BScrollView::MessageReceived(BMessage* message)
329 BView::MessageReceived(message);
333 void
334 BScrollView::MouseDown(BPoint where)
336 BView::MouseDown(where);
340 void
341 BScrollView::MouseMoved(BPoint where, uint32 code,
342 const BMessage* dragMessage)
344 BView::MouseMoved(where, code, dragMessage);
348 void
349 BScrollView::MouseUp(BPoint where)
351 BView::MouseUp(where);
355 void
356 BScrollView::WindowActivated(bool active)
358 if (fHighlighted)
359 Invalidate();
361 BView::WindowActivated(active);
365 // #pragma mark - Size methods
368 void
369 BScrollView::GetPreferredSize(float* _width, float* _height)
371 BSize size = PreferredSize();
373 if (_width)
374 *_width = size.width;
376 if (_height)
377 *_height = size.height;
381 void
382 BScrollView::ResizeToPreferred()
384 if (Window() == NULL)
385 return;
386 BView::ResizeToPreferred();
390 void
391 BScrollView::MakeFocus(bool focus)
393 BView::MakeFocus(focus);
397 BSize
398 BScrollView::MinSize()
400 BSize size = _ComputeSize(fTarget != NULL ? fTarget->MinSize()
401 : BSize(16, 16));
403 return BLayoutUtils::ComposeSize(ExplicitMinSize(), size);
407 BSize
408 BScrollView::MaxSize()
410 BSize size = _ComputeSize(fTarget != NULL ? fTarget->MaxSize()
411 : BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
413 return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size);
417 BSize
418 BScrollView::PreferredSize()
420 BSize size = _ComputeSize(fTarget != NULL ? fTarget->PreferredSize()
421 : BSize(32, 32));
423 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), size);
427 // #pragma mark - BScrollView methods
430 BScrollBar*
431 BScrollView::ScrollBar(orientation direction) const
433 if (direction == B_HORIZONTAL)
434 return fHorizontalScrollBar;
436 return fVerticalScrollBar;
440 void
441 BScrollView::SetBorder(border_style border)
443 if (fBorder == border)
444 return;
446 if (Flags() & B_SUPPORTS_LAYOUT) {
447 fBorder = border;
448 SetFlags(_ModifyFlags(Flags(), border));
450 DoLayout();
451 Invalidate();
452 return;
455 float offset = _BorderSize() - _BorderSize(border);
456 float resize = 2 * offset;
458 float horizontalGap = 0, verticalGap = 0;
459 float change = 0;
460 if (border == B_NO_BORDER || fBorder == B_NO_BORDER) {
461 if (fHorizontalScrollBar != NULL)
462 verticalGap = border != B_NO_BORDER ? 1 : -1;
463 if (fVerticalScrollBar != NULL)
464 horizontalGap = border != B_NO_BORDER ? 1 : -1;
466 change = border != B_NO_BORDER ? -1 : 1;
467 if (fHorizontalScrollBar == NULL || fVerticalScrollBar == NULL)
468 change *= 2;
471 fBorder = border;
473 int32 savedResizingMode = 0;
474 if (fTarget != NULL) {
475 savedResizingMode = fTarget->ResizingMode();
476 fTarget->SetResizingMode(B_FOLLOW_NONE);
479 MoveBy(offset, offset);
480 ResizeBy(-resize - horizontalGap, -resize - verticalGap);
482 if (fTarget != NULL) {
483 fTarget->MoveBy(-offset, -offset);
484 fTarget->SetResizingMode(savedResizingMode);
487 if (fHorizontalScrollBar != NULL) {
488 fHorizontalScrollBar->MoveBy(-offset - verticalGap, offset + verticalGap);
489 fHorizontalScrollBar->ResizeBy(resize + horizontalGap - change, 0);
491 if (fVerticalScrollBar != NULL) {
492 fVerticalScrollBar->MoveBy(offset + horizontalGap, -offset - horizontalGap);
493 fVerticalScrollBar->ResizeBy(0, resize + verticalGap - change);
496 SetFlags(_ModifyFlags(Flags(), border));
500 border_style
501 BScrollView::Border() const
503 return fBorder;
507 void
508 BScrollView::SetBorders(uint32 borders)
510 if (fBorders == borders || (Flags() & B_SUPPORTS_LAYOUT) == 0)
511 return;
513 fBorders = borders;
514 DoLayout();
515 Invalidate();
519 uint32
520 BScrollView::Borders() const
522 return fBorders;
526 status_t
527 BScrollView::SetBorderHighlighted(bool highlight)
529 if (fHighlighted == highlight)
530 return B_OK;
532 if (fBorder != B_FANCY_BORDER)
533 // highlighting only works for B_FANCY_BORDER
534 return B_ERROR;
536 fHighlighted = highlight;
538 if (fHorizontalScrollBar != NULL)
539 fHorizontalScrollBar->SetBorderHighlighted(highlight);
540 if (fVerticalScrollBar != NULL)
541 fVerticalScrollBar->SetBorderHighlighted(highlight);
543 BRect bounds = Bounds();
544 bounds.InsetBy(1, 1);
546 Invalidate(BRect(bounds.left, bounds.top, bounds.right, bounds.top));
547 Invalidate(BRect(bounds.left, bounds.top + 1, bounds.left,
548 bounds.bottom - 1));
549 Invalidate(BRect(bounds.right, bounds.top + 1, bounds.right,
550 bounds.bottom - 1));
551 Invalidate(BRect(bounds.left, bounds.bottom, bounds.right, bounds.bottom));
553 return B_OK;
557 bool
558 BScrollView::IsBorderHighlighted() const
560 return fHighlighted;
564 void
565 BScrollView::SetTarget(BView* target)
567 if (fTarget == target)
568 return;
570 if (fTarget != NULL) {
571 fTarget->TargetedByScrollView(NULL);
572 RemoveChild(fTarget);
574 // we are not supposed to delete the view
577 fTarget = target;
578 if (fHorizontalScrollBar != NULL)
579 fHorizontalScrollBar->SetTarget(target);
580 if (fVerticalScrollBar != NULL)
581 fVerticalScrollBar->SetTarget(target);
583 if (target != NULL) {
584 float borderSize = _BorderSize();
585 target->MoveTo((fBorders & BControlLook::B_LEFT_BORDER) != 0
586 ? borderSize : 0, (fBorders & BControlLook::B_TOP_BORDER) != 0
587 ? borderSize : 0);
588 BRect innerFrame = _InnerFrame();
589 target->ResizeTo(innerFrame.Width() - 1, innerFrame.Height() - 1);
590 target->TargetedByScrollView(this);
592 AddChild(target, ChildAt(0));
593 // This way, we are making sure that the target will
594 // be added top most in the list (which is important
595 // for unarchiving)
600 BView*
601 BScrollView::Target() const
603 return fTarget;
607 // #pragma mark - Scripting methods
611 BHandler*
612 BScrollView::ResolveSpecifier(BMessage* message, int32 index,
613 BMessage* specifier, int32 what, const char* property)
615 return BView::ResolveSpecifier(message, index, specifier, what, property);
619 status_t
620 BScrollView::GetSupportedSuites(BMessage* message)
622 return BView::GetSupportedSuites(message);
626 // #pragma mark - Perform
629 status_t
630 BScrollView::Perform(perform_code code, void* _data)
632 switch (code) {
633 case PERFORM_CODE_MIN_SIZE:
634 ((perform_data_min_size*)_data)->return_value
635 = BScrollView::MinSize();
636 return B_OK;
638 case PERFORM_CODE_MAX_SIZE:
639 ((perform_data_max_size*)_data)->return_value
640 = BScrollView::MaxSize();
641 return B_OK;
643 case PERFORM_CODE_PREFERRED_SIZE:
644 ((perform_data_preferred_size*)_data)->return_value
645 = BScrollView::PreferredSize();
646 return B_OK;
648 case PERFORM_CODE_LAYOUT_ALIGNMENT:
649 ((perform_data_layout_alignment*)_data)->return_value
650 = BScrollView::LayoutAlignment();
651 return B_OK;
653 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
654 ((perform_data_has_height_for_width*)_data)->return_value
655 = BScrollView::HasHeightForWidth();
656 return B_OK;
658 case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
660 perform_data_get_height_for_width* data
661 = (perform_data_get_height_for_width*)_data;
662 BScrollView::GetHeightForWidth(data->width, &data->min, &data->max,
663 &data->preferred);
664 return B_OK;
667 case PERFORM_CODE_SET_LAYOUT:
669 perform_data_set_layout* data = (perform_data_set_layout*)_data;
670 BScrollView::SetLayout(data->layout);
671 return B_OK;
674 case PERFORM_CODE_LAYOUT_INVALIDATED:
676 perform_data_layout_invalidated* data
677 = (perform_data_layout_invalidated*)_data;
678 BScrollView::LayoutInvalidated(data->descendants);
679 return B_OK;
682 case PERFORM_CODE_DO_LAYOUT:
684 BScrollView::DoLayout();
685 return B_OK;
689 return BView::Perform(code, _data);
693 // #pragma mark - Protected methods
696 void
697 BScrollView::LayoutInvalidated(bool descendants)
702 void
703 BScrollView::DoLayout()
705 if ((Flags() & B_SUPPORTS_LAYOUT) == 0)
706 return;
708 // If the user set a layout, we let the base class version call its hook.
709 if (GetLayout() != NULL) {
710 BView::DoLayout();
711 return;
714 BRect innerFrame = _InnerFrame();
716 if (fTarget != NULL) {
717 fTarget->MoveTo(innerFrame.left, innerFrame.top);
718 fTarget->ResizeTo(innerFrame.Width(), innerFrame.Height());
720 //BLayoutUtils::AlignInFrame(fTarget, fTarget->Bounds());
723 _AlignScrollBars(fHorizontalScrollBar != NULL, fVerticalScrollBar != NULL,
724 innerFrame);
728 // #pragma mark - Private methods
731 void
732 BScrollView::_Init(bool horizontal, bool vertical)
734 fHorizontalScrollBar = NULL;
735 fVerticalScrollBar = NULL;
736 fHighlighted = false;
737 fBorders = BControlLook::B_ALL_BORDERS;
739 SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
741 if (horizontal) {
742 fHorizontalScrollBar = new BScrollBar(BRect(0, 0, 14, 14), "_HSB_",
743 fTarget, 0, 1000, B_HORIZONTAL);
744 AddChild(fHorizontalScrollBar);
747 if (vertical) {
748 fVerticalScrollBar = new BScrollBar(BRect(0, 0, 14, 14), "_VSB_",
749 fTarget, 0, 1000, B_VERTICAL);
750 AddChild(fVerticalScrollBar);
753 BRect targetFrame;
754 if (fTarget) {
755 // layout target and add it
756 fTarget->TargetedByScrollView(this);
757 fTarget->MoveTo(B_ORIGIN);
759 if (fBorder != B_NO_BORDER)
760 fTarget->MoveBy(_BorderSize(), _BorderSize());
762 AddChild(fTarget);
763 targetFrame = fTarget->Frame();
764 } else {
765 // no target specified
766 targetFrame = Bounds();
767 if (horizontal)
768 targetFrame.bottom -= B_H_SCROLL_BAR_HEIGHT + 1;
769 if (vertical)
770 targetFrame.right -= B_V_SCROLL_BAR_WIDTH + 1;
771 if (fBorder == B_FANCY_BORDER) {
772 targetFrame.bottom--;
773 targetFrame.right--;
777 _AlignScrollBars(horizontal, vertical, targetFrame);
779 fPreviousWidth = uint16(Bounds().Width());
780 fPreviousHeight = uint16(Bounds().Height());
784 float
785 BScrollView::_BorderSize() const
787 return _BorderSize(fBorder);
791 BRect
792 BScrollView::_InnerFrame() const
794 BRect frame = Bounds();
795 _InsetBorders(frame, fBorder, fBorders);
797 float borderSize = _BorderSize();
799 if (fHorizontalScrollBar != NULL) {
800 frame.bottom -= B_H_SCROLL_BAR_HEIGHT;
801 if (borderSize == 0)
802 frame.bottom--;
804 if (fVerticalScrollBar != NULL) {
805 frame.right -= B_V_SCROLL_BAR_WIDTH;
806 if (borderSize == 0)
807 frame.right--;
810 return frame;
814 BSize
815 BScrollView::_ComputeSize(BSize targetSize) const
817 BRect frame = _ComputeFrame(
818 BRect(0, 0, targetSize.width, targetSize.height));
820 return BSize(frame.Width(), frame.Height());
824 BRect
825 BScrollView::_ComputeFrame(BRect targetRect) const
827 return _ComputeFrame(targetRect, fHorizontalScrollBar != NULL,
828 fVerticalScrollBar != NULL, fBorder, fBorders);
832 void
833 BScrollView::_AlignScrollBars(bool horizontal, bool vertical, BRect targetFrame)
835 if (horizontal) {
836 BRect rect = targetFrame;
837 rect.top = rect.bottom + 1;
838 rect.bottom = rect.top + B_H_SCROLL_BAR_HEIGHT;
839 if (fBorder != B_NO_BORDER || vertical) {
840 // extend scrollbar so that it overlaps one pixel with vertical
841 // scrollbar
842 rect.right++;
845 if (fBorder != B_NO_BORDER) {
846 // the scrollbar draws part of the surrounding frame on the left
847 rect.left--;
850 fHorizontalScrollBar->MoveTo(rect.left, rect.top);
851 fHorizontalScrollBar->ResizeTo(rect.Width(), rect.Height());
854 if (vertical) {
855 BRect rect = targetFrame;
856 rect.left = rect.right + 1;
857 rect.right = rect.left + B_V_SCROLL_BAR_WIDTH;
858 if (fBorder != B_NO_BORDER || horizontal) {
859 // extend scrollbar so that it overlaps one pixel with vertical
860 // scrollbar
861 rect.bottom++;
864 if (fBorder != B_NO_BORDER) {
865 // the scrollbar draws part of the surrounding frame on the left
866 rect.top--;
869 fVerticalScrollBar->MoveTo(rect.left, rect.top);
870 fVerticalScrollBar->ResizeTo(rect.Width(), rect.Height());
875 /*! This static method is used to calculate the frame that the
876 ScrollView will cover depending on the frame of its target
877 and which border style is used.
878 It is used in the constructor and at other places.
880 /*static*/ BRect
881 BScrollView::_ComputeFrame(BRect frame, bool horizontal, bool vertical,
882 border_style border, uint32 borders)
884 if (vertical)
885 frame.right += B_V_SCROLL_BAR_WIDTH;
886 if (horizontal)
887 frame.bottom += B_H_SCROLL_BAR_HEIGHT;
889 _InsetBorders(frame, border, borders, true);
891 if (_BorderSize(border) == 0) {
892 if (vertical)
893 frame.right++;
894 if (horizontal)
895 frame.bottom++;
898 return frame;
902 /*static*/ BRect
903 BScrollView::_ComputeFrame(BView *target, bool horizontal, bool vertical,
904 border_style border, uint32 borders)
906 return _ComputeFrame(target != NULL ? target->Frame()
907 : BRect(0, 0, 16, 16), horizontal, vertical, border, borders);
911 /*! This method returns the size of the specified border.
913 /*static*/ float
914 BScrollView::_BorderSize(border_style border)
916 if (border == B_FANCY_BORDER)
917 return kFancyBorderSize;
918 if (border == B_PLAIN_BORDER)
919 return kPlainBorderSize;
921 return 0;
925 /*! This method changes the "flags" argument as passed on to
926 the BView constructor.
928 /*static*/ int32
929 BScrollView::_ModifyFlags(int32 flags, border_style border)
931 // We either need B_FULL_UPDATE_ON_RESIZE or
932 // B_FRAME_EVENTS if we have to draw a border
933 if (border != B_NO_BORDER)
934 return flags | B_WILL_DRAW | (flags & B_FULL_UPDATE_ON_RESIZE ? 0 : B_FRAME_EVENTS);
936 return flags & ~(B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE);
940 /*static*/ void
941 BScrollView::_InsetBorders(BRect& frame, border_style border, uint32 borders, bool expand)
943 float borderSize = _BorderSize(border);
944 if (expand)
945 borderSize = -borderSize;
946 if ((borders & BControlLook::B_LEFT_BORDER) != 0)
947 frame.left += borderSize;
948 if ((borders & BControlLook::B_TOP_BORDER) != 0)
949 frame.top += borderSize;
950 if ((borders & BControlLook::B_RIGHT_BORDER) != 0)
951 frame.right -= borderSize;
952 if ((borders & BControlLook::B_BOTTOM_BORDER) != 0)
953 frame.bottom -= borderSize;
957 // #pragma mark - FBC and forbidden
960 BScrollView&
961 BScrollView::operator=(const BScrollView &)
963 return *this;
967 void BScrollView::_ReservedScrollView1() {}
968 void BScrollView::_ReservedScrollView2() {}
969 void BScrollView::_ReservedScrollView3() {}
970 void BScrollView::_ReservedScrollView4() {}
973 extern "C" void
974 B_IF_GCC_2(InvalidateLayout__11BScrollViewb,
975 _ZN11BScrollView16InvalidateLayoutEb)(BScrollView* view, bool descendants)
977 perform_data_layout_invalidated data;
978 data.descendants = descendants;
980 view->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data);