Implemented a BSeparatorView. It can be a horizontal or vertical line/border,
or also a label, optionally with a BView for the label. Some aspects of it have not been exposed to throughrough testing, yet (archiving, label view), the BAlignment support is also not well tested. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31846 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
483acc4382
commit
79f2db07a8
106
headers/os/interface/SeparatorView.h
Normal file
106
headers/os/interface/SeparatorView.h
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _SEPARATOR_VIEW_H
|
||||
#define _SEPARATOR_VIEW_H
|
||||
|
||||
#include <Alignment.h>
|
||||
#include <String.h>
|
||||
#include <View.h>
|
||||
|
||||
|
||||
class BSeparatorView : public BView {
|
||||
public:
|
||||
BSeparatorView(enum orientation orientation,
|
||||
border_style border = B_FANCY_BORDER);
|
||||
BSeparatorView(const char* name,
|
||||
const char* label,
|
||||
enum orientation orientation
|
||||
= B_HORIZONTAL,
|
||||
border_style border = B_FANCY_BORDER,
|
||||
const BAlignment& alignment
|
||||
= BAlignment(B_ALIGN_HORIZONTAL_CENTER,
|
||||
B_ALIGN_VERTICAL_CENTER));
|
||||
BSeparatorView(const char* name,
|
||||
BView* labelView,
|
||||
enum orientation orientation
|
||||
= B_HORIZONTAL,
|
||||
border_style border = B_FANCY_BORDER,
|
||||
const BAlignment& alignment
|
||||
= BAlignment(B_ALIGN_HORIZONTAL_CENTER,
|
||||
B_ALIGN_VERTICAL_CENTER));
|
||||
BSeparatorView(const char* label = NULL,
|
||||
enum orientation orientation
|
||||
= B_HORIZONTAL,
|
||||
border_style border = B_FANCY_BORDER,
|
||||
const BAlignment& alignment
|
||||
= BAlignment(B_ALIGN_HORIZONTAL_CENTER,
|
||||
B_ALIGN_VERTICAL_CENTER));
|
||||
BSeparatorView(BView* labelView,
|
||||
enum orientation orientation
|
||||
= B_HORIZONTAL,
|
||||
border_style border = B_FANCY_BORDER,
|
||||
const BAlignment& alignment
|
||||
= BAlignment(B_ALIGN_HORIZONTAL_CENTER,
|
||||
B_ALIGN_VERTICAL_CENTER));
|
||||
|
||||
BSeparatorView(BMessage* archive);
|
||||
|
||||
virtual ~BSeparatorView();
|
||||
|
||||
static BArchivable* Instantiate(BMessage* archive);
|
||||
virtual status_t Archive(BMessage* into,
|
||||
bool deep = true) const;
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
virtual void GetPreferredSize(float* width, float* height);
|
||||
|
||||
virtual BSize MinSize();
|
||||
virtual BSize MaxSize();
|
||||
virtual BSize PreferredSize();
|
||||
|
||||
void SetOrientation(enum orientation orientation);
|
||||
void SetAlignment(const BAlignment& aligment);
|
||||
void SetBorderStyle(border_style border);
|
||||
|
||||
void SetLabel(const char* label);
|
||||
void SetLabel(BView* view, bool deletePrevious);
|
||||
|
||||
virtual status_t Perform(perform_code code, void* data);
|
||||
|
||||
protected:
|
||||
virtual void DoLayout();
|
||||
|
||||
private:
|
||||
virtual void _ReservedSeparatorView1();
|
||||
virtual void _ReservedSeparatorView2();
|
||||
virtual void _ReservedSeparatorView3();
|
||||
virtual void _ReservedSeparatorView4();
|
||||
virtual void _ReservedSeparatorView5();
|
||||
virtual void _ReservedSeparatorView6();
|
||||
virtual void _ReservedSeparatorView7();
|
||||
virtual void _ReservedSeparatorView8();
|
||||
virtual void _ReservedSeparatorView9();
|
||||
virtual void _ReservedSeparatorView10();
|
||||
|
||||
private:
|
||||
void _Init(const char* label, BView* labelView,
|
||||
enum orientation orientation,
|
||||
BAlignment alignment, border_style border);
|
||||
|
||||
float _BorderSize() const;
|
||||
BRect _MaxLabelBounds() const;
|
||||
|
||||
BString fLabel;
|
||||
BView* fLabelView;
|
||||
|
||||
orientation fOrientation;
|
||||
BAlignment fAlignment;
|
||||
border_style fBorder;
|
||||
|
||||
uint32 _reserved[10];
|
||||
};
|
||||
|
||||
#endif // _SEPARATOR_VIEW_H
|
501
src/kits/interface/SeparatorView.cpp
Normal file
501
src/kits/interface/SeparatorView.cpp
Normal file
@ -0,0 +1,501 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
// TODO: Actually implement alignment support!
|
||||
// TODO: More testing, especially archiving.
|
||||
|
||||
|
||||
BSeparatorView::BSeparatorView(enum 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,
|
||||
enum 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,
|
||||
enum 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,
|
||||
enum 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,
|
||||
enum 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)
|
||||
{
|
||||
// TODO: Test this.
|
||||
if (archive == NULL)
|
||||
return;
|
||||
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - archiving
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
// TODO: Test this.
|
||||
status_t ret = BView::Archive(into, deep);
|
||||
if (ret != B_OK)
|
||||
return ret;
|
||||
|
||||
if (fLabelView != NULL)
|
||||
ret = into->AddString("_labelview", fLabelView->Name());
|
||||
else
|
||||
ret = into->AddString("_label", fLabel.String());
|
||||
|
||||
if (ret == B_OK)
|
||||
ret = into->AddInt32("_orientation", fOrientation);
|
||||
|
||||
if (ret == B_OK)
|
||||
ret = into->AddInt32("_halignment", fAlignment.horizontal);
|
||||
|
||||
if (ret == B_OK)
|
||||
ret = into->AddInt32("_valignment", fAlignment.vertical);
|
||||
|
||||
if (ret == B_OK)
|
||||
ret = into->AddInt32("_border", fBorder);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
BSeparatorView::Draw(BRect updateRect)
|
||||
{
|
||||
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
|
||||
if (BView* parent = Parent()) {
|
||||
if (parent->ViewColor() != B_TRANSPARENT_COLOR)
|
||||
base = parent->ViewColor();
|
||||
}
|
||||
|
||||
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) {
|
||||
default:
|
||||
case B_ALIGN_LEFT:
|
||||
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) {
|
||||
default:
|
||||
case B_ALIGN_TOP:
|
||||
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, base,
|
||||
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, base,
|
||||
fBorder, 0, BControlLook::B_LEFT_BORDER);
|
||||
}
|
||||
if (labelBounds.IsValid())
|
||||
region.Include(labelBounds);
|
||||
ConstrainClippingRegion(®ion);
|
||||
}
|
||||
|
||||
SetLowColor(base);
|
||||
FillRect(updateRect, B_SOLID_LOW);
|
||||
|
||||
if (fLabel.CountChars() > 0) {
|
||||
font_height fontHeight;
|
||||
GetFontHeight(&fontHeight);
|
||||
|
||||
SetHighColor(0, 0, 0, 255);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetPreferredSize
|
||||
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) {
|
||||
// swap width and height
|
||||
float temp = height;
|
||||
height = width;
|
||||
width = temp;
|
||||
}
|
||||
}
|
||||
|
||||
float borderSize = _BorderSize();
|
||||
|
||||
// Add some room for the border
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
BSeparatorView::SetOrientation(enum 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);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - protected/private
|
||||
|
||||
|
||||
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,
|
||||
enum 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
|
||||
{
|
||||
// TODO: Get these values from the BControlLook class.
|
||||
switch (fBorder) {
|
||||
case B_PLAIN_BORDER:
|
||||
return 1.0f;
|
||||
case B_FANCY_BORDER:
|
||||
return 3.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;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - FBC padding
|
||||
|
||||
|
||||
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() {}
|
||||
|
Loading…
Reference in New Issue
Block a user