we might as well use it. Couldn't see any regressions so far. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35457 a95241bf-73f2-0310-859d-f6bbb57e9c96
777 lines
16 KiB
C++
777 lines
16 KiB
C++
/*
|
|
* Copyright 2001-2008, Haiku Inc. All rights reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*
|
|
* Authors:
|
|
* Marc Flerackers ([email protected])
|
|
* Mike Wilber
|
|
* Stefano Ceccherini ([email protected])
|
|
* Ivan Tonizza
|
|
* Stephan Aßmus <[email protected]>
|
|
*/
|
|
|
|
|
|
#include <Button.h>
|
|
|
|
#include <new>
|
|
|
|
#include <ControlLook.h>
|
|
#include <Font.h>
|
|
#include <LayoutUtils.h>
|
|
#include <String.h>
|
|
#include <Window.h>
|
|
|
|
#include <binary_compatibility/Interface.h>
|
|
|
|
|
|
BButton::BButton(BRect frame, const char* name, const char* label,
|
|
BMessage* message, uint32 resizingMode, uint32 flags)
|
|
: BControl(frame, name, label, message, resizingMode,
|
|
flags | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
|
|
fPreferredSize(-1, -1),
|
|
fDrawAsDefault(false)
|
|
{
|
|
// Resize to minimum height if needed
|
|
font_height fh;
|
|
GetFontHeight(&fh);
|
|
float minHeight = 12.0f + (float)ceil(fh.ascent + fh.descent);
|
|
if (Bounds().Height() < minHeight)
|
|
ResizeTo(Bounds().Width(), minHeight);
|
|
}
|
|
|
|
|
|
BButton::BButton(const char* name, const char* label, BMessage* message,
|
|
uint32 flags)
|
|
: BControl(name, label, message,
|
|
flags | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
|
|
fPreferredSize(-1, -1),
|
|
fDrawAsDefault(false)
|
|
{
|
|
}
|
|
|
|
|
|
BButton::BButton(const char* label, BMessage* message)
|
|
: BControl(NULL, label, message,
|
|
B_WILL_DRAW | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE),
|
|
fPreferredSize(-1, -1),
|
|
fDrawAsDefault(false)
|
|
{
|
|
}
|
|
|
|
|
|
BButton::~BButton()
|
|
{
|
|
}
|
|
|
|
|
|
BButton::BButton(BMessage* archive)
|
|
: BControl(archive),
|
|
fPreferredSize(-1, -1)
|
|
{
|
|
if (archive->FindBool("_default", &fDrawAsDefault) != B_OK)
|
|
fDrawAsDefault = false;
|
|
// NOTE: Default button state will be synchronized with the window
|
|
// in AttachedToWindow().
|
|
}
|
|
|
|
|
|
BArchivable*
|
|
BButton::Instantiate(BMessage* archive)
|
|
{
|
|
if (validate_instantiation(archive, "BButton"))
|
|
return new(std::nothrow) BButton(archive);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
status_t
|
|
BButton::Archive(BMessage* archive, bool deep) const
|
|
{
|
|
status_t err = BControl::Archive(archive, deep);
|
|
|
|
if (err != B_OK)
|
|
return err;
|
|
|
|
if (IsDefault())
|
|
err = archive->AddBool("_default", true);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
void
|
|
BButton::Draw(BRect updateRect)
|
|
{
|
|
if (be_control_look != NULL) {
|
|
BRect rect(Bounds());
|
|
rgb_color background = LowColor();
|
|
rgb_color base = background;
|
|
uint32 flags = be_control_look->Flags(this);
|
|
if (IsDefault())
|
|
flags |= BControlLook::B_DEFAULT_BUTTON;
|
|
be_control_look->DrawButtonFrame(this, rect, updateRect,
|
|
base, background, flags);
|
|
be_control_look->DrawButtonBackground(this, rect, updateRect,
|
|
base, flags);
|
|
|
|
// always leave some room around the label
|
|
rect.InsetBy(3.0, 3.0);
|
|
be_control_look->DrawLabel(this, Label(), rect, updateRect,
|
|
base, flags, BAlignment(B_ALIGN_CENTER, B_ALIGN_MIDDLE));
|
|
return;
|
|
}
|
|
|
|
font_height fh;
|
|
GetFontHeight(&fh);
|
|
|
|
const BRect bounds = Bounds();
|
|
BRect rect = bounds;
|
|
|
|
const bool enabled = IsEnabled();
|
|
const bool pushed = Value() == B_CONTROL_ON;
|
|
// Default indicator
|
|
if (IsDefault())
|
|
rect = _DrawDefault(rect, enabled);
|
|
|
|
BRect fillArea = rect;
|
|
fillArea.InsetBy(3.0, 3.0);
|
|
|
|
BString text = Label();
|
|
|
|
#if 1
|
|
// Label truncation
|
|
BFont font;
|
|
GetFont(&font);
|
|
font.TruncateString(&text, B_TRUNCATE_END, fillArea.Width() - 4);
|
|
#endif
|
|
|
|
// Label position
|
|
const float stringWidth = StringWidth(text.String());
|
|
const float x = (rect.right - stringWidth) / 2.0;
|
|
const float labelY = bounds.top
|
|
+ ((bounds.Height() - fh.ascent - fh.descent) / 2.0)
|
|
+ fh.ascent + 1.0;
|
|
const float focusLineY = labelY + fh.descent;
|
|
|
|
/* speed trick:
|
|
if the focus changes but the button is not pressed then we can
|
|
redraw only the focus line,
|
|
if the focus changes and the button is pressed invert the internal rect
|
|
this block takes care of all the focus changes
|
|
*/
|
|
if (IsFocusChanging()) {
|
|
if (pushed) {
|
|
rect.InsetBy(2.0, 2.0);
|
|
InvertRect(rect);
|
|
} else {
|
|
_DrawFocusLine(x, focusLineY, stringWidth, IsFocus()
|
|
&& Window()->IsActive());
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// colors
|
|
rgb_color panelBgColor = ui_color(B_PANEL_BACKGROUND_COLOR);
|
|
rgb_color buttonBgColor = tint_color(panelBgColor, B_LIGHTEN_1_TINT);
|
|
rgb_color lightColor;
|
|
rgb_color maxLightColor;
|
|
rgb_color maxShadowColor = tint_color(panelBgColor, B_DARKEN_MAX_TINT);
|
|
|
|
rgb_color dark1BorderColor;
|
|
rgb_color dark2BorderColor;
|
|
|
|
rgb_color bevelColor1;
|
|
rgb_color bevelColor2;
|
|
rgb_color bevelColorRBCorner;
|
|
|
|
rgb_color borderBevelShadow;
|
|
rgb_color borderBevelLight;
|
|
|
|
if (enabled) {
|
|
lightColor = tint_color(panelBgColor, B_LIGHTEN_2_TINT);
|
|
maxLightColor = tint_color(panelBgColor, B_LIGHTEN_MAX_TINT);
|
|
|
|
dark1BorderColor = tint_color(panelBgColor, B_DARKEN_3_TINT);
|
|
dark2BorderColor = tint_color(panelBgColor, B_DARKEN_4_TINT);
|
|
|
|
bevelColor1 = tint_color(panelBgColor, B_DARKEN_2_TINT);
|
|
bevelColor2 = panelBgColor;
|
|
|
|
if (IsDefault()) {
|
|
borderBevelShadow = tint_color(dark1BorderColor,
|
|
(B_NO_TINT + B_DARKEN_1_TINT) / 2);
|
|
borderBevelLight = tint_color(dark1BorderColor, B_LIGHTEN_1_TINT);
|
|
|
|
borderBevelLight.red = (borderBevelLight.red + panelBgColor.red)
|
|
/ 2;
|
|
borderBevelLight.green = (borderBevelLight.green
|
|
+ panelBgColor.green) / 2;
|
|
borderBevelLight.blue = (borderBevelLight.blue
|
|
+ panelBgColor.blue) / 2;
|
|
|
|
dark1BorderColor = tint_color(dark1BorderColor, B_DARKEN_3_TINT);
|
|
dark2BorderColor = tint_color(dark1BorderColor, B_DARKEN_4_TINT);
|
|
|
|
bevelColorRBCorner = borderBevelShadow;
|
|
} else {
|
|
borderBevelShadow = tint_color(panelBgColor,
|
|
(B_NO_TINT + B_DARKEN_1_TINT) / 2);
|
|
borderBevelLight = buttonBgColor;
|
|
|
|
bevelColorRBCorner = dark1BorderColor;
|
|
}
|
|
} else {
|
|
lightColor = tint_color(panelBgColor, B_LIGHTEN_2_TINT);
|
|
maxLightColor = tint_color(panelBgColor, B_LIGHTEN_1_TINT);
|
|
|
|
dark1BorderColor = tint_color(panelBgColor, B_DARKEN_1_TINT);
|
|
dark2BorderColor = tint_color(panelBgColor, B_DARKEN_2_TINT);
|
|
|
|
bevelColor1 = panelBgColor;
|
|
bevelColor2 = buttonBgColor;
|
|
|
|
if (IsDefault()) {
|
|
borderBevelShadow = dark1BorderColor;
|
|
borderBevelLight = panelBgColor;
|
|
dark1BorderColor = tint_color(dark1BorderColor, B_DARKEN_1_TINT);
|
|
dark2BorderColor = tint_color(dark1BorderColor, 1.16);
|
|
|
|
} else {
|
|
borderBevelShadow = panelBgColor;
|
|
borderBevelLight = panelBgColor;
|
|
}
|
|
|
|
bevelColorRBCorner = tint_color(panelBgColor, 1.08);;
|
|
}
|
|
|
|
// fill the button area
|
|
SetHighColor(buttonBgColor);
|
|
FillRect(fillArea);
|
|
|
|
BeginLineArray(22);
|
|
// bevel around external border
|
|
AddLine(BPoint(rect.left, rect.bottom),
|
|
BPoint(rect.left, rect.top), borderBevelShadow);
|
|
AddLine(BPoint(rect.left + 1, rect.top),
|
|
BPoint(rect.right, rect.top), borderBevelShadow);
|
|
|
|
AddLine(BPoint(rect.right, rect.top + 1),
|
|
BPoint(rect.right, rect.bottom), borderBevelLight);
|
|
AddLine(BPoint(rect.left + 1, rect.bottom),
|
|
BPoint(rect.right - 1, rect.bottom), borderBevelLight);
|
|
|
|
rect.InsetBy(1.0, 1.0);
|
|
|
|
// external border
|
|
AddLine(BPoint(rect.left, rect.bottom),
|
|
BPoint(rect.left, rect.top), dark1BorderColor);
|
|
AddLine(BPoint(rect.left + 1, rect.top),
|
|
BPoint(rect.right, rect.top), dark1BorderColor);
|
|
AddLine(BPoint(rect.right, rect.top + 1),
|
|
BPoint(rect.right, rect.bottom), dark2BorderColor);
|
|
AddLine(BPoint(rect.right - 1, rect.bottom),
|
|
BPoint(rect.left + 1, rect.bottom), dark2BorderColor);
|
|
|
|
rect.InsetBy(1.0, 1.0);
|
|
|
|
// Light
|
|
AddLine(BPoint(rect.left, rect.top),
|
|
BPoint(rect.left, rect.top), buttonBgColor);
|
|
AddLine(BPoint(rect.left, rect.top + 1),
|
|
BPoint(rect.left, rect.bottom - 1), lightColor);
|
|
AddLine(BPoint(rect.left, rect.bottom),
|
|
BPoint(rect.left, rect.bottom), bevelColor2);
|
|
AddLine(BPoint(rect.left + 1, rect.top),
|
|
BPoint(rect.right - 1, rect.top), lightColor);
|
|
AddLine(BPoint(rect.right, rect.top),
|
|
BPoint(rect.right, rect.top), bevelColor2);
|
|
// Shadow
|
|
AddLine(BPoint(rect.left + 1, rect.bottom),
|
|
BPoint(rect.right - 1, rect.bottom), bevelColor1);
|
|
AddLine(BPoint(rect.right, rect.bottom),
|
|
BPoint(rect.right, rect.bottom), bevelColorRBCorner);
|
|
AddLine(BPoint(rect.right, rect.bottom - 1),
|
|
BPoint(rect.right, rect.top + 1), bevelColor1);
|
|
|
|
rect.InsetBy(1.0, 1.0);
|
|
|
|
// Light
|
|
AddLine(BPoint(rect.left, rect.top),
|
|
BPoint(rect.left, rect.bottom - 1), maxLightColor);
|
|
AddLine(BPoint(rect.left, rect.bottom),
|
|
BPoint(rect.left, rect.bottom), buttonBgColor);
|
|
AddLine(BPoint(rect.left + 1, rect.top),
|
|
BPoint(rect.right - 1, rect.top), maxLightColor);
|
|
AddLine(BPoint(rect.right, rect.top),
|
|
BPoint(rect.right, rect.top), buttonBgColor);
|
|
// Shadow
|
|
AddLine(BPoint(rect.left + 1, rect.bottom),
|
|
BPoint(rect.right, rect.bottom), bevelColor2);
|
|
AddLine(BPoint(rect.right, rect.bottom - 1),
|
|
BPoint(rect.right, rect.top + 1), bevelColor2);
|
|
|
|
rect.InsetBy(1.0,1.0);
|
|
|
|
EndLineArray();
|
|
|
|
// Invert if clicked
|
|
if (enabled && pushed) {
|
|
rect.InsetBy(-2.0, -2.0);
|
|
InvertRect(rect);
|
|
}
|
|
|
|
// Label color
|
|
if (enabled) {
|
|
if (pushed) {
|
|
SetHighColor(maxLightColor);
|
|
SetLowColor(255 - buttonBgColor.red,
|
|
255 - buttonBgColor.green,
|
|
255 - buttonBgColor.blue);
|
|
} else {
|
|
SetHighColor(ui_color(B_CONTROL_TEXT_COLOR));
|
|
SetLowColor(buttonBgColor);
|
|
}
|
|
} else {
|
|
SetHighColor(tint_color(panelBgColor, B_DISABLED_LABEL_TINT));
|
|
SetLowColor(buttonBgColor);
|
|
}
|
|
|
|
// Draw the label
|
|
DrawString(text.String(), BPoint(x, labelY));
|
|
|
|
// Focus line
|
|
if (enabled && IsFocus() && Window()->IsActive() && !pushed)
|
|
_DrawFocusLine(x, focusLineY, stringWidth, true);
|
|
}
|
|
|
|
|
|
void
|
|
BButton::MouseDown(BPoint point)
|
|
{
|
|
if (!IsEnabled())
|
|
return;
|
|
|
|
SetValue(B_CONTROL_ON);
|
|
|
|
if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) {
|
|
SetTracking(true);
|
|
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
|
|
} else {
|
|
BRect bounds = Bounds();
|
|
uint32 buttons;
|
|
|
|
do {
|
|
Window()->UpdateIfNeeded();
|
|
snooze(40000);
|
|
|
|
GetMouse(&point, &buttons, true);
|
|
|
|
bool inside = bounds.Contains(point);
|
|
|
|
if ((Value() == B_CONTROL_ON) != inside)
|
|
SetValue(inside ? B_CONTROL_ON : B_CONTROL_OFF);
|
|
} while (buttons != 0);
|
|
|
|
if (Value() == B_CONTROL_ON)
|
|
Invoke();
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
BButton::AttachedToWindow()
|
|
{
|
|
BControl::AttachedToWindow();
|
|
// low color will now be the parents view color
|
|
|
|
if (IsDefault())
|
|
Window()->SetDefaultButton(this);
|
|
|
|
SetViewColor(B_TRANSPARENT_COLOR);
|
|
}
|
|
|
|
|
|
void
|
|
BButton::KeyDown(const char *bytes, int32 numBytes)
|
|
{
|
|
if (*bytes == B_ENTER || *bytes == B_SPACE) {
|
|
if (!IsEnabled())
|
|
return;
|
|
|
|
SetValue(B_CONTROL_ON);
|
|
|
|
// make sure the user saw that
|
|
Window()->UpdateIfNeeded();
|
|
snooze(25000);
|
|
|
|
Invoke();
|
|
|
|
} else
|
|
BControl::KeyDown(bytes, numBytes);
|
|
}
|
|
|
|
|
|
void
|
|
BButton::MakeDefault(bool flag)
|
|
{
|
|
BButton *oldDefault = NULL;
|
|
BWindow *window = Window();
|
|
|
|
if (window)
|
|
oldDefault = window->DefaultButton();
|
|
|
|
if (flag) {
|
|
if (fDrawAsDefault && oldDefault == this)
|
|
return;
|
|
|
|
if (!fDrawAsDefault) {
|
|
fDrawAsDefault = true;
|
|
|
|
ResizeBy(6.0f, 6.0f);
|
|
MoveBy(-3.0f, -3.0f);
|
|
}
|
|
|
|
if (window && oldDefault != this)
|
|
window->SetDefaultButton(this);
|
|
} else {
|
|
if (!fDrawAsDefault)
|
|
return;
|
|
|
|
fDrawAsDefault = false;
|
|
|
|
ResizeBy(-6.0f, -6.0f);
|
|
MoveBy(3.0f, 3.0f);
|
|
|
|
if (window && oldDefault == this)
|
|
window->SetDefaultButton(NULL);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
BButton::SetLabel(const char *string)
|
|
{
|
|
BControl::SetLabel(string);
|
|
}
|
|
|
|
|
|
bool
|
|
BButton::IsDefault() const
|
|
{
|
|
return fDrawAsDefault;
|
|
}
|
|
|
|
|
|
void
|
|
BButton::MessageReceived(BMessage *message)
|
|
{
|
|
BControl::MessageReceived(message);
|
|
}
|
|
|
|
|
|
void
|
|
BButton::WindowActivated(bool active)
|
|
{
|
|
BControl::WindowActivated(active);
|
|
}
|
|
|
|
|
|
void
|
|
BButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
|
|
{
|
|
if (!IsTracking())
|
|
return;
|
|
|
|
bool inside = Bounds().Contains(point);
|
|
|
|
if ((Value() == B_CONTROL_ON) != inside)
|
|
SetValue(inside ? B_CONTROL_ON : B_CONTROL_OFF);
|
|
}
|
|
|
|
|
|
void
|
|
BButton::MouseUp(BPoint point)
|
|
{
|
|
if (!IsTracking())
|
|
return;
|
|
|
|
if (Bounds().Contains(point))
|
|
Invoke();
|
|
|
|
SetTracking(false);
|
|
}
|
|
|
|
|
|
void
|
|
BButton::DetachedFromWindow()
|
|
{
|
|
BControl::DetachedFromWindow();
|
|
}
|
|
|
|
|
|
void
|
|
BButton::SetValue(int32 value)
|
|
{
|
|
if (value != Value())
|
|
BControl::SetValue(value);
|
|
}
|
|
|
|
|
|
void
|
|
BButton::GetPreferredSize(float *_width, float *_height)
|
|
{
|
|
_ValidatePreferredSize();
|
|
|
|
if (_width)
|
|
*_width = fPreferredSize.width;
|
|
|
|
if (_height)
|
|
*_height = fPreferredSize.height;
|
|
}
|
|
|
|
|
|
void
|
|
BButton::ResizeToPreferred()
|
|
{
|
|
BControl::ResizeToPreferred();
|
|
}
|
|
|
|
|
|
status_t
|
|
BButton::Invoke(BMessage *message)
|
|
{
|
|
Sync();
|
|
snooze(50000);
|
|
|
|
status_t err = BControl::Invoke(message);
|
|
|
|
SetValue(B_CONTROL_OFF);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
void
|
|
BButton::FrameMoved(BPoint newLocation)
|
|
{
|
|
BControl::FrameMoved(newLocation);
|
|
}
|
|
|
|
|
|
void
|
|
BButton::FrameResized(float width, float height)
|
|
{
|
|
BControl::FrameResized(width, height);
|
|
}
|
|
|
|
|
|
void
|
|
BButton::MakeFocus(bool focused)
|
|
{
|
|
BControl::MakeFocus(focused);
|
|
}
|
|
|
|
|
|
void
|
|
BButton::AllAttached()
|
|
{
|
|
BControl::AllAttached();
|
|
}
|
|
|
|
|
|
void
|
|
BButton::AllDetached()
|
|
{
|
|
BControl::AllDetached();
|
|
}
|
|
|
|
|
|
BHandler *
|
|
BButton::ResolveSpecifier(BMessage *message, int32 index,
|
|
BMessage *specifier, int32 what,
|
|
const char *property)
|
|
{
|
|
return BControl::ResolveSpecifier(message, index, specifier, what, property);
|
|
}
|
|
|
|
|
|
status_t
|
|
BButton::GetSupportedSuites(BMessage *message)
|
|
{
|
|
return BControl::GetSupportedSuites(message);
|
|
}
|
|
|
|
|
|
status_t
|
|
BButton::Perform(perform_code code, void* _data)
|
|
{
|
|
switch (code) {
|
|
case PERFORM_CODE_MIN_SIZE:
|
|
((perform_data_min_size*)_data)->return_value
|
|
= BButton::MinSize();
|
|
return B_OK;
|
|
case PERFORM_CODE_MAX_SIZE:
|
|
((perform_data_max_size*)_data)->return_value
|
|
= BButton::MaxSize();
|
|
return B_OK;
|
|
case PERFORM_CODE_PREFERRED_SIZE:
|
|
((perform_data_preferred_size*)_data)->return_value
|
|
= BButton::PreferredSize();
|
|
return B_OK;
|
|
case PERFORM_CODE_LAYOUT_ALIGNMENT:
|
|
((perform_data_layout_alignment*)_data)->return_value
|
|
= BButton::LayoutAlignment();
|
|
return B_OK;
|
|
case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
|
|
((perform_data_has_height_for_width*)_data)->return_value
|
|
= BButton::HasHeightForWidth();
|
|
return B_OK;
|
|
case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
|
|
{
|
|
perform_data_get_height_for_width* data
|
|
= (perform_data_get_height_for_width*)_data;
|
|
BButton::GetHeightForWidth(data->width, &data->min, &data->max,
|
|
&data->preferred);
|
|
return B_OK;
|
|
}
|
|
case PERFORM_CODE_SET_LAYOUT:
|
|
{
|
|
perform_data_set_layout* data = (perform_data_set_layout*)_data;
|
|
BButton::SetLayout(data->layout);
|
|
return B_OK;
|
|
}
|
|
case PERFORM_CODE_INVALIDATE_LAYOUT:
|
|
{
|
|
perform_data_invalidate_layout* data
|
|
= (perform_data_invalidate_layout*)_data;
|
|
BButton::InvalidateLayout(data->descendants);
|
|
return B_OK;
|
|
}
|
|
case PERFORM_CODE_DO_LAYOUT:
|
|
{
|
|
BButton::DoLayout();
|
|
return B_OK;
|
|
}
|
|
}
|
|
|
|
return BControl::Perform(code, _data);
|
|
}
|
|
|
|
|
|
void
|
|
BButton::InvalidateLayout(bool descendants)
|
|
{
|
|
// invalidate cached preferred size
|
|
fPreferredSize.Set(-1, -1);
|
|
|
|
BControl::InvalidateLayout(descendants);
|
|
}
|
|
|
|
|
|
BSize
|
|
BButton::MinSize()
|
|
{
|
|
return BLayoutUtils::ComposeSize(ExplicitMinSize(),
|
|
_ValidatePreferredSize());
|
|
}
|
|
|
|
|
|
BSize
|
|
BButton::MaxSize()
|
|
{
|
|
return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
|
|
_ValidatePreferredSize());
|
|
}
|
|
|
|
|
|
BSize
|
|
BButton::PreferredSize()
|
|
{
|
|
return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
|
|
_ValidatePreferredSize());
|
|
}
|
|
|
|
|
|
void BButton::_ReservedButton1() {}
|
|
void BButton::_ReservedButton2() {}
|
|
void BButton::_ReservedButton3() {}
|
|
|
|
|
|
BButton &
|
|
BButton::operator=(const BButton &)
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
|
|
BSize
|
|
BButton::_ValidatePreferredSize()
|
|
{
|
|
if (fPreferredSize.width < 0) {
|
|
// width
|
|
float width = 20.0f + (float)ceil(StringWidth(Label()));
|
|
if (width < 75.0f)
|
|
width = 75.0f;
|
|
|
|
if (fDrawAsDefault)
|
|
width += 6.0f;
|
|
|
|
fPreferredSize.width = width;
|
|
|
|
// height
|
|
font_height fontHeight;
|
|
GetFontHeight(&fontHeight);
|
|
|
|
fPreferredSize.height
|
|
= ceilf((fontHeight.ascent + fontHeight.descent) * 1.8)
|
|
+ (fDrawAsDefault ? 6.0f : 0);
|
|
}
|
|
|
|
return fPreferredSize;
|
|
}
|
|
|
|
|
|
BRect
|
|
BButton::_DrawDefault(BRect bounds, bool enabled)
|
|
{
|
|
rgb_color low = LowColor();
|
|
rgb_color focusColor = tint_color(low, enabled ?
|
|
(B_DARKEN_1_TINT + B_DARKEN_2_TINT) / 2
|
|
: (B_NO_TINT + B_DARKEN_1_TINT) / 2);
|
|
|
|
SetHighColor(focusColor);
|
|
|
|
StrokeRect(bounds, B_SOLID_LOW);
|
|
bounds.InsetBy(1.0, 1.0);
|
|
StrokeRect(bounds);
|
|
bounds.InsetBy(1.0, 1.0);
|
|
StrokeRect(bounds);
|
|
bounds.InsetBy(1.0, 1.0);
|
|
|
|
return bounds;
|
|
}
|
|
|
|
|
|
void
|
|
BButton::_DrawFocusLine(float x, float y, float width, bool visible)
|
|
{
|
|
if (visible)
|
|
SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
|
|
else {
|
|
SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
|
|
B_LIGHTEN_1_TINT));
|
|
}
|
|
|
|
// Blue Line
|
|
StrokeLine(BPoint(x, y), BPoint(x + width, y));
|
|
|
|
if (visible)
|
|
SetHighColor(255, 255, 255);
|
|
// White Line
|
|
StrokeLine(BPoint(x, y + 1.0f), BPoint(x + width, y + 1.0f));
|
|
}
|
|
|
|
|