* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "IconOptionsControl.h"
#include <stdio.h>
#include <Window.h>
#include "IconButton.h"
#define LABEL_DIST 8.0
IconOptionsControl::IconOptionsControl(const char* name,
const char* label,
BMessage* message,
BHandler* target)
: MView(),
BControl(BRect(0.0, 0.0, 10.0, 10.0), name, label, message,
B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS),
fTargetCache(target)
{
if (Label()) {
labelwidth = StringWidth(Label()) + LABEL_DIST;
} else {
labelwidth = 0.0;
}
}
IconOptionsControl::~IconOptionsControl()
{
}
minimax
IconOptionsControl::layoutprefs()
{
if (rolemodel)
labelwidth = rolemodel->LabelWidth();
if (labelwidth < LabelWidth())
labelwidth = LabelWidth();
mpm.mini.x = 0.0 + labelwidth + 5.0;
mpm.mini.y = 0.0;
for (int32 i = 0; IconButton* button = _FindIcon(i); i++) {
minimax childPrefs = button->layoutprefs();
mpm.mini.x += childPrefs.mini.x + 1;
if (mpm.mini.y < childPrefs.mini.y + 1)
mpm.mini.y = childPrefs.mini.y + 1;
}
mpm.maxi.x = mpm.mini.x;
mpm.maxi.y = mpm.mini.y;
mpm.weight = 1.0;
return mpm;
}
BRect
IconOptionsControl::layout(BRect frame)
{
if (frame.Width() < mpm.mini.x + 1)
frame.right = frame.left + mpm.mini.x + 1;
MoveTo(frame.LeftTop());
ResizeTo(frame.Width(), frame.Height());
return Frame();
}
float
IconOptionsControl::LabelWidth()
{
float width = ceilf(StringWidth(Label()));
if (width > 0.0)
width += LABEL_DIST;
return width;
}
void
IconOptionsControl::SetLabel(const char* label)
{
BControl::SetLabel(label);
float width = LabelWidth();
if (rolemodel)
labelwidth = rolemodel->LabelWidth() > labelwidth ?
rolemodel->LabelWidth() : labelwidth;
labelwidth = width > labelwidth ? width : labelwidth;
_TriggerRelayout();
}
void
IconOptionsControl::AttachedToWindow()
{
BControl::AttachedToWindow();
SetViewColor(B_TRANSPARENT_32_BIT);
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
}
void
IconOptionsControl::AllAttached()
{
for (int32 i = 0; IconButton* button = _FindIcon(i); i++)
button->SetTarget(this);
if (fTargetCache)
SetTarget(fTargetCache);
}
void
IconOptionsControl::Draw(BRect updateRect)
{
FillRect(updateRect, B_SOLID_LOW);
if (Label()) {
if (!IsEnabled())
SetHighColor(tint_color(LowColor(), B_DISABLED_LABEL_TINT));
else
SetHighColor(tint_color(LowColor(), B_DARKEN_MAX_TINT));
font_height fh;
GetFontHeight(&fh);
BPoint p(Bounds().LeftTop());
p.y += floorf(Bounds().Height() / 2.0 + (fh.ascent + fh.descent) / 2.0) - 2.0;
DrawString(Label(), p);
}
}
void
IconOptionsControl::FrameResized(float width, float height)
{
_LayoutIcons(Bounds());
}
void
IconOptionsControl::SetValue(int32 value)
{
if (IconButton* valueButton = _FindIcon(value)) {
for (int32 i = 0; IconButton* button = _FindIcon(i); i++) {
button->SetPressed(button == valueButton);
}
}
}
int32
IconOptionsControl::Value() const
{
for (int32 i = 0; IconButton* button = _FindIcon(i); i++) {
if (button->IsPressed())
return i;
}
return -1;
}
void
IconOptionsControl::SetEnabled(bool enable)
{
for (int32 i = 0; IconButton* button = _FindIcon(i); i++) {
button->SetEnabled(enable);
}
BControl::SetEnabled(enable);
Invalidate();
}
void
IconOptionsControl::MessageReceived(BMessage* message)
{
BView* source;
if (message->FindPointer("be:source", (void**)&source) >= B_OK) {
if (IconButton* sourceIcon = dynamic_cast<IconButton*>(source)) {
for (int32 i = 0; IconButton* button = _FindIcon(i); i++) {
if (button == sourceIcon) {
SetValue(i);
break;
}
}
Invoke(message);
return;
}
}
BControl::MessageReceived(message);
}
status_t
IconOptionsControl::Invoke(BMessage* message)
{
return BInvoker::Invoke(message);
}
void
IconOptionsControl::AddOption(IconButton* icon)
{
if (icon) {
if (!_FindIcon(0)) {
icon->SetPressed(true);
}
AddChild(icon);
icon->SetTarget(this);
layoutprefs();
_TriggerRelayout();
}
}
IconButton*
IconOptionsControl::_FindIcon(int32 index) const
{
if (BView* view = ChildAt(index))
return dynamic_cast<IconButton*>(view);
return NULL;
}
void
IconOptionsControl::_TriggerRelayout()
{
if (!Parent())
return;
MView* mParent = dynamic_cast<MView*>(Parent());
if (mParent) {
if (BWindow* window = Window()) {
window->PostMessage(M_RECALCULATE_SIZE);
}
} else {
_LayoutIcons(Bounds());
}
}
void
IconOptionsControl::_LayoutIcons(BRect frame)
{
BPoint lt = frame.LeftTop();
if (rolemodel)
labelwidth = rolemodel->LabelWidth();
if (labelwidth < LabelWidth())
labelwidth = LabelWidth();
lt.x += labelwidth;
for (int32 i = 0; IconButton* button = _FindIcon(i); i++) {
if (i == 0) {
lt.y = ceilf((frame.top + frame.bottom - button->mpm.mini.y) / 2.0);
}
button->MoveTo(lt);
button->ResizeTo(button->mpm.mini.x, button->mpm.mini.y);
lt = button->Frame().RightTop() + BPoint(1.0, 0.0);
}
}