/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "OptionValueView.h"
#include <stdio.h>
#include <Font.h>
#include <MenuItem.h>
#include <Message.h>
#include <PopUpMenu.h>
#include <Region.h>
enum {
MSG_OPTION_CHANGED = 'opch',
};
// constructor
OptionValueView::OptionValueView(OptionProperty* property)
: PropertyEditorView(),
fProperty(property),
fCurrentOption(""),
fEnabled(true)
{
if (fProperty)
fProperty->GetCurrentOption(&fCurrentOption);
}
// destructor
OptionValueView::~OptionValueView()
{
}
// Draw
void
OptionValueView::Draw(BRect updateRect)
{
BRect b(Bounds());
// focus indication
if (IsFocus()) {
SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
StrokeRect(b);
b.InsetBy(1.0, 1.0);
BRegion clipping;
clipping.Include(b);
ConstrainClippingRegion(&clipping);
b.left --;
}
// background
FillRect(b, B_SOLID_LOW);
rgb_color labelColor = LowColor();
if (fEnabled)
labelColor = tint_color(labelColor, B_DARKEN_MAX_TINT);
else
labelColor = tint_color(labelColor, B_DISABLED_LABEL_TINT);
SetHighColor(labelColor);
b.InsetBy(2.0, 1.0);
float center = floorf(b.top + b.Height() / 2.0);
BPoint arrow[3];
arrow[0] = BPoint(b.left, center - 3.0);
arrow[1] = BPoint(b.left, center + 3.0);
arrow[2] = BPoint(b.left + 3.0, center);
FillPolygon(arrow, 3);
b.left += 6.0;
BFont font;
GetFont(&font);
font_height fh;
font.GetHeight(&fh);
BString truncated(fCurrentOption);
font.TruncateString(&truncated, B_TRUNCATE_END, b.Width());
DrawString(fCurrentOption.String(), BPoint(b.left, floorf(center + fh.ascent / 2.0)));
}
// FrameResized
void
OptionValueView::FrameResized(float width, float height)
{
/* float radius = ceilf((height - 6.0) / 2.0);
float centerX = floorf(Bounds().left + width / 2.0);
float centerY = floorf(Bounds().top + height / 2.0);
fCheckBoxRect.Set(centerX - radius, centerY - radius,
centerX + radius, centerY + radius);*/
}
// MakeFocus
void
OptionValueView::MakeFocus(bool focused)
{
PropertyEditorView::MakeFocus(focused);
Invalidate();
}
// MessageReceived
void
OptionValueView::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_OPTION_CHANGED:
if (fProperty) {
int32 id;
if (message->FindInt32("id", &id) >= B_OK) {
fProperty->SetCurrentOptionID(id);
ValueChanged();
}
}
break;
default:
PropertyEditorView::MessageReceived(message);
break;
}
}
// MouseDown
void
OptionValueView::MouseDown(BPoint where)
{
if (BView* parent = Parent())
parent->MouseDown(ConvertToParent(where));
if (fProperty) {
BPopUpMenu* menu = new BPopUpMenu("option popup", false, false);
BString name;
int32 id;
for (int32 i = 0; fProperty->GetOption(i, &name, &id); i++) {
BMessage* message = new BMessage(MSG_OPTION_CHANGED);
message->AddInt32("id", id);
BMenuItem* item = new BMenuItem(name.String(), message);
menu->AddItem(item);
if (id == fProperty->CurrentOptionID())
item->SetMarked(true);
}
menu->SetTargetForItems(this);
menu->SetAsyncAutoDestruct(true);
menu->SetFont(be_plain_font);
menu->SetEnabled(fEnabled);
where = ConvertToScreen(where);
BRect mouseRect(where, where);
mouseRect.InsetBy(-10.0, -10.0);
where += BPoint(5.0, 5.0);
menu->Go(where, true, false, mouseRect, true);
}
}
// KeyDown
void
OptionValueView::KeyDown(const char* bytes, int32 numBytes)
{
bool handled = fEnabled;
if (fEnabled && numBytes > 0) {
switch (bytes[0]) {
case B_LEFT_ARROW:
case B_UP_ARROW:
fProperty->SetOptionAtOffset(-1);
ValueChanged();
break;
case B_RIGHT_ARROW:
case B_DOWN_ARROW:
fProperty->SetOptionAtOffset(1);
ValueChanged();
break;
default:
handled = false;
break;
}
}
if (!handled)
PropertyEditorView::KeyDown(bytes, numBytes);
}
// SetEnabled
void
OptionValueView::SetEnabled(bool enabled)
{
if (fEnabled != enabled) {
fEnabled = enabled;
Invalidate();
}
}
// ValueChanged
void
OptionValueView::ValueChanged()
{
if (fProperty) {
fProperty->GetCurrentOption(&fCurrentOption);
BRect b(Bounds());
b.InsetBy(1.0, 1.0);
b.left += 5.0;
Invalidate(b);
}
PropertyEditorView::ValueChanged();
}
// AdoptProperty
bool
OptionValueView::AdoptProperty(Property* property)
{
OptionProperty* p = dynamic_cast<OptionProperty*>(property);
if (p) {
BString currentOption;
p->GetCurrentOption(¤tOption);
if (currentOption != fCurrentOption) {
fCurrentOption = currentOption;
BRect b(Bounds());
b.InsetBy(1.0, 1.0);
b.left += 5.0;
Invalidate(b);
}
fProperty = p;
return true;
}
return false;
}
// GetProperty
Property*
OptionValueView::GetProperty() const
{
return fProperty;
}
↑ V773 Visibility scope of the 'menu' pointer was exited without releasing the memory. A memory leak is possible.