vfs: check userland buffers before reading them.
[haiku.git] / src / kits / interface / SeparatorView.cpp
blob616f0b3cdff8c99772dae1e9e99c7f33e01fb169
1 /*
2 * Copyright 2001-2009, Stephan Aßmus <superstippi@gmx.de>
3 * Copyright 2001-2009, Ingo Weinhold <ingo_weinhold@gmx.de>
4 * All rights reserved. Distributed under the terms of the MIT license.
5 */
8 #include "SeparatorView.h"
10 #include <new>
12 #include <math.h>
13 #include <stdio.h>
15 #include <ControlLook.h>
16 #include <LayoutUtils.h>
17 #include <Region.h>
20 static const float kMinBorderLength = 5.0f;
23 // TODO: Actually implement alignment support!
24 // TODO: More testing, especially archiving.
27 BSeparatorView::BSeparatorView(orientation orientation, border_style border)
29 BView(NULL, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE)
31 _Init(NULL, NULL, orientation, BAlignment(B_ALIGN_HORIZONTAL_CENTER,
32 B_ALIGN_VERTICAL_CENTER), border);
36 BSeparatorView::BSeparatorView(const char* name, const char* label,
37 orientation orientation, border_style border, const BAlignment& alignment)
39 BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE)
41 _Init(label, NULL, orientation, alignment, border);
45 BSeparatorView::BSeparatorView(const char* name, BView* labelView,
46 orientation orientation, border_style border, const BAlignment& alignment)
48 BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE)
50 _Init(NULL, labelView, orientation, alignment, border);
54 BSeparatorView::BSeparatorView(const char* label,
55 orientation orientation, border_style border, const BAlignment& alignment)
57 BView("", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE)
59 _Init(label, NULL, orientation, alignment, border);
63 BSeparatorView::BSeparatorView(BView* labelView,
64 orientation orientation, border_style border, const BAlignment& alignment)
66 BView("", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE)
68 _Init(NULL, labelView, orientation, alignment, border);
72 BSeparatorView::BSeparatorView(BMessage* archive)
74 BView(archive),
75 fLabel(),
76 fLabelView(NULL),
77 fOrientation(B_HORIZONTAL),
78 fAlignment(BAlignment(B_ALIGN_HORIZONTAL_CENTER,
79 B_ALIGN_VERTICAL_CENTER)),
80 fBorder(B_FANCY_BORDER)
82 // NULL archives will be caught by BView.
84 const char* label;
85 if (archive->FindString("_labelview", &label) == B_OK) {
86 fLabelView = FindView(label);
87 } else if (archive->FindString("_label", &label) == B_OK) {
88 fLabel.SetTo(label);
91 int32 orientation;
92 if (archive->FindInt32("_orientation", &orientation) == B_OK)
93 fOrientation = (enum orientation)orientation;
95 int32 hAlignment;
96 int32 vAlignment;
97 if (archive->FindInt32("_halignment", &hAlignment) == B_OK
98 && archive->FindInt32("_valignment", &vAlignment) == B_OK) {
99 fAlignment.horizontal = (alignment)hAlignment;
100 fAlignment.vertical = (vertical_alignment)vAlignment;
103 int32 borderStyle;
104 if (archive->FindInt32("_border", &borderStyle) != B_OK)
105 fBorder = (border_style)borderStyle;
109 BSeparatorView::~BSeparatorView()
114 // #pragma mark - Archiving
117 BArchivable*
118 BSeparatorView::Instantiate(BMessage* archive)
120 if (validate_instantiation(archive, "BSeparatorView"))
121 return new (std::nothrow) BSeparatorView(archive);
123 return NULL;
127 status_t
128 BSeparatorView::Archive(BMessage* into, bool deep) const
130 // TODO: Test this.
131 status_t result = BView::Archive(into, deep);
132 if (result != B_OK)
133 return result;
135 if (fLabelView != NULL)
136 result = into->AddString("_labelview", fLabelView->Name());
137 else
138 result = into->AddString("_label", fLabel.String());
140 if (result == B_OK)
141 result = into->AddInt32("_orientation", fOrientation);
143 if (result == B_OK)
144 result = into->AddInt32("_halignment", fAlignment.horizontal);
146 if (result == B_OK)
147 result = into->AddInt32("_valignment", fAlignment.vertical);
149 if (result == B_OK)
150 result = into->AddInt32("_border", fBorder);
152 return result;
156 // #pragma mark -
159 void
160 BSeparatorView::Draw(BRect updateRect)
162 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
163 if (BView* parent = Parent()) {
164 if (parent->ViewColor() != B_TRANSPARENT_COLOR)
165 base = parent->ViewColor();
168 BRect labelBounds;
169 if (fLabelView != NULL) {
170 labelBounds = fLabelView->Frame();
171 } else if (fLabel.CountChars() > 0) {
172 labelBounds = _MaxLabelBounds();
173 float labelWidth = StringWidth(fLabel.String());
174 if (fOrientation == B_HORIZONTAL) {
175 switch (fAlignment.horizontal) {
176 case B_ALIGN_LEFT:
177 default:
178 labelBounds.right = labelBounds.left + labelWidth;
179 break;
181 case B_ALIGN_RIGHT:
182 labelBounds.left = labelBounds.right - labelWidth;
183 break;
185 case B_ALIGN_CENTER:
186 labelBounds.left = (labelBounds.left + labelBounds.right
187 - labelWidth) / 2;
188 labelBounds.right = labelBounds.left + labelWidth;
189 break;
191 } else {
192 switch (fAlignment.vertical) {
193 case B_ALIGN_TOP:
194 default:
195 labelBounds.bottom = labelBounds.top + labelWidth;
196 break;
198 case B_ALIGN_BOTTOM:
199 labelBounds.top = labelBounds.bottom - labelWidth;
200 break;
202 case B_ALIGN_MIDDLE:
203 labelBounds.top = (labelBounds.top + labelBounds.bottom
204 - labelWidth) / 2;
205 labelBounds.bottom = labelBounds.top + labelWidth;
206 break;
211 BRect bounds = Bounds();
212 BRegion region(bounds);
213 if (labelBounds.IsValid()) {
214 region.Exclude(labelBounds);
215 ConstrainClippingRegion(&region);
218 float borderSize = _BorderSize();
219 if (borderSize > 0.0f) {
220 if (fOrientation == B_HORIZONTAL) {
221 bounds.top = floorf((bounds.top + bounds.bottom + 1 - borderSize)
222 / 2);
223 bounds.bottom = bounds.top + borderSize - 1;
224 region.Exclude(bounds);
225 be_control_look->DrawBorder(this, bounds, updateRect, base,
226 fBorder, 0, BControlLook::B_TOP_BORDER);
227 } else {
228 bounds.left = floorf((bounds.left + bounds.right + 1 - borderSize)
229 / 2);
230 bounds.right = bounds.left + borderSize - 1;
231 region.Exclude(bounds);
232 be_control_look->DrawBorder(this, bounds, updateRect, base,
233 fBorder, 0, BControlLook::B_LEFT_BORDER);
235 if (labelBounds.IsValid())
236 region.Include(labelBounds);
238 ConstrainClippingRegion(&region);
241 SetLowColor(base);
242 FillRect(updateRect, B_SOLID_LOW);
244 if (fLabel.CountChars() > 0) {
245 font_height fontHeight;
246 GetFontHeight(&fontHeight);
248 SetHighColor(0, 0, 0, 255);
250 if (fOrientation == B_HORIZONTAL) {
251 DrawString(fLabel.String(), BPoint(labelBounds.left,
252 labelBounds.top + ceilf(fontHeight.ascent)));
253 } else {
254 DrawString(fLabel.String(), BPoint(labelBounds.left
255 + ceilf(fontHeight.ascent), labelBounds.bottom));
261 void
262 BSeparatorView::GetPreferredSize(float* _width, float* _height)
264 float width = 0.0f;
265 float height = 0.0f;
267 if (fLabelView != NULL) {
268 fLabelView->GetPreferredSize(&width, &height);
269 } else if (fLabel.CountChars() > 0) {
270 width = StringWidth(fLabel.String());
271 font_height fontHeight;
272 GetFontHeight(&fontHeight);
273 height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
274 if (fOrientation == B_VERTICAL) {
275 // swap width and height
276 float temp = height;
277 height = width;
278 width = temp;
282 float borderSize = _BorderSize();
284 // Add some room for the border
285 if (fOrientation == B_HORIZONTAL) {
286 width += kMinBorderLength * 2.0f;
287 height = max_c(height, borderSize - 1.0f);
288 } else {
289 height += kMinBorderLength * 2.0f;
290 width = max_c(width, borderSize - 1.0f);
293 if (_width != NULL)
294 *_width = width;
296 if (_height != NULL)
297 *_height = height;
301 BSize
302 BSeparatorView::MinSize()
304 BSize size;
305 GetPreferredSize(&size.width, &size.height);
306 return BLayoutUtils::ComposeSize(ExplicitMinSize(), size);
310 BSize
311 BSeparatorView::MaxSize()
313 BSize size(MinSize());
314 if (fOrientation == B_HORIZONTAL)
315 size.width = B_SIZE_UNLIMITED;
316 else
317 size.height = B_SIZE_UNLIMITED;
319 return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size);
323 BSize
324 BSeparatorView::PreferredSize()
326 BSize size;
327 GetPreferredSize(&size.width, &size.height);
329 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), size);
333 // #pragma mark -
336 void
337 BSeparatorView::SetOrientation(orientation orientation)
339 if (orientation == fOrientation)
340 return;
342 fOrientation = orientation;
344 BFont font;
345 GetFont(&font);
346 if (fOrientation == B_VERTICAL)
347 font.SetRotation(90.0f);
349 SetFont(&font);
351 Invalidate();
352 InvalidateLayout();
356 void
357 BSeparatorView::SetAlignment(const BAlignment& aligment)
359 if (aligment == fAlignment)
360 return;
362 fAlignment = aligment;
364 Invalidate();
365 InvalidateLayout();
369 void
370 BSeparatorView::SetBorderStyle(border_style border)
372 if (border == fBorder)
373 return;
375 fBorder = border;
377 Invalidate();
381 void
382 BSeparatorView::SetLabel(const char* label)
384 if (label == NULL)
385 label = "";
387 if (fLabel == label)
388 return;
390 fLabel.SetTo(label);
392 Invalidate();
393 InvalidateLayout();
397 void
398 BSeparatorView::SetLabel(BView* view, bool deletePrevious)
400 if (fLabelView == view)
401 return;
403 if (fLabelView != NULL) {
404 fLabelView->RemoveSelf();
405 if (deletePrevious)
406 delete fLabelView;
409 fLabelView = view;
411 if (fLabelView != NULL)
412 AddChild(view);
416 status_t
417 BSeparatorView::Perform(perform_code code, void* data)
419 return BView::Perform(code, data);
423 // #pragma mark - protected/private
426 void
427 BSeparatorView::DoLayout()
429 BView::DoLayout();
431 if (fLabelView == NULL)
432 return;
434 BRect bounds = _MaxLabelBounds();
435 BRect frame = BLayoutUtils::AlignInFrame(bounds, fLabelView->MaxSize(),
436 fAlignment);
438 fLabelView->MoveTo(frame.LeftTop());
439 fLabelView->ResizeTo(frame.Width(), frame.Height());
443 void
444 BSeparatorView::_Init(const char* label, BView* labelView,
445 orientation orientation, BAlignment alignment, border_style border)
447 fLabel = "";
448 fLabelView = NULL;
450 fOrientation = B_HORIZONTAL;
451 fAlignment = alignment;
452 fBorder = border;
454 SetFont(be_bold_font);
455 SetViewColor(B_TRANSPARENT_32_BIT);
457 SetLabel(label);
458 SetLabel(labelView, true);
459 SetOrientation(orientation);
463 float
464 BSeparatorView::_BorderSize() const
466 // TODO: Get these values from the BControlLook class.
467 switch (fBorder) {
468 case B_PLAIN_BORDER:
469 return 1.0f;
471 case B_FANCY_BORDER:
472 return 2.0f;
474 case B_NO_BORDER:
475 default:
476 return 0.0f;
481 BRect
482 BSeparatorView::_MaxLabelBounds() const
484 BRect bounds = Bounds();
485 if (fOrientation == B_HORIZONTAL)
486 bounds.InsetBy(kMinBorderLength, 0.0f);
487 else
488 bounds.InsetBy(0.0f, kMinBorderLength);
490 return bounds;
494 // #pragma mark - FBC padding
497 void BSeparatorView::_ReservedSeparatorView1() {}
498 void BSeparatorView::_ReservedSeparatorView2() {}
499 void BSeparatorView::_ReservedSeparatorView3() {}
500 void BSeparatorView::_ReservedSeparatorView4() {}
501 void BSeparatorView::_ReservedSeparatorView5() {}
502 void BSeparatorView::_ReservedSeparatorView6() {}
503 void BSeparatorView::_ReservedSeparatorView7() {}
504 void BSeparatorView::_ReservedSeparatorView8() {}
505 void BSeparatorView::_ReservedSeparatorView9() {}
506 void BSeparatorView::_ReservedSeparatorView10() {}