vfs: check userland buffers before reading them.
[haiku.git] / src / kits / interface / ViewPort.cpp
blobc2ea225611745ee6e0516cf12737c18786a05ebc
1 /*
2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <ViewPort.h>
9 #include <algorithm>
11 #include <AbstractLayout.h>
12 #include <ScrollBar.h>
14 #include "ViewLayoutItem.h"
17 namespace BPrivate {
20 // #pragma mark - ViewPortLayout
23 class BViewPort::ViewPortLayout : public BAbstractLayout {
24 public:
25 ViewPortLayout(BViewPort* viewPort)
27 BAbstractLayout(),
28 fViewPort(viewPort),
29 fHasViewChild(false),
30 fIsCacheValid(false),
31 fMin(),
32 fMax(),
33 fPreferred()
37 BView* ChildView() const
39 if (!fHasViewChild)
40 return NULL;
41 if (BViewLayoutItem* item = dynamic_cast<BViewLayoutItem*>(ItemAt(0)))
42 return item->View();
43 return NULL;
46 void SetChildView(BView* view)
48 _UnsetChild();
50 if (view != NULL && AddView(0, view) != NULL)
51 fHasViewChild = true;
54 BLayoutItem* ChildItem() const
56 return ItemAt(0);
59 void SetChildItem(BLayoutItem* item)
61 _UnsetChild();
63 if (item != NULL)
64 AddItem(0, item);
67 virtual BSize BaseMinSize()
69 _ValidateMinMax();
70 return fMin;
73 virtual BSize BaseMaxSize()
75 _ValidateMinMax();
76 return fMax;
79 virtual BSize BasePreferredSize()
81 _ValidateMinMax();
82 return fPreferred;
85 virtual BAlignment BaseAlignment()
87 return BAbstractLayout::BaseAlignment();
90 virtual bool HasHeightForWidth()
92 _ValidateMinMax();
93 return false;
94 // TODO: Support height-for-width!
97 virtual void GetHeightForWidth(float width, float* min, float* max,
98 float* preferred)
100 if (!HasHeightForWidth())
101 return;
103 // TODO: Support height-for-width!
106 virtual void LayoutInvalidated(bool children)
108 fIsCacheValid = false;
111 virtual void DoLayout()
113 _ValidateMinMax();
115 BLayoutItem* child = ItemAt(0);
116 if (child == NULL)
117 return;
119 // Determine the layout area: LayoutArea() will only give us the size
120 // of the view port's frame.
121 BSize viewSize = LayoutArea().Size();
122 BSize layoutSize = viewSize;
124 BSize childMin = child->MinSize();
125 BSize childMax = child->MaxSize();
127 // apply the maximum constraints
128 layoutSize.width = std::min(layoutSize.width, childMax.width);
129 layoutSize.height = std::min(layoutSize.height, childMax.height);
131 // apply the minimum constraints
132 layoutSize.width = std::max(layoutSize.width, childMin.width);
133 layoutSize.height = std::max(layoutSize.height, childMin.height);
135 // TODO: Support height-for-width!
137 child->AlignInFrame(BRect(BPoint(0, 0), layoutSize));
139 _UpdateScrollBar(fViewPort->ScrollBar(B_HORIZONTAL), viewSize.width,
140 layoutSize.width);
141 _UpdateScrollBar(fViewPort->ScrollBar(B_VERTICAL), viewSize.height,
142 layoutSize.height);
145 private:
146 void _UnsetChild()
148 if (CountItems() > 0) {
149 BLayoutItem* item = RemoveItem((int32)0);
150 if (fHasViewChild)
151 delete item;
152 fHasViewChild = false;
156 void _ValidateMinMax()
158 if (fIsCacheValid)
159 return;
161 if (BLayoutItem* child = ItemAt(0)) {
162 fMin = child->MinSize();
163 if (_IsHorizontallyScrollable())
164 fMin.width = -1;
165 if (_IsVerticallyScrollable())
166 fMin.height = -1;
167 fMax = child->MaxSize();
168 fPreferred = child->PreferredSize();
169 // TODO: Support height-for-width!
170 } else {
171 fMin.Set(-1, -1);
172 fMax.Set(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
173 fPreferred.Set(20, 20);
176 fIsCacheValid = true;
179 bool _IsHorizontallyScrollable() const
181 return fViewPort->ScrollBar(B_HORIZONTAL) != NULL;
184 bool _IsVerticallyScrollable() const
186 return fViewPort->ScrollBar(B_VERTICAL) != NULL;
189 void _UpdateScrollBar(BScrollBar* scrollBar, float viewPortSize,
190 float dataSize)
192 if (scrollBar == NULL)
193 return;
195 if (viewPortSize < dataSize) {
196 scrollBar->SetRange(0, dataSize - viewPortSize);
197 scrollBar->SetProportion(viewPortSize / dataSize);
198 float smallStep;
199 scrollBar->GetSteps(&smallStep, NULL);
200 scrollBar->SetSteps(smallStep, viewPortSize);
201 } else {
202 scrollBar->SetRange(0, 0);
203 scrollBar->SetProportion(1);
207 private:
208 BViewPort* fViewPort;
209 bool fHasViewChild;
210 bool fIsCacheValid;
211 BSize fMin;
212 BSize fMax;
213 BSize fPreferred;
217 // #pragma mark - BViewPort
220 BViewPort::BViewPort(BView* child)
222 BView(NULL, 0),
223 fChild(NULL)
225 _Init();
226 SetChildView(child);
230 BViewPort::BViewPort(BLayoutItem* child)
232 BView(NULL, 0),
233 fChild(NULL)
235 _Init();
236 SetChildItem(child);
240 BViewPort::BViewPort(const char* name, BView* child)
242 BView(name, 0),
243 fChild(NULL)
245 _Init();
246 SetChildView(child);
250 BViewPort::BViewPort(const char* name, BLayoutItem* child)
252 BView(name, 0),
253 fChild(NULL)
255 _Init();
256 SetChildItem(child);
260 BViewPort::~BViewPort()
265 BView*
266 BViewPort::ChildView() const
268 return fLayout->ChildView();
272 void
273 BViewPort::SetChildView(BView* child)
275 fLayout->SetChildView(child);
276 InvalidateLayout();
280 BLayoutItem*
281 BViewPort::ChildItem() const
283 return fLayout->ChildItem();
287 void
288 BViewPort::SetChildItem(BLayoutItem* child)
290 fLayout->SetChildItem(child);
291 InvalidateLayout();
295 void
296 BViewPort::_Init()
298 fLayout = new ViewPortLayout(this);
299 SetLayout(fLayout);
303 } // namespace BPrivate
306 using ::BPrivate::BViewPort;