* Copyright 2001-2009, Stephan Aßmus <superstippi@gmx.de>
* Copyright 2001-2009, Ingo Weinhold <ingo_weinhold@gmx.de>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "SeparatorView.h"
#include <new>
#include <math.h>
#include <stdio.h>
#include <ControlLook.h>
#include <LayoutUtils.h>
#include <Region.h>
static const float kMinBorderLength = 5.0f;
BSeparatorView::BSeparatorView(orientation orientation, border_style border)
:
BView(NULL, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE)
{
_Init(NULL, NULL, orientation, BAlignment(B_ALIGN_HORIZONTAL_CENTER,
B_ALIGN_VERTICAL_CENTER), border);
}
BSeparatorView::BSeparatorView(const char* name, const char* label,
orientation orientation, border_style border, const BAlignment& alignment)
:
BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE)
{
_Init(label, NULL, orientation, alignment, border);
}
BSeparatorView::BSeparatorView(const char* name, BView* labelView,
orientation orientation, border_style border, const BAlignment& alignment)
:
BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE)
{
_Init(NULL, labelView, orientation, alignment, border);
}
BSeparatorView::BSeparatorView(const char* label,
orientation orientation, border_style border, const BAlignment& alignment)
:
BView("", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE)
{
_Init(label, NULL, orientation, alignment, border);
}
BSeparatorView::BSeparatorView(BView* labelView,
orientation orientation, border_style border, const BAlignment& alignment)
:
BView("", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE)
{
_Init(NULL, labelView, orientation, alignment, border);
}
BSeparatorView::BSeparatorView(BMessage* archive)
:
BView(archive),
fLabel(),
fLabelView(NULL),
fOrientation(B_HORIZONTAL),
fAlignment(BAlignment(B_ALIGN_HORIZONTAL_CENTER,
B_ALIGN_VERTICAL_CENTER)),
fBorder(B_FANCY_BORDER)
{
const char* label;
if (archive->FindString("_labelview", &label) == B_OK) {
fLabelView = FindView(label);
} else if (archive->FindString("_label", &label) == B_OK) {
fLabel.SetTo(label);
}
int32 orientation;
if (archive->FindInt32("_orientation", &orientation) == B_OK)
fOrientation = (enum orientation)orientation;
int32 hAlignment;
int32 vAlignment;
if (archive->FindInt32("_halignment", &hAlignment) == B_OK
&& archive->FindInt32("_valignment", &vAlignment) == B_OK) {
fAlignment.horizontal = (alignment)hAlignment;
fAlignment.vertical = (vertical_alignment)vAlignment;
}
int32 borderStyle;
if (archive->FindInt32("_border", &borderStyle) != B_OK)
fBorder = (border_style)borderStyle;
}
BSeparatorView::~BSeparatorView()
{
}
BArchivable*
BSeparatorView::Instantiate(BMessage* archive)
{
if (validate_instantiation(archive, "BSeparatorView"))
return new (std::nothrow) BSeparatorView(archive);
return NULL;
}
status_t
BSeparatorView::Archive(BMessage* into, bool deep) const
{
status_t result = BView::Archive(into, deep);
if (result != B_OK)
return result;
if (fLabelView != NULL)
result = into->AddString("_labelview", fLabelView->Name());
else
result = into->AddString("_label", fLabel.String());
if (result == B_OK)
result = into->AddInt32("_orientation", fOrientation);
if (result == B_OK)
result = into->AddInt32("_halignment", fAlignment.horizontal);
if (result == B_OK)
result = into->AddInt32("_valignment", fAlignment.vertical);
if (result == B_OK)
result = into->AddInt32("_border", fBorder);
return result;
}
void
BSeparatorView::Draw(BRect updateRect)
{
rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR);
rgb_color highColor = ui_color(B_PANEL_TEXT_COLOR);
if (BView* parent = Parent()) {
if (parent->ViewColor() != B_TRANSPARENT_COLOR) {
bgColor = parent->ViewColor();
highColor = parent->HighColor();
}
}
BRect labelBounds;
if (fLabelView != NULL) {
labelBounds = fLabelView->Frame();
} else if (fLabel.CountChars() > 0) {
labelBounds = _MaxLabelBounds();
float labelWidth = StringWidth(fLabel.String());
if (fOrientation == B_HORIZONTAL) {
switch (fAlignment.horizontal) {
case B_ALIGN_LEFT:
default:
labelBounds.right = labelBounds.left + labelWidth;
break;
case B_ALIGN_RIGHT:
labelBounds.left = labelBounds.right - labelWidth;
break;
case B_ALIGN_CENTER:
labelBounds.left = (labelBounds.left + labelBounds.right
- labelWidth) / 2;
labelBounds.right = labelBounds.left + labelWidth;
break;
}
} else {
switch (fAlignment.vertical) {
case B_ALIGN_TOP:
default:
labelBounds.bottom = labelBounds.top + labelWidth;
break;
case B_ALIGN_BOTTOM:
labelBounds.top = labelBounds.bottom - labelWidth;
break;
case B_ALIGN_MIDDLE:
labelBounds.top = (labelBounds.top + labelBounds.bottom
- labelWidth) / 2;
labelBounds.bottom = labelBounds.top + labelWidth;
break;
}
}
}
BRect bounds = Bounds();
BRegion region(bounds);
if (labelBounds.IsValid()) {
region.Exclude(labelBounds);
ConstrainClippingRegion(®ion);
}
float borderSize = _BorderSize();
if (borderSize > 0.0f) {
if (fOrientation == B_HORIZONTAL) {
bounds.top = floorf((bounds.top + bounds.bottom + 1 - borderSize)
/ 2);
bounds.bottom = bounds.top + borderSize - 1;
region.Exclude(bounds);
be_control_look->DrawBorder(this, bounds, updateRect, bgColor,
fBorder, 0, BControlLook::B_TOP_BORDER);
} else {
bounds.left = floorf((bounds.left + bounds.right + 1 - borderSize)
/ 2);
bounds.right = bounds.left + borderSize - 1;
region.Exclude(bounds);
be_control_look->DrawBorder(this, bounds, updateRect, bgColor,
fBorder, 0, BControlLook::B_LEFT_BORDER);
}
if (labelBounds.IsValid())
region.Include(labelBounds);
ConstrainClippingRegion(®ion);
}
SetLowColor(bgColor);
FillRect(updateRect, B_SOLID_LOW);
if (fLabel.CountChars() > 0) {
font_height fontHeight;
GetFontHeight(&fontHeight);
SetHighColor(highColor);
if (fOrientation == B_HORIZONTAL) {
DrawString(fLabel.String(), BPoint(labelBounds.left,
labelBounds.top + ceilf(fontHeight.ascent)));
} else {
DrawString(fLabel.String(), BPoint(labelBounds.left
+ ceilf(fontHeight.ascent), labelBounds.bottom));
}
}
}
void
BSeparatorView::GetPreferredSize(float* _width, float* _height)
{
float width = 0.0f;
float height = 0.0f;
if (fLabelView != NULL) {
fLabelView->GetPreferredSize(&width, &height);
} else if (fLabel.CountChars() > 0) {
width = StringWidth(fLabel.String());
font_height fontHeight;
GetFontHeight(&fontHeight);
height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
if (fOrientation == B_VERTICAL) {
float temp = height;
height = width;
width = temp;
}
}
float borderSize = _BorderSize();
if (fOrientation == B_HORIZONTAL) {
width += kMinBorderLength * 2.0f;
height = max_c(height, borderSize - 1.0f);
} else {
height += kMinBorderLength * 2.0f;
width = max_c(width, borderSize - 1.0f);
}
if (_width != NULL)
*_width = width;
if (_height != NULL)
*_height = height;
}
BSize
BSeparatorView::MinSize()
{
BSize size;
GetPreferredSize(&size.width, &size.height);
return BLayoutUtils::ComposeSize(ExplicitMinSize(), size);
}
BSize
BSeparatorView::MaxSize()
{
BSize size(MinSize());
if (fOrientation == B_HORIZONTAL)
size.width = B_SIZE_UNLIMITED;
else
size.height = B_SIZE_UNLIMITED;
return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size);
}
BSize
BSeparatorView::PreferredSize()
{
BSize size;
GetPreferredSize(&size.width, &size.height);
return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), size);
}
void
BSeparatorView::SetOrientation(orientation orientation)
{
if (orientation == fOrientation)
return;
fOrientation = orientation;
BFont font;
GetFont(&font);
if (fOrientation == B_VERTICAL)
font.SetRotation(90.0f);
SetFont(&font);
Invalidate();
InvalidateLayout();
}
void
BSeparatorView::SetAlignment(const BAlignment& aligment)
{
if (aligment == fAlignment)
return;
fAlignment = aligment;
Invalidate();
InvalidateLayout();
}
void
BSeparatorView::SetBorderStyle(border_style border)
{
if (border == fBorder)
return;
fBorder = border;
Invalidate();
}
void
BSeparatorView::SetLabel(const char* label)
{
if (label == NULL)
label = "";
if (fLabel == label)
return;
fLabel.SetTo(label);
Invalidate();
InvalidateLayout();
}
void
BSeparatorView::SetLabel(BView* view, bool deletePrevious)
{
if (fLabelView == view)
return;
if (fLabelView != NULL) {
fLabelView->RemoveSelf();
if (deletePrevious)
delete fLabelView;
}
fLabelView = view;
if (fLabelView != NULL)
AddChild(view);
}
status_t
BSeparatorView::Perform(perform_code code, void* data)
{
return BView::Perform(code, data);
}
void
BSeparatorView::DoLayout()
{
BView::DoLayout();
if (fLabelView == NULL)
return;
BRect bounds = _MaxLabelBounds();
BRect frame = BLayoutUtils::AlignInFrame(bounds, fLabelView->MaxSize(),
fAlignment);
fLabelView->MoveTo(frame.LeftTop());
fLabelView->ResizeTo(frame.Width(), frame.Height());
}
void
BSeparatorView::_Init(const char* label, BView* labelView,
orientation orientation, BAlignment alignment, border_style border)
{
fLabel = "";
fLabelView = NULL;
fOrientation = B_HORIZONTAL;
fAlignment = alignment;
fBorder = border;
SetFont(be_bold_font);
SetViewColor(B_TRANSPARENT_32_BIT);
SetLabel(label);
SetLabel(labelView, true);
SetOrientation(orientation);
}
float
BSeparatorView::_BorderSize() const
{
switch (fBorder) {
case B_PLAIN_BORDER:
return 1.0f;
case B_FANCY_BORDER:
return 2.0f;
case B_NO_BORDER:
default:
return 0.0f;
}
}
BRect
BSeparatorView::_MaxLabelBounds() const
{
BRect bounds = Bounds();
if (fOrientation == B_HORIZONTAL)
bounds.InsetBy(kMinBorderLength, 0.0f);
else
bounds.InsetBy(0.0f, kMinBorderLength);
return bounds;
}
void BSeparatorView::_ReservedSeparatorView1() {}
void BSeparatorView::_ReservedSeparatorView2() {}
void BSeparatorView::_ReservedSeparatorView3() {}
void BSeparatorView::_ReservedSeparatorView4() {}
void BSeparatorView::_ReservedSeparatorView5() {}
void BSeparatorView::_ReservedSeparatorView6() {}
void BSeparatorView::_ReservedSeparatorView7() {}
void BSeparatorView::_ReservedSeparatorView8() {}
void BSeparatorView::_ReservedSeparatorView9() {}
void BSeparatorView::_ReservedSeparatorView10() {}