added extensive "PropertyObject" framework

* Property is an abstract class for representing some property with
  an interface for setting/getting the value and cloning
  the property and such stuff
* PropertyObject holds a bunch of different Properties
* various specific Property classes represent floats, integers,
  colors, booleans, options and so on
* PropertyListView can edit the different properties in a
  given PropertyObject by using individual property editor views

The plan is to be able to convert some random object (for example
a selected Shape or Transformer, Style or whatever) into a
PropertyObject for being edited in the PropertyListView like it is
done in WonderBrush...


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18036 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2006-07-05 02:09:43 +00:00
parent a6d3f8a9da
commit 64d80db621
44 changed files with 4943 additions and 3 deletions

View File

@ -15,6 +15,10 @@ local sourceDirs =
generic/gui/scrollview
generic/gui/stateview
generic/listener
generic/property
generic/property/specific_properties
generic/property/view
generic/property/view/specific_properties
generic/selection
generic/support
gui
@ -41,11 +45,11 @@ Application Icon-O-Matic :
# generic/command
Command.cpp
CommandStack.cpp
# generic/selection
Selectable.cpp
Selection.cpp
# generic/gui
Group.cpp
InputTextView.cpp
NummericalTextView.cpp
StringTextView.cpp
ListViews.cpp
SwatchView.cpp
# generic/gui/panel
@ -58,6 +62,9 @@ Application Icon-O-Matic :
ColorSlider.cpp
# generic/gui/popup_control
# generic/gui/scrollview
Scrollable.cpp
Scroller.cpp
ScrollView.cpp
# generic/gui/stateview
Manipulator.cpp
MultipleManipulatorState.cpp
@ -66,7 +73,34 @@ Application Icon-O-Matic :
# generic/listener
Observable.cpp
Observer.cpp
# generic/property
CommonPropertyIDs.cpp
Property.cpp
PropertyObject.cpp
# generic/property/specific_properties
ColorProperty.cpp
Int64Property.cpp
OptionProperty.cpp
# generic/property/view
PropertyEditorFactory.cpp
PropertyEditorView.cpp
PropertyItemView.cpp
PropertyListView.cpp
# generic/property/view/specific_properties
BoolValueView.cpp
ColorValueView.cpp
FloatValueView.cpp
IconProperty.cpp
IconValueView.cpp
Int64ValueView.cpp
IntValueView.cpp
OptionValueView.cpp
StringValueView.cpp
SwatchValueView.cpp
TextInputValueView.cpp
# generic/selection
Selectable.cpp
Selection.cpp
# generic/support
RWLocker.cpp
support.cpp

View File

@ -9,6 +9,8 @@
#ifndef SCROLLER_H
#define SCROLLER_H
#include <Rect.h>
class Scrollable;
class Scroller {

View File

@ -0,0 +1,51 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "CommonPropertyIDs.h"
// name_for_id
const char*
name_for_id(int32 id)
{
const char* name = NULL;
switch (id) {
case PROPERTY_NAME:
name = "Name";
break;
case PROPERTY_OPACITY:
name = "Opacity";
break;
case PROPERTY_COLOR:
name = "Color";
break;
case PROPERTY_WIDTH:
name = "Width";
break;
case PROPERTY_HEIGHT:
name = "Height";
break;
case PROPERTY_CAP_MODE:
name = "Caps";
break;
case PROPERTY_JOIN_MODE:
name = "Joins";
break;
case PROPERTY_MITER_LIMIT:
name = "Miter Limit";
break;
default:
name = "<unkown property>";
break;
}
return name;
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef COMMON_PROPERTY_IDS_H
#define COMMON_PROPERTY_IDS_H
#include <SupportDefs.h>
enum {
PROPERTY_NAME = 'name',
PROPERTY_OPACITY = 'alpa',
PROPERTY_COLOR = 'colr',
PROPERTY_WIDTH = 'wdth',
PROPERTY_HEIGHT = 'hght',
PROPERTY_CAP_MODE = 'cpmd',
PROPERTY_JOIN_MODE = 'jnmd',
PROPERTY_MITER_LIMIT = 'mtlm',
};
const char* name_for_id(int32 id);
#endif // COMMON_PROPERTY_IDS_H

View File

@ -0,0 +1,463 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "Property.h"
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Message.h>
#include "support.h"
using std::nowthrow;
// constructor
Property::Property(uint32 identifier)
: fIdentifier(identifier),
fEditable(true)
{
}
// constructor
Property::Property(const Property& other)
: fIdentifier(other.fIdentifier),
fEditable(other.fEditable)
{
}
// constructor
Property::Property(BMessage* archive)
: fIdentifier(0),
fEditable(true)
{
if (!archive)
return;
if (archive->FindInt32("id", (int32*)&fIdentifier) < B_OK)
fIdentifier = 0;
if (archive->FindBool("editable", &fEditable) < B_OK)
fEditable = true;
}
// destructor
Property::~Property()
{
}
// InterpolateTo
bool
Property::InterpolateTo(const Property* other, float scale)
{
// some properties don't support this
return false;
}
// SetEditable
void
Property::SetEditable(bool editable)
{
fEditable = editable;
}
// #pragma mark -
// constructor
IntProperty::IntProperty(uint32 identifier, int32 value,
int32 min, int32 max)
: Property(identifier),
fValue(value),
fMin(min),
fMax(max)
{
}
// constructor
IntProperty::IntProperty(const IntProperty& other)
: Property(other),
fValue(other.fValue),
fMin(other.fMin),
fMax(other.fMax)
{
}
// destructor
IntProperty::~IntProperty()
{
}
// Clone
Property*
IntProperty::Clone() const
{
return new IntProperty(*this);
}
// SetValue
bool
IntProperty::SetValue(const char* value)
{
return SetValue(atoi(value));
}
// SetValue
bool
IntProperty::SetValue(const Property* other)
{
const IntProperty* i = dynamic_cast<const IntProperty*>(other);
if (i) {
return SetValue(i->Value());
}
return false;
}
// GetValue
void
IntProperty::GetValue(BString& string)
{
string << fValue;
}
// InterpolateTo
bool
IntProperty::InterpolateTo(const Property* other, float scale)
{
const IntProperty* i = dynamic_cast<const IntProperty*>(other);
if (i) {
return SetValue(fValue + (int32)((float)(i->Value()
- fValue) * scale + 0.5));
}
return false;
}
// SetValue
bool
IntProperty::SetValue(int32 value)
{
// truncate
if (value < fMin)
value = fMin;
if (value > fMax)
value = fMax;
if (value != fValue) {
fValue = value;
return true;
}
return false;
}
// #pragma mark -
// constructor
FloatProperty::FloatProperty(uint32 identifier, float value,
float min, float max)
: Property(identifier),
fValue(value),
fMin(min),
fMax(max)
{
}
// constructor
FloatProperty::FloatProperty(const FloatProperty& other)
: Property(other),
fValue(other.fValue),
fMin(other.fMin),
fMax(other.fMax)
{
}
// destructor
FloatProperty::~FloatProperty()
{
}
// Clone
Property*
FloatProperty::Clone() const
{
return new FloatProperty(*this);
}
// SetValue
bool
FloatProperty::SetValue(const char* value)
{
return SetValue(atof(value));
}
// SetValue
bool
FloatProperty::SetValue(const Property* other)
{
const FloatProperty* f = dynamic_cast<const FloatProperty*>(other);
if (f) {
return SetValue(f->Value());
}
return false;
}
// GetValue
void
FloatProperty::GetValue(BString& string)
{
append_float(string, fValue, 4);
}
// InterpolateTo
bool
FloatProperty::InterpolateTo(const Property* other, float scale)
{
const FloatProperty* f = dynamic_cast<const FloatProperty*>(other);
if (f) {
return SetValue(fValue + (f->Value() - fValue) * scale);
}
return false;
}
// SetValue
bool
FloatProperty::SetValue(float value)
{
// truncate
if (value < fMin)
value = fMin;
if (value > fMax)
value = fMax;
if (value != fValue) {
fValue = value;
return true;
}
return false;
}
// #pragma mark -
// constructor
UInt8Property::UInt8Property(uint32 identifier, uint8 value)
: Property(identifier),
fValue(value)
{
}
// constructor
UInt8Property::UInt8Property(const UInt8Property& other)
: Property(other),
fValue(other.fValue)
{
}
// destructor
UInt8Property::~UInt8Property()
{
}
// Clone
Property*
UInt8Property::Clone() const
{
return new UInt8Property(*this);
}
// SetValue
bool
UInt8Property::SetValue(const char* value)
{
return SetValue((uint8)max_c(0, min_c(255, atoi(value))));
}
// SetValue
bool
UInt8Property::SetValue(const Property* other)
{
const UInt8Property* u = dynamic_cast<const UInt8Property*>(other);
if (u) {
return SetValue(u->Value());
}
return false;
}
// GetValue
void
UInt8Property::GetValue(BString& string)
{
string << fValue;
}
// InterpolateTo
bool
UInt8Property::InterpolateTo(const Property* other, float scale)
{
const UInt8Property* u = dynamic_cast<const UInt8Property*>(other);
if (u) {
return SetValue(fValue + (uint8)((float)(u->Value()
- fValue) * scale + 0.5));
}
return false;
}
// SetValue
bool
UInt8Property::SetValue(uint8 value)
{
if (value != fValue) {
fValue = value;
return true;
}
return false;
}
// #pragma mark -
// constructor
BoolProperty::BoolProperty(uint32 identifier, bool value)
: Property(identifier),
fValue(value)
{
}
// constructor
BoolProperty::BoolProperty(const BoolProperty& other)
: Property(other),
fValue(other.fValue)
{
}
// destructor
BoolProperty::~BoolProperty()
{
}
// Clone
Property*
BoolProperty::Clone() const
{
return new BoolProperty(*this);
}
// SetValue
bool
BoolProperty::SetValue(const char* value)
{
bool v;
if (strcasecmp(value, "true") == 0)
v = true;
else if (strcasecmp(value, "on") == 0)
v = true;
else
v = (bool)atoi(value);
return SetValue(v);
}
// SetValue
bool
BoolProperty::SetValue(const Property* other)
{
const BoolProperty* b = dynamic_cast<const BoolProperty*>(other);
if (b) {
return SetValue(b->Value());
}
return false;
}
// GetValue
void
BoolProperty::GetValue(BString& string)
{
if (fValue)
string << "on";
else
string << "off";
}
// InterpolateTo
bool
BoolProperty::InterpolateTo(const Property* other, float scale)
{
const BoolProperty* b = dynamic_cast<const BoolProperty*>(other);
if (b) {
if (scale >= 0.5)
return SetValue(b->Value());
}
return false;
}
// SetValue
bool
BoolProperty::SetValue(bool value)
{
if (value != fValue) {
fValue = value;
return true;
}
return false;
}
// #pragma mark -
// constructor
StringProperty::StringProperty(uint32 identifier, const char* value)
: Property(identifier),
fValue(value)
{
}
// constructor
StringProperty::StringProperty(const StringProperty& other)
: Property(other),
fValue(other.fValue)
{
}
// destructor
StringProperty::~StringProperty()
{
}
// Clone
Property*
StringProperty::Clone() const
{
return new StringProperty(*this);
}
// SetValue
bool
StringProperty::SetValue(const char* value)
{
BString t(value);
if (fValue != t) {
fValue = t;
return true;
}
return false;
}
// SetValue
bool
StringProperty::SetValue(const Property* other)
{
const StringProperty* s = dynamic_cast<const StringProperty*>(other);
if (s) {
return SetValue(s->Value());
}
return false;
}
// GetValue
void
StringProperty::GetValue(BString& string)
{
string << fValue;
}

View File

@ -0,0 +1,214 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef PROPERTY_H
#define PROPERTY_H
#include <limits.h>
#include <Archivable.h>
#include <String.h>
#include <TypeConstants.h>
class PropertyAnimator;
// Property
class Property : public BArchivable {
// TODO: actually use BArchivable!
public:
Property(uint32 identifier);
Property(const Property& other);
Property(BMessage* archive);
virtual ~Property();
virtual Property* Clone() const = 0;
virtual type_code Type() const = 0;
virtual bool SetValue(const char* value) = 0;
virtual bool SetValue(const Property* other) = 0;
virtual void GetValue(BString& string) = 0;
// animation
virtual bool InterpolateTo(const Property* other,
float scale);
inline uint32 Identifier() const
{ return fIdentifier; }
void SetEditable(bool editable);
inline bool IsEditable() const
{ return fEditable; }
private:
uint32 fIdentifier;
bool fEditable;
};
// IntProperty
class IntProperty : public Property {
public:
IntProperty(uint32 identifier,
int32 value = 0,
int32 min = LONG_MIN,
int32 max = LONG_MAX);
IntProperty(const IntProperty& other);
virtual ~IntProperty();
virtual Property* Clone() const;
virtual type_code Type() const
{ return B_INT32_TYPE; }
virtual bool SetValue(const char* value);
virtual bool SetValue(const Property* other);
virtual void GetValue(BString& string);
virtual bool InterpolateTo(const Property* other,
float scale);
// IntProperty
bool SetValue(int32 value);
inline int32 Value() const
{ return fValue; }
inline int32 Min() const
{ return fMin; }
inline int32 Max() const
{ return fMax; }
private:
int32 fValue;
int32 fMin;
int32 fMax;
};
// FloatProperty
class FloatProperty : public Property {
public:
FloatProperty(uint32 identifier,
float value = 0.0,
float min = -1000000.0,
float max = 1000000.0);
FloatProperty(const FloatProperty& other);
virtual ~FloatProperty();
virtual Property* Clone() const;
virtual type_code Type() const
{ return B_FLOAT_TYPE; }
virtual bool SetValue(const char* value);
virtual bool SetValue(const Property* other);
virtual void GetValue(BString& string);
virtual bool InterpolateTo(const Property* other,
float scale);
// FloatProperty
bool SetValue(float value);
inline float Value() const
{ return fValue; }
inline float Min() const
{ return fMin; }
inline float Max() const
{ return fMax; }
private:
float fValue;
float fMin;
float fMax;
};
// UInt8Property
class UInt8Property : public Property {
public:
UInt8Property(uint32 identifier,
uint8 value = 255);
UInt8Property(const UInt8Property& other);
virtual ~UInt8Property();
virtual Property* Clone() const;
virtual type_code Type() const
{ return B_INT8_TYPE; }
virtual bool SetValue(const char* value);
virtual bool SetValue(const Property* other);
virtual void GetValue(BString& string);
virtual bool InterpolateTo(const Property* other,
float scale);
// UInt8Property
bool SetValue(uint8 value);
inline uint8 Value() const
{ return fValue; }
private:
uint8 fValue;
};
// BoolProperty
class BoolProperty : public Property {
public:
BoolProperty(uint32 identifier,
bool value = false);
BoolProperty(const BoolProperty& other);
virtual ~BoolProperty();
virtual Property* Clone() const;
virtual type_code Type() const
{ return B_BOOL_TYPE; }
virtual bool SetValue(const char* value);
virtual bool SetValue(const Property* other);
virtual void GetValue(BString& string);
virtual bool InterpolateTo(const Property* other,
float scale);
// BoolProperty
bool SetValue(bool value);
inline bool Value() const
{ return fValue; }
private:
bool fValue;
};
// StringProperty
class StringProperty : public Property {
public:
StringProperty(uint32 identifier,
const char* string);
StringProperty(const StringProperty& other);
virtual ~StringProperty();
virtual Property* Clone() const;
virtual type_code Type() const
{ return B_STRING_TYPE; }
virtual bool SetValue(const char* value);
virtual bool SetValue(const Property* other);
virtual void GetValue(BString& string);
// StringProperty
inline const char* Value() const
{ return fValue.String(); }
private:
BString fValue;
};
#endif // PROPERTY_H

View File

@ -0,0 +1,365 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "PropertyObject.h"
#include <stdio.h>
#include <ByteOrder.h>
#include <Message.h>
#include <OS.h>
#include "Int64Property.h"
#include "Property.h"
#ifndef DEBUG
# define DEBUG 0
#endif
// constructor
PropertyObject::PropertyObject()
: fProperties(16)
{
}
// constructor
PropertyObject::PropertyObject(const PropertyObject& other)
: fProperties(16)
{
Assign(other);
}
// destructor
PropertyObject::~PropertyObject()
{
DeleteProperties();
}
// #pragma mark -
// Archive
status_t
PropertyObject::Archive(BMessage* into) const
{
if (!into)
return B_BAD_VALUE;
status_t ret = B_OK;
int32 count = CountProperties();
for (int32 i = 0; i < count; i++) {
Property* p = PropertyAtFast(i);
unsigned id = B_HOST_TO_BENDIAN_INT32(p->Identifier());
char idString[5];
sprintf(idString, "%.4s", (const char*)&id);
idString[4] = 0;
BString value;
p->GetValue(value);
ret = into->AddString(idString, value.String());
if (ret < B_OK)
return ret;
}
return ret;
}
// Unarchive
status_t
PropertyObject::Unarchive(const BMessage* archive)
{
if (!archive)
return B_BAD_VALUE;
SuspendNotifications(true);
int32 count = CountProperties();
for (int32 i = 0; i < count; i++) {
Property* p = PropertyAtFast(i);
unsigned id = B_HOST_TO_BENDIAN_INT32(p->Identifier());
char idString[5];
sprintf(idString, "%.4s", (const char*)&id);
idString[4] = 0;
const char* value;
if (archive->FindString(idString, &value) == B_OK)
if (p->SetValue(value))
Notify();
}
SuspendNotifications(false);
return B_OK;
}
// #pragma mark -
// AddProperty
bool
PropertyObject::AddProperty(Property* property)
{
if (!property)
return false;
#if DEBUG
if (FindProperty(property->Identifier())) {
debugger("PropertyObject::AddProperty() -"
"property with same ID already here!\n");
return false;
}
// debugging
if (fProperties.HasItem((void*)property)) {
debugger("PropertyObject::AddProperty() - property id "
"changed unexpectedly\n");
return false;
}
#endif
if (fProperties.AddItem((void*)property)) {
Notify();
return true;
}
return false;
}
// PropertyAt
Property*
PropertyObject::PropertyAt(int32 index) const
{
return (Property*)fProperties.ItemAt(index);
}
// PropertyAtFast
Property*
PropertyObject::PropertyAtFast(int32 index) const
{
return (Property*)fProperties.ItemAtFast(index);
}
// CountProperties
int32
PropertyObject::CountProperties() const
{
return fProperties.CountItems();
}
// #pragma mark -
// FindProperty
Property*
PropertyObject::FindProperty(uint32 propertyID) const
{
int32 count = fProperties.CountItems();
for (int32 i = 0; i < count; i++) {
Property* p = (Property*)fProperties.ItemAtFast(i);
if (p->Identifier() == propertyID)
return p;
}
return NULL;
}
// ContainsSameProperties
bool
PropertyObject::ContainsSameProperties(const PropertyObject& other) const
{
bool equal = false;
int32 count = CountProperties();
if (count == other.CountProperties()) {
equal = true;
for (int32 i = 0; i < count; i++) {
Property* ownProperty = PropertyAtFast(i);
Property* otherProperty = other.PropertyAtFast(i);
if (ownProperty->Identifier() != otherProperty->Identifier()) {
equal = false;
break;
}
}
}
return equal;
}
// Assign
status_t
PropertyObject::Assign(const PropertyObject& other)
{
DeleteProperties();
int32 count = other.fProperties.CountItems();
for (int32 i = 0; i < count; i++) {
Property* p = (Property*)other.fProperties.ItemAtFast(i);
Property* clone = p->Clone();
if (!AddProperty(clone)) {
delete clone;
fprintf(stderr, "PropertyObject::Assign() - no memory for "
"cloning properties!\n");
return B_NO_MEMORY;
}
}
return B_OK;
}
// DeleteProperties
void
PropertyObject::DeleteProperties()
{
int32 count = fProperties.CountItems();
for (int32 i = 0; i < count; i++)
delete (Property*)fProperties.ItemAtFast(i);
fProperties.MakeEmpty();
Notify();
}
// DeleteProperty
bool
PropertyObject::DeleteProperty(uint32 propertyID)
{
int32 count = fProperties.CountItems();
for (int32 i = 0; i < count; i++) {
Property* p = (Property*)fProperties.ItemAtFast(i);
if (p->Identifier() == propertyID) {
if (fProperties.RemoveItem(i)) {
Notify();
delete p;
return true;
}
break;
}
}
return false;
}
// ValueChanged
void
PropertyObject::ValueChanged(uint32 propertyID)
{
Notify();
}
// #pragma mark -
// SetValue
bool
PropertyObject::SetValue(uint32 propertyID, const char* value)
{
if (Property* p = FindProperty(propertyID)) {
if (p->SetValue(value)) {
ValueChanged(propertyID);
return true;
}
}
return false;
}
// GetValue
bool
PropertyObject::GetValue(uint32 propertyID, BString& value) const
{
if (Property* p = FindProperty(propertyID)) {
p->GetValue(value);
return true;
}
return false;
}
// #pragma mark - int32
// SetValue
bool
PropertyObject::SetValue(uint32 propertyID, int32 value)
{
IntProperty* p = dynamic_cast<IntProperty*>(FindProperty(propertyID));
if (p && p->SetValue(value)) {
ValueChanged(propertyID);
return true;
}
return false;
}
// Value
int32
PropertyObject::Value(uint32 propertyID, int32 defaultValue) const
{
if (IntProperty* p = dynamic_cast<IntProperty*>(FindProperty(propertyID)))
return p->Value();
return defaultValue;
}
// #pragma mark - int64
// SetValue
bool
PropertyObject::SetValue(uint32 propertyID, int64 value)
{
Int64Property* p = dynamic_cast<Int64Property*>(FindProperty(propertyID));
if (p && p->SetValue(value)) {
ValueChanged(propertyID);
return true;
}
return false;
}
// Value
int64
PropertyObject::Value(uint32 propertyID, int64 defaultValue) const
{
if (Int64Property* p = dynamic_cast<Int64Property*>(FindProperty(propertyID)))
return p->Value();
return defaultValue;
}
// #pragma mark - float
// SetValue
bool
PropertyObject::SetValue(uint32 propertyID, float value)
{
FloatProperty* p = dynamic_cast<FloatProperty*>(FindProperty(propertyID));
if (p && p->SetValue(value)) {
ValueChanged(propertyID);
return true;
}
return false;
}
// Value
float
PropertyObject::Value(uint32 propertyID, float defaultValue) const
{
if (FloatProperty* p = dynamic_cast<FloatProperty*>(FindProperty(propertyID)))
return p->Value();
return defaultValue;
}
// #pragma mark - bool
// SetValue
bool
PropertyObject::SetValue(uint32 propertyID, bool value)
{
BoolProperty* p = dynamic_cast<BoolProperty*>(FindProperty(propertyID));
if (p && p->SetValue(value)) {
ValueChanged(propertyID);
return true;
}
return false;
}
// Value
bool
PropertyObject::Value(uint32 propertyID, bool defaultValue) const
{
if (BoolProperty* p = dynamic_cast<BoolProperty*>(FindProperty(propertyID)))
return p->Value();
return defaultValue;
}

View File

@ -0,0 +1,78 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef PROPERTY_OBJECT_H
#define PROPERTY_OBJECT_H
#include "Observable.h"
class BMessage;
class BString;
class Property;
class PropertyObject : public Observable {
public:
PropertyObject();
PropertyObject(const PropertyObject& other);
virtual ~PropertyObject();
status_t Archive(BMessage* into) const;
status_t Unarchive(const BMessage* archive);
bool AddProperty(Property* property);
Property* PropertyAt(int32 index) const;
Property* PropertyAtFast(int32 index) const;
int32 CountProperties() const;
Property* FindProperty(uint32 propertyID) const;
bool ContainsSameProperties(
const PropertyObject& other) const;
private:
status_t Assign(const PropertyObject& other);
public:
void DeleteProperties();
bool DeleteProperty(uint32 propertyID);
virtual void ValueChanged(uint32 propertyID);
// common interface for any property
bool SetValue(uint32 propertyID,
const char* value);
bool GetValue(uint32 propertyID,
BString& value) const;
// access to more specific property types
bool SetValue(uint32 propertyID,
int32 value);
int32 Value(uint32 propertyID,
int32 defaultValue) const;
bool SetValue(uint32 propertyID,
int64 value);
int64 Value(uint32 propertyID,
int64 defaultValue) const;
bool SetValue(uint32 propertyID,
float value);
float Value(uint32 propertyID,
float defaultValue) const;
bool SetValue(uint32 propertyID,
bool value);
bool Value(uint32 propertyID,
bool defaultValue) const;
private:
BList fProperties;
};
#endif // PROPERTY_OBJECT_H

View File

@ -0,0 +1,145 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "ColorProperty.h"
#include <new>
#include <stdio.h>
#include "support_ui.h"
#include "ui_defines.h"
using std::nothrow;
// constructor
ColorProperty::ColorProperty(uint32 identifier)
: Property(identifier),
fValue(kBlack)
{
}
// constructor
ColorProperty::ColorProperty(uint32 identifier, rgb_color color)
: Property(identifier),
fValue(color)
{
}
// constructor
ColorProperty::ColorProperty(const ColorProperty& other)
: Property(other),
fValue(other.fValue)
{
}
// destrucor
ColorProperty::~ColorProperty()
{
}
// Clone
Property*
ColorProperty::Clone() const
{
return new (nothrow) ColorProperty(*this);
}
// SetValue
bool
ColorProperty::SetValue(const char* str)
{
rgb_color value = fValue;
if (*str == '#') {
str++;
int32 length = strlen(str);
unsigned scannedColor = 0;
char expanded[7];
if (length == 3) {
// if there are only 3 bytes, than it means that we
// need to expand the color (#f60 -> #ff6600)
// TODO: There must be an easier way...
expanded[0] = *str;
expanded[1] = *str++;
expanded[2] = *str;
expanded[3] = *str++;
expanded[4] = *str;
expanded[5] = *str++;
expanded[6] = 0;
str = expanded;
}
if (sscanf(str, "%x", &scannedColor) == 1) {
uint8* colorByte = (uint8*)&scannedColor;
value.red = colorByte[3];
value.green = colorByte[2];
value.blue = colorByte[1];
value.alpha = colorByte[0];
}
} else {
// TODO: parse "named color"
}
return SetValue(value);
}
// SetValue
bool
ColorProperty::SetValue(const Property* other)
{
const ColorProperty* c = dynamic_cast<const ColorProperty*>(other);
if (c)
return SetValue(c->Value());
return false;
}
// GetValue
void
ColorProperty::GetValue(BString& string)
{
char valueString[16];
sprintf(valueString, "#%02x%02x%02x%02x",
fValue.red, fValue.green, fValue.blue, fValue.alpha);
string << valueString;
}
// InterpolateTo
bool
ColorProperty::InterpolateTo(const Property* other, float scale)
{
const ColorProperty* c = dynamic_cast<const ColorProperty*>(other);
if (c) {
rgb_color a = fValue;
const rgb_color& b = c->fValue;
a.red = a.red + (uint8)floorf((b.red - a.red) * scale + 0.5);
a.green = a.green + (uint8)floorf((b.green - a.green) * scale + 0.5);
a.blue = a.blue + (uint8)floorf((b.blue - a.blue) * scale + 0.5);
a.alpha = a.alpha + (uint8)floorf((b.alpha - a.alpha) * scale + 0.5);
return SetValue(a);
}
return false;
}
// SetValue
bool
ColorProperty::SetValue(rgb_color color)
{
if (fValue != color) {
fValue = color;
return true;
}
return false;
}
// Value
rgb_color
ColorProperty::Value() const
{
return fValue;
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef COLOR_PROPERTY_H
#define COLOR_PROPERTY_H
#include <GraphicsDefs.h>
#include "Property.h"
class ColorProperty : public Property {
public:
ColorProperty(uint32 identifier);
ColorProperty(uint32 identifier,
rgb_color color);
ColorProperty(const ColorProperty& other);
virtual ~ColorProperty();
virtual Property* Clone() const;
virtual type_code Type() const
{ return B_RGB_COLOR_TYPE; }
virtual bool SetValue(const char* value);
virtual bool SetValue(const Property* other);
virtual void GetValue(BString& string);
virtual bool InterpolateTo(const Property* other,
float scale);
// ColorProperty
bool SetValue(rgb_color color);
rgb_color Value() const;
private:
rgb_color fValue;
};
#endif // COLOR_PROPERTY_H

View File

@ -0,0 +1,137 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "IconProperty.h"
#include <new>
#include <Message.h>
using std::nothrow;
// constructor
IconProperty::IconProperty(uint32 identifier,
const uchar* icon,
uint32 width, uint32 height,
color_space format,
BMessage* message)
: Property(identifier),
fMessage(message),
fIcon(icon),
fWidth(width),
fHeight(height),
fFormat(format)
{
}
// archive constructor
IconProperty::IconProperty(const IconProperty& other)
: Property(other),
fMessage(other.fMessage ? new BMessage(*other.fMessage) : NULL),
fIcon(other.fIcon),
fWidth(other.fWidth),
fHeight(other.fHeight),
fFormat(other.fFormat)
{
}
// archive constructor
IconProperty::IconProperty(BMessage* archive)
: Property(archive),
fMessage(new BMessage())
{
if (archive->FindMessage("message", fMessage) < B_OK) {
delete fMessage;
fMessage = NULL;
}
}
// destrucor
IconProperty::~IconProperty()
{
delete fMessage;
}
// Archive
status_t
IconProperty::Archive(BMessage* into, bool deep) const
{
status_t status = Property::Archive(into, deep);
if (status >= B_OK && fMessage)
status = into->AddMessage("message", fMessage);
// finish off
if (status >= B_OK)
status = into->AddString("class", "IconProperty");
return status;
}
// Instantiate
BArchivable*
IconProperty::Instantiate(BMessage* archive)
{
if (validate_instantiation(archive, "IconProperty"))
return new IconProperty(archive);
return NULL;
}
// #pragma mark -
// Clone
Property*
IconProperty::Clone() const
{
return new (nothrow) IconProperty(*this);
}
// SetValue
bool
IconProperty::SetValue(const char* str)
{
return false;
}
// SetValue
bool
IconProperty::SetValue(const Property* other)
{
const IconProperty* i = dynamic_cast<const IconProperty*>(other);
if (i) {
SetMessage(i->Message());
return true;
}
return false;
}
// GetValue
void
IconProperty::GetValue(BString& string)
{
string << "dummy";
}
// InterpolateTo
bool
IconProperty::InterpolateTo(const Property* other, float scale)
{
return false;
}
// #pragma mark -
// SetMessage
void
IconProperty::SetMessage(const BMessage* message)
{
if (message && fMessage) {
*fMessage = *message;
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef ICON_PROPERTY_H
#define ICON_PROPERTY_H
#include <GraphicsDefs.h>
#include "Property.h"
class IconProperty : public Property {
public:
IconProperty(uint32 identifier,
const uchar* icon,
uint32 width, uint32 height,
color_space format,
BMessage* message = NULL);
IconProperty(const IconProperty& other);
IconProperty(BMessage* archive);
virtual ~IconProperty();
// BArchivable interface
virtual status_t Archive(BMessage* archive, bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive);
// Property interface
virtual Property* Clone() const;
virtual type_code Type() const
{ return B_RGB_COLOR_TYPE; }
virtual bool SetValue(const char* value);
virtual bool SetValue(const Property* other);
virtual void GetValue(BString& string);
virtual bool InterpolateTo(const Property* other,
float scale);
// IconProperty
const BMessage* Message() const
{ return fMessage; }
void SetMessage(const BMessage* message);
const uchar* Icon() const { return fIcon; }
uint32 Width() const { return fWidth; }
uint32 Height() const { return fHeight; }
color_space Format() const { return fFormat; }
private:
BMessage* fMessage;
const uchar* fIcon;
uint32 fWidth;
uint32 fHeight;
color_space fFormat;
};
#endif // ICON_PROPERTY_H

View File

@ -0,0 +1,91 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "Int64Property.h"
#include <new>
#include <stdio.h>
#include <stdlib.h>
using std::nowthrow;
// constructor
Int64Property::Int64Property(uint32 identifier, int64 value)
: Property(identifier),
fValue(value)
{
}
// constructor
Int64Property::Int64Property(const Int64Property& other)
: Property(other),
fValue(other.fValue)
{
}
// destructor
Int64Property::~Int64Property()
{
}
// Clone
Property*
Int64Property::Clone() const
{
return new (nothrow) Int64Property(*this);
}
// SetValue
bool
Int64Property::SetValue(const char* value)
{
// TODO: atoll is defined for __INTEL__ only
return SetValue(atoll(value));
}
// SetValue
bool
Int64Property::SetValue(const Property* other)
{
const Int64Property* intOther = dynamic_cast<const Int64Property*>(other);
if (intOther) {
return SetValue(intOther->Value());
}
return false;
}
// GetValue
void
Int64Property::GetValue(BString& string)
{
string << fValue;
}
// InterpolateTo
bool
Int64Property::InterpolateTo(const Property* other, float scale)
{
const Int64Property* intOther = dynamic_cast<const Int64Property*>(other);
if (intOther) {
return SetValue(fValue + (int64)((double)(intOther->Value()
- fValue) * scale + 0.5));
}
return false;
}
// SetValue
bool
Int64Property::SetValue(int64 value)
{
if (value != fValue) {
fValue = value;
return true;
}
return false;
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef INT64_PROPERTY_H
#define INT64_PROPERTY_H
#include "Property.h"
class Int64Property : public Property {
public:
Int64Property(uint32 identifier,
int64 value = 0);
Int64Property(const Int64Property& other);
virtual ~Int64Property();
virtual Property* Clone() const;
virtual type_code Type() const
{ return B_INT64_TYPE; }
virtual bool SetValue(const char* value);
virtual bool SetValue(const Property* other);
virtual void GetValue(BString& string);
virtual bool InterpolateTo(const Property* other,
float scale);
// IntProperty
bool SetValue(int64 value);
inline int64 Value() const
{ return fValue; }
private:
int64 fValue;
};
#endif // PROPERTY_H

View File

@ -0,0 +1,260 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "OptionProperty.h"
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <ByteOrder.h>
#include <Message.h>
using std::nothrow;
// constructor
OptionProperty::OptionProperty(uint32 identifier)
: Property(identifier),
fOptions(4),
fCurrentOptionID(-1)
{
}
// copy constructor
OptionProperty::OptionProperty(const OptionProperty& other)
: Property(other),
fOptions(4),
fCurrentOptionID(other.fCurrentOptionID)
{
// clone the actual options
int32 count = other.fOptions.CountItems();
for (int32 i = 0; i < count; i++) {
option* o = (option*)(other.fOptions.ItemAtFast(i));
option* clone = new (nothrow) option;
if (!clone || !fOptions.AddItem(clone)) {
delete clone;
break;
}
clone->id = o->id;
clone->name = o->name;
}
}
// archive constructor
OptionProperty::OptionProperty(BMessage* archive)
: Property(archive),
fOptions(4),
fCurrentOptionID(-1)
{
if (archive) {
if (archive->FindInt32("option", &fCurrentOptionID) < B_OK)
fCurrentOptionID = -1;
}
}
// destrucor
OptionProperty::~OptionProperty()
{
int32 count = fOptions.CountItems();
for (int32 i = 0; i < count; i++)
delete (option*)fOptions.ItemAtFast(i);
}
// #pragma mark -
// Clone
Property*
OptionProperty::Clone() const
{
return new (nothrow) OptionProperty(*this);
}
// Type
type_code
OptionProperty::Type() const
{
// NOTE: not a Be defined type (those are upper case)
return 'optn';
}
// SetValue
bool
OptionProperty::SetValue(const char* value)
{
// try to find option by name
int32 count = fOptions.CountItems();
for (int32 i = 0; i < count; i++) {
option* o = (option*)fOptions.ItemAtFast(i);
if (strcmp(o->name.String(), value) == 0) {
return SetCurrentOptionID(o->id);
}
}
// try to find option by id
int32 id = atoi(value);
if (id < 0)
return false;
for (int32 i = 0; i < count; i++) {
option* o = (option*)fOptions.ItemAtFast(i);
if (o->id == id) {
return SetCurrentOptionID(o->id);
}
}
return false;
}
// SetValue
bool
OptionProperty::SetValue(const Property* other)
{
const OptionProperty* optOther = dynamic_cast<const OptionProperty*>(other);
if (optOther) {
return SetCurrentOptionID(optOther->CurrentOptionID());
}
return false;
}
// GetValue
void
OptionProperty::GetValue(BString& string)
{
if (!GetCurrentOption(&string))
string << fCurrentOptionID;
}
// MakeAnimatable
bool
OptionProperty::MakeAnimatable(bool animatable)
{
return false;
}
// #pragma mark -
// Archive
status_t
OptionProperty::Archive(BMessage* into, bool deep) const
{
status_t status = Property::Archive(into, deep);
if (status >= B_OK)
status = into->AddInt32("option", fCurrentOptionID);
// finish off
if (status >= B_OK)
status = into->AddString("class", "OptionProperty");
return status;
}
// Instantiate
BArchivable*
OptionProperty::Instantiate(BMessage* archive)
{
if (validate_instantiation(archive, "OptionProperty"))
return new (nothrow) OptionProperty(archive);
return NULL;
}
// #pragma mark -
// AddOption
void
OptionProperty::AddOption(int32 id, const char* name)
{
if (!name)
return;
if (option* o = new (nothrow) option) {
o->id = id;
o->name = name;
fOptions.AddItem((void*)o);
}
}
// CurrentOptionID
int32
OptionProperty::CurrentOptionID() const
{
return fCurrentOptionID;
}
// SetCurrentOptionID
bool
OptionProperty::SetCurrentOptionID(int32 id)
{
if (fCurrentOptionID != id) {
fCurrentOptionID = id;
return true;
}
return false;
}
// GetOption
bool
OptionProperty::GetOption(int32 index, BString* string, int32* id) const
{
if (option* o = (option*)fOptions.ItemAt(index)) {
*id = o->id;
*string = o->name;
return true;
} else {
*id = -1;
*string = "";
return false;
}
}
// GetCurrentOption
bool
OptionProperty::GetCurrentOption(BString* string) const
{
for (int32 i = 0; option* o = (option*)fOptions.ItemAt(i); i++) {
if (o->id == fCurrentOptionID) {
*string = o->name;
return true;
}
}
uint32 current = B_HOST_TO_BENDIAN_INT32(fCurrentOptionID);
printf("OptionProperty::GetCurrentOption() - "
"did not find option %.4s!!\n", (char*)&current);
return false;
}
// SetOptionAtOffset
bool
OptionProperty::SetOptionAtOffset(int32 indexOffset)
{
// NOTE: used by the Property editor GUI
if (fOptions.CountItems() > 1) {
int32 index = -1;
for (int32 i = 0; option* o = (option*)fOptions.ItemAt(i); i++) {
if (o->id == fCurrentOptionID) {
index = i;
}
}
if (index >= 0) {
// offset index
index += indexOffset;
// keep index in range by wrapping arround
if (index >= fOptions.CountItems())
index = 0;
if (index < 0)
index = fOptions.CountItems() - 1;
if (option* o = (option*)fOptions.ItemAt(index)) {
SetCurrentOptionID(o->id);
return true;
}
}
}
return false;
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef OPTION_PROPERTY_H
#define OPTION_PROPERTY_H
#include <List.h>
#include <String.h>
#include "Property.h"
class OptionProperty : public Property {
public:
OptionProperty(uint32 identifier);
OptionProperty(const OptionProperty& other);
OptionProperty(BMessage* archive);
virtual ~OptionProperty();
// Property interface
virtual Property* Clone() const;
virtual type_code Type() const;
virtual bool SetValue(const char* value);
virtual bool SetValue(const Property* other);
virtual void GetValue(BString& string);
// animation
virtual bool MakeAnimatable(bool animatable = true);
// BArchivable interface
virtual status_t Archive(BMessage* archive, bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive);
// OptionProperty
void AddOption(int32 id, const char* name);
int32 CurrentOptionID() const;
bool SetCurrentOptionID(int32 id);
bool GetOption(int32 index, BString* string, int32* id) const;
bool GetCurrentOption(BString* string) const;
bool SetOptionAtOffset(int32 indexOffset);
private:
struct option {
int32 id;
BString name;
};
BList fOptions;
int32 fCurrentOptionID;
};
#endif // OPTION_PROPERTY_H

View File

@ -0,0 +1,62 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "PropertyEditorFactory.h"
#include "ColorProperty.h"
#include "Property.h"
#include "IconProperty.h"
#include "Int64Property.h"
#include "OptionProperty.h"
#include "BoolValueView.h"
#include "ColorValueView.h"
#include "FloatValueView.h"
#include "IconValueView.h"
#include "IntValueView.h"
#include "Int64ValueView.h"
#include "OptionValueView.h"
#include "StringValueView.h"
PropertyEditorView*
EditorFor(Property* p)
{
if (!p)
return NULL;
if (IntProperty* i = dynamic_cast<IntProperty*>(p))
return new IntValueView(i);
if (FloatProperty* f = dynamic_cast<FloatProperty*>(p))
return new FloatValueView(f);
if (BoolProperty* b = dynamic_cast<BoolProperty*>(p))
return new BoolValueView(b);
if (StringProperty* s = dynamic_cast<StringProperty*>(p))
return new StringValueView(s);
if (Int64Property* i = dynamic_cast<Int64Property*>(p))
return new Int64ValueView(i);
if (OptionProperty* o = dynamic_cast<OptionProperty*>(p))
return new OptionValueView(o);
if (ColorProperty* c = dynamic_cast<ColorProperty*>(p))
return new ColorValueView(c);
if (IconProperty* i = dynamic_cast<IconProperty*>(p)) {
IconValueView* view = new IconValueView(i);
view->SetIcon(i->Icon(), i->Width(), i->Height(), i->Format());
return view;
}
return NULL;
}

View File

@ -0,0 +1,19 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef PROPERTY_EDITOR_FACTORY
#define PROPERTY_EDITOR_FACTORY
#include <SupportDefs.h>
class Property;
class PropertyEditorView;
PropertyEditorView* EditorFor(Property* property);
#endif // PROPERTY_EDITOR_FACTORY

View File

@ -0,0 +1,110 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "PropertyEditorView.h"
#include <stdio.h>
#include "Property.h"
#include "PropertyItemView.h"
// constructor
PropertyEditorView::PropertyEditorView(Property* property)
: BView(BRect(0.0, 0.0, 10.0, 10.0), "property item",
B_FOLLOW_LEFT | B_FOLLOW_TOP,
B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE),
fParent(NULL),
fProperty(property),
fSelected(false)
{
}
// destructor
PropertyEditorView::~PropertyEditorView()
{
}
// Draw
void
PropertyEditorView::Draw(BRect updateRect)
{
// just draw background
FillRect(Bounds(), B_SOLID_LOW);
}
// MouseDown
void
PropertyEditorView::MouseDown(BPoint where)
{
if (fParent) {
// forward click
fParent->MouseDown(ConvertToParent(where));
}
}
// MouseUp
void
PropertyEditorView::MouseUp(BPoint where)
{
if (fParent) {
// forward click
fParent->MouseUp(ConvertToParent(where));
}
}
// MouseMoved
void
PropertyEditorView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
{
if (fParent) {
// forward click
fParent->MouseMoved(ConvertToParent(where), transit, dragMessage);
}
}
// PreferredHeight
float
PropertyEditorView::PreferredHeight() const
{
font_height fh;
GetFontHeight(&fh);
float height = floorf(4.0 + fh.ascent + fh.descent);
return height;
}
// SetSelected
void
PropertyEditorView::SetSelected(bool selected)
{
fSelected = selected;
}
// SetItemView
void
PropertyEditorView::SetItemView(PropertyItemView* parent)
{
fParent = parent;
if (fParent) {
BFont font;
fParent->GetFont(&font);
SetFont(&font);
SetLowColor(fParent->LowColor());
}
}
// ValueChanged
void
PropertyEditorView::ValueChanged()
{
if (fParent)
fParent->UpdateObject();
}

View File

@ -0,0 +1,61 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef PROPERTY_EDITOR_VIEW_H
#define PROPERTY_EDITOR_VIEW_H
#include <View.h>
class Property;
class PropertyItemView;
class PropertyEditorView : public BView {
public:
PropertyEditorView(Property* property);
virtual ~PropertyEditorView();
// BView
virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint where);
virtual void MouseUp(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
// PropertyEditorView
virtual float PreferredHeight() const;
Property* GetProperty() const
{ return fProperty; }
void SetSelected(bool selected);
bool IsSelected() const
{ return fSelected; }
virtual void SetEnabled(bool enabled) = 0;
virtual bool IsFocused() const
{ return IsFocus(); }
void SetItemView(PropertyItemView* parent);
// used to trigger an update on the
// represented object
virtual void ValueChanged();
virtual bool AdoptProperty(Property* property) = 0;
protected:
PropertyItemView* fParent;
private:
Property* fProperty;
bool fSelected;
};
#endif // PROPERTY_EDITOR_VIEW_H

View File

@ -0,0 +1,256 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "PropertyItemView.h"
#include <stdio.h>
#include <Message.h>
#include <Window.h>
#include "support_ui.h"
#include "ui_defines.h"
#include "CommonPropertyIDs.h"
#include "Property.h"
#include "PropertyEditorFactory.h"
#include "PropertyEditorView.h"
#include "PropertyListView.h"
// constructor
PropertyItemView::PropertyItemView(Property* property)
: BView(BRect(0.0, 0.0, 10.0, 10.0), "property item",
B_FOLLOW_LEFT | B_FOLLOW_TOP,
B_NAVIGABLE | B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE),
fParent(NULL),
fEditorView(/*factory->*/EditorFor(property)),
// NOTE: can be NULL if property is NULL or unkown
fSelected(false),
fEnabled(true),
fLabelWidth(0.0)
{
if (fEditorView) {
AddChild(fEditorView);
fEditorView->SetItemView(this);
}
}
// destructor
PropertyItemView::~PropertyItemView()
{
}
// Draw
void
PropertyItemView::Draw(BRect updateRect)
{
const Property* property = GetProperty();
if (property && fParent) {
BRect b(Bounds());
// just draw background and label
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);
BFont font;
GetFont(&font);
BString truncated(name_for_id(property->Identifier()));
font.TruncateString(&truncated, B_TRUNCATE_MIDDLE, fLabelWidth - 10.0);
font_height fh;
font.GetHeight(&fh);
FillRect(BRect(b.left, b.top, b.left + fLabelWidth, b.bottom), B_SOLID_LOW);
DrawString(truncated.String(), BPoint(b.left + 5.0,
floorf(b.top + b.Height() / 2.0
+ fh.ascent / 2.0)));
// draw a "separator" line behind the label
SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT));
StrokeLine(BPoint(b.left + fLabelWidth - 1.0, b.top),
BPoint(b.left + fLabelWidth - 1.0, b.bottom), B_SOLID_HIGH);
}
}
// FrameResized
void
PropertyItemView::FrameResized(float width, float height)
{
if (fEditorView) {
fEditorView->MoveTo(fLabelWidth, 0.0);
fEditorView->ResizeTo(width - fLabelWidth, height);
fEditorView->FrameResized(fEditorView->Bounds().Width(),
fEditorView->Bounds().Height());
}
}
// MakeFocus
void
PropertyItemView::MakeFocus(bool focused)
{
if (fEditorView)
fEditorView->MakeFocus(focused);
}
// MouseDown
void
PropertyItemView::MouseDown(BPoint where)
{
if (fParent) {
// select ourself
fParent->Select(this);
if (fEditorView)
fEditorView->MakeFocus(true);
if (BMessage* message = Window()->CurrentMessage()) {
int32 clicks;
if (message->FindInt32("clicks", &clicks) >= B_OK)
if (clicks >= 2)
fParent->DoubleClicked(this);
else
fParent->Clicked(this);
}
}
}
// MouseUp
void
PropertyItemView::MouseUp(BPoint where)
{
}
// MouseMoved
void
PropertyItemView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
{
}
// PreferredHeight
float
PropertyItemView::PreferredHeight() const
{
font_height fh;
GetFontHeight(&fh);
float height = floorf(4.0 + fh.ascent + fh.descent);
if (fEditorView)
height = max_c(height, fEditorView->PreferredHeight());
return height;
}
// PreferredLabelWidth
float
PropertyItemView::PreferredLabelWidth() const
{
float width = 0.0;
if (const Property* property = GetProperty())
width = ceilf(StringWidth(name_for_id(property->Identifier())) + 10.0);
return width;
}
// SetLabelWidth
void
PropertyItemView::SetLabelWidth(float width)
{
if (width < 0.0)
width = 0.0;
/* if (fEditorView && width > Bounds().Width() - fEditorView->Bounds().Width())
width = Bounds().Width() - fEditorView->Bounds().Width();
else if (width > Bounds().Width())
width = Bounds().Width();*/
fLabelWidth = width;
}
// SetSelected
void
PropertyItemView::SetSelected(bool selected)
{
fSelected = selected;
_UpdateLowColor();
}
// SetEnabled
void
PropertyItemView::SetEnabled(bool enabled)
{
if (fEnabled != enabled) {
fEnabled = enabled;
fEditorView->SetEnabled(fEnabled);
}
}
// IsFocused
bool
PropertyItemView::IsFocused() const
{
if (fEditorView)
return fEditorView->IsFocused();
return false;
}
// GetProperty
Property*
PropertyItemView::GetProperty() const
{
if (fEditorView)
return fEditorView->GetProperty();
return NULL;
}
// SetProperty
bool
PropertyItemView::AdoptProperty(Property* property)
{
if (fEditorView && fEditorView->AdoptProperty(property)) {
_UpdateLowColor();
return true;
}
return false;
}
// SetListView
void
PropertyItemView::SetListView(PropertyListView* parent)
{
fParent = parent;
_UpdateLowColor();
}
// UpdateObject
void
PropertyItemView::UpdateObject()
{
if (fParent && fEditorView) {
if (const Property* p = fEditorView->GetProperty())
fParent->UpdateObject(p->Identifier());
}
}
// #pragma mark -
// _UpdateLowColor
void
PropertyItemView::_UpdateLowColor()
{
rgb_color lowColor = fParent ? fParent->LowColor() : kWhite;
if (fSelected)
lowColor = tint_color(lowColor, B_DARKEN_2_TINT);
if (lowColor != LowColor()) {
SetLowColor(lowColor);
Invalidate();
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef PROPERTY_ITEM_VIEW_H
#define PROPERTY_ITEM_VIEW_H
#include <View.h>
class Property;
class PropertyEditorView;
class PropertyListView;
class PropertyItemView : public BView {
public:
PropertyItemView(Property* property);
virtual ~PropertyItemView();
// BView interface
virtual void Draw(BRect updateRect);
virtual void FrameResized(float width, float height);
virtual void MakeFocus(bool focused);
virtual void MouseDown(BPoint where);
virtual void MouseUp(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
// PropertyItemView
float PreferredHeight() const;
float PreferredLabelWidth() const;
void SetLabelWidth(float width);
Property* GetProperty() const;
bool AdoptProperty(Property* property);
void SetSelected(bool selected);
bool IsSelected() const
{ return fSelected; }
void SetEnabled(bool enabled);
bool IsEnabled() const
{ return fEnabled; }
virtual bool IsFocused() const;
void SetListView(PropertyListView* parent);
virtual void UpdateObject();
private:
void _UpdateLowColor();
PropertyListView* fParent;
PropertyEditorView* fEditorView;
bool fSelected;
bool fEnabled;
float fLabelWidth;
};
#endif // PROPERTY_ITEM_VIEW_H

View File

@ -0,0 +1,655 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "PropertyListView.h"
#include <stdio.h>
#include <string.h>
#include <ClassInfo.h>
#include <Clipboard.h>
#include <Menu.h>
#include <MenuItem.h>
#include <Message.h>
#include <Window.h>
#include "CommonPropertyIDs.h"
//#include "LanguageManager.h"
#include "Property.h"
#include "PropertyItemView.h"
#include "PropertyObject.h"
#include "Scrollable.h"
#include "Scroller.h"
#include "ScrollView.h"
enum {
MSG_COPY_PROPERTIES = 'cppr',
MSG_PASTE_PROPERTIES = 'pspr',
MSG_ADD_KEYFRAME = 'adkf',
MSG_SELECT_ALL = B_SELECT_ALL,
MSG_SELECT_NONE = 'slnn',
MSG_INVERT_SELECTION = 'invs',
};
// TabFilter class
class TabFilter : public BMessageFilter {
public:
TabFilter(PropertyListView* target)
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
fTarget(target)
{
}
virtual ~TabFilter()
{
}
virtual filter_result Filter(BMessage* message, BHandler** target)
{
filter_result result = B_DISPATCH_MESSAGE;
switch (message->what) {
case B_UNMAPPED_KEY_DOWN:
case B_KEY_DOWN: {
uint32 key;
uint32 modifiers;
if (message->FindInt32("raw_char", (int32*)&key) >= B_OK
&& message->FindInt32("modifiers", (int32*)&modifiers) >= B_OK)
if (key == B_TAB && fTarget->TabFocus(modifiers & B_SHIFT_KEY))
result = B_SKIP_MESSAGE;
break;
}
default:
break;
}
return result;
}
private:
PropertyListView* fTarget;
};
// constructor
PropertyListView::PropertyListView()
: BView(BRect(0.0, 0.0, 100.0, 100.0), NULL, B_FOLLOW_NONE,
B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE),
Scrollable(),
BList(20),
fClipboard(new BClipboard("icon-o-matic properties")),
fPropertyM(NULL),
fPropertyObject(NULL),
fLastClickedItem(NULL),
fSuspendUpdates(false),
fMouseWheelFilter(new MouseWheelFilter(this)),
fTabFilter(new TabFilter(this))
{
SetLowColor(255, 255, 255, 255);
SetHighColor(0, 0, 0, 255);
SetViewColor(B_TRANSPARENT_32_BIT);
}
// destructor
PropertyListView::~PropertyListView()
{
delete fClipboard;
delete fPropertyObject;
delete fMouseWheelFilter;
delete fTabFilter;
}
// AttachedToWindow
void
PropertyListView::AttachedToWindow()
{
Window()->AddCommonFilter(fMouseWheelFilter);
Window()->AddCommonFilter(fTabFilter);
}
// DetachedFromWindow
void
PropertyListView::DetachedFromWindow()
{
Window()->RemoveCommonFilter(fTabFilter);
Window()->RemoveCommonFilter(fMouseWheelFilter);
}
// FrameResized
void
PropertyListView::FrameResized(float width, float height)
{
SetVisibleSize(width, height);
}
// Draw
void
PropertyListView::Draw(BRect updateRect)
{
if (!fSuspendUpdates)
FillRect(updateRect, B_SOLID_LOW);
}
// MakeFocus
void
PropertyListView::MakeFocus(bool focus)
{
if (focus == IsFocus())
return;
BView::MakeFocus(focus);
if (::ScrollView* scrollView = dynamic_cast< ::ScrollView*>(Parent()))
scrollView->ChildFocusChanged(focus);
}
// MouseDown
void
PropertyListView::MouseDown(BPoint where)
{
if (!(modifiers() & B_SHIFT_KEY)) {
DeselectAll();
}
MakeFocus(true);
}
// MessageReceived
void
PropertyListView::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_PASTE_PROPERTIES: {
if (!fPropertyObject || !fClipboard->Lock())
break;
BMessage* data = fClipboard->Data();
if (!data) {
fClipboard->Unlock();
break;
}
PropertyObject propertyObject;
BMessage archive;
for (int32 i = 0;
data->FindMessage("property", i, &archive) >= B_OK;
i++) {
BArchivable* archivable = instantiate_object(&archive);
if (!archivable)
continue;
// see if this is actually a property
Property* property = cast_as(archivable, Property);
if (!property || !propertyObject.AddProperty(property))
delete archivable;
}
if (propertyObject.CountProperties() > 0)
PasteProperties(&propertyObject);
fClipboard->Unlock();
break;
}
case MSG_COPY_PROPERTIES: {
if (!fPropertyObject || !fClipboard->Lock())
break;
BMessage* data = fClipboard->Data();
if (!data) {
fClipboard->Unlock();
break;
}
fClipboard->Clear();
for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) {
if (!item->IsSelected())
continue;
const Property* property = item->GetProperty();
if (property) {
BMessage archive;
if (property->Archive(&archive) >= B_OK) {
data->AddMessage("property", &archive);
}
}
}
fClipboard->Commit();
fClipboard->Unlock();
_CheckMenuStatus();
break;
}
// property selection
case MSG_SELECT_ALL:
for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) {
item->SetSelected(true);
}
_CheckMenuStatus();
break;
case MSG_SELECT_NONE:
for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) {
item->SetSelected(false);
}
_CheckMenuStatus();
break;
case MSG_INVERT_SELECTION:
for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) {
item->SetSelected(!item->IsSelected());
}
_CheckMenuStatus();
break;
default:
BView::MessageReceived(message);
}
}
// #pragma mark -
// TabFocus
bool
PropertyListView::TabFocus(bool shift)
{
bool result = false;
PropertyItemView* item = NULL;
if (IsFocus() && !shift) {
item = _ItemAt(0);
} else {
int32 focussedIndex = -1;
for (int32 i = 0; PropertyItemView* oldItem = _ItemAt(i); i++) {
if (oldItem->IsFocused()) {
focussedIndex = shift ? i - 1 : i + 1;
break;
}
}
item = _ItemAt(focussedIndex);
}
if (item) {
item->MakeFocus(true);
result = true;
}
return result;
}
// SetMenu
void
PropertyListView::SetMenu(BMenu* menu)
{
fPropertyM = menu;
if (!fPropertyM)
return;
fSelectM = new BMenu("Select");
fSelectAllMI = new BMenuItem("All", new BMessage(MSG_SELECT_ALL));
fSelectM->AddItem(fSelectAllMI);
fSelectNoneMI = new BMenuItem("None", new BMessage(MSG_SELECT_NONE));
fSelectM->AddItem(fSelectNoneMI);
fInvertSelectionMI = new BMenuItem("Invert Selection", new BMessage(MSG_INVERT_SELECTION));
fSelectM->AddItem(fInvertSelectionMI);
fSelectM->SetTargetForItems(this);
fPropertyM->AddItem(fSelectM);
fPropertyM->AddSeparatorItem();
fCopyMI = new BMenuItem("Copy", new BMessage(MSG_COPY_PROPERTIES));
fPropertyM->AddItem(fCopyMI);
fPasteMI = new BMenuItem("Paste", new BMessage(MSG_PASTE_PROPERTIES));
fPropertyM->AddItem(fPasteMI);
fPropertyM->SetTargetForItems(this);
// disable menus
_CheckMenuStatus();
}
// UpdateStrings
void
PropertyListView::UpdateStrings()
{
// if (fSelectM) {
// LanguageManager* m = LanguageManager::Default();
//
// fSelectM->Superitem()->SetLabel(m->GetString(PROPERTY_SELECTION, "Select"));
// fSelectAllMI->SetLabel(m->GetString(SELECT_ALL_PROPERTIES, "All"));
// fSelectNoneMI->SetLabel(m->GetString(SELECT_NO_PROPERTIES, "None"));
// fInvertSelectionMI->SetLabel(m->GetString(INVERT_SELECTION, "Invert Selection"));
//
// fPropertyM->Superitem()->SetLabel(m->GetString(PROPERTY, "Property"));
// fCopyMI->SetLabel(m->GetString(COPY, "Copy"));
// if (IsEditingMultipleObjects())
// fPasteMI->SetLabel(m->GetString(MULTI_PASTE, "Multi Paste"));
// else
// fPasteMI->SetLabel(m->GetString(PASTE, "Paste"));
// }
}
// ScrollView
::ScrollView*
PropertyListView::ScrollView() const
{
return dynamic_cast< ::ScrollView*>(ScrollSource());
}
// #pragma mark -
// SetTo
void
PropertyListView::SetTo(PropertyObject* object)
{
// try to do without rebuilding the list
// it should in fact be pretty unlikely that this does not
// work, but we keep being defensive
if (fPropertyObject && object &&
fPropertyObject->ContainsSameProperties(*object)) {
// iterate over view items and update their value views
for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) {
Property* property = object->PropertyAt(i);
if (!item->AdoptProperty(property)) {
// the reason for this can be that the property is
// unkown to the PropertyEditorFactory and therefor
// there is no editor view at this item
fprintf(stderr, "PropertyListView::_SetTo() - "
"property mismatch at %ld\n", i);
break;
}
if (property)
item->SetEnabled(property->IsEditable());
}
// we didn't take on ownership, but kept our old object
delete object;
} else {
// remember scroll pos, selection and focused item
BPoint scrollOffset = ScrollOffset();
BList selection(20);
int32 focused = -1;
for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) {
if (item->IsSelected())
selection.AddItem((void*)i);
if (item->IsFocused())
focused = i;
}
if (Window())
Window()->BeginViewTransaction();
fSuspendUpdates = true;
// rebuild list
_MakeEmpty();
fPropertyObject = object;
if (fPropertyObject) {
// fill with content
for (int32 i = 0; Property* property = fPropertyObject->PropertyAt(i); i++) {
PropertyItemView* item = new PropertyItemView(property);
item->SetEnabled(property->IsEditable());
_AddItem(item);
}
_LayoutItems();
// restore scroll pos, selection and focus
SetScrollOffset(scrollOffset);
for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) {
if (selection.HasItem((void*)i))
item->SetSelected(true);
if (i == focused)
item->MakeFocus(true);
}
}
if (Window())
Window()->EndViewTransaction();
fSuspendUpdates = false;
SetDataRect(_ItemsRect());
}
_CheckMenuStatus();
}
// UpdateObject
void
PropertyListView::UpdateObject(uint32 propertyID)
{
printf("PropertyListView::UpdateObject(%s)\n", name_for_id(propertyID));
}
// PasteProperties
void
PropertyListView::PasteProperties(const PropertyObject* object)
{
if (!fPropertyObject)
return;
// default implementation is to adopt the pasted properties
int32 count = object->CountProperties();
for (int32 i = 0; i < count; i++) {
Property* p = object->PropertyAtFast(i);
Property* local = fPropertyObject->FindProperty(p->Identifier());
if (local)
local->SetValue(p);
}
}
// IsEditingMultipleObjects
bool
PropertyListView::IsEditingMultipleObjects()
{
return false;
}
// #pragma mark -
// ScrollOffsetChanged
void
PropertyListView::ScrollOffsetChanged(BPoint oldOffset, BPoint newOffset)
{
ScrollBy(newOffset.x - oldOffset.x,
newOffset.y - oldOffset.y);
}
// Select
void
PropertyListView::Select(PropertyItemView* item)
{
if (item) {
if (modifiers() & B_SHIFT_KEY) {
item->SetSelected(!item->IsSelected());
} else if (modifiers() & B_OPTION_KEY) {
item->SetSelected(true);
int32 firstSelected = _CountItems();
int32 lastSelected = -1;
for (int32 i = 0; PropertyItemView* otherItem = _ItemAt(i); i++) {
if (otherItem->IsSelected()) {
if (i < firstSelected)
firstSelected = i;
if (i > lastSelected)
lastSelected = i;
}
}
if (lastSelected > firstSelected) {
for (int32 i = firstSelected; PropertyItemView* otherItem = _ItemAt(i); i++) {
if (i > lastSelected)
break;
otherItem->SetSelected(true);
}
}
} else {
for (int32 i = 0; PropertyItemView* otherItem = _ItemAt(i); i++) {
otherItem->SetSelected(otherItem == item);
}
}
}
_CheckMenuStatus();
}
// DeselectAll
void
PropertyListView::DeselectAll()
{
for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) {
item->SetSelected(false);
}
_CheckMenuStatus();
}
// Clicked
void
PropertyListView::Clicked(PropertyItemView* item)
{
fLastClickedItem = item;
}
// DoubleClicked
void
PropertyListView::DoubleClicked(PropertyItemView* item)
{
if (fLastClickedItem == item) {
printf("implement PropertyListView::DoubleClicked()\n");
// ...->EditObject(item->GetProperty());
}
fLastClickedItem = NULL;
}
// #pragma mark -
// _AddItem
bool
PropertyListView::_AddItem(PropertyItemView* item)
{
if (item && BList::AddItem((void*)item)) {
// AddChild(item);
// NOTE: for now added in _LayoutItems()
item->SetListView(this);
return true;
}
return false;
}
// _RemoveItem
PropertyItemView*
PropertyListView::_RemoveItem(int32 index)
{
PropertyItemView* item = (PropertyItemView*)BList::RemoveItem(index);
if (item) {
item->SetListView(NULL);
if (!RemoveChild(item))
fprintf(stderr, "failed to remove view in PropertyListView::_RemoveItem()\n");
}
return item;
}
// _ItemAt
PropertyItemView*
PropertyListView::_ItemAt(int32 index) const
{
return (PropertyItemView*)BList::ItemAt(index);
}
// _CountItems
int32
PropertyListView::_CountItems() const
{
return BList::CountItems();
}
// _MakeEmpty
void
PropertyListView::_MakeEmpty()
{
int32 count = _CountItems();
while (PropertyItemView* item = _RemoveItem(count - 1)) {
delete item;
count--;
}
delete fPropertyObject;
fPropertyObject = NULL;
SetScrollOffset(BPoint(0.0, 0.0));
}
// _ItemsRect
BRect
PropertyListView::_ItemsRect() const
{
float width = Bounds().Width();
float height = -1.0;
for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) {
height += item->PreferredHeight() + 1.0;
}
if (height < 0.0)
height = 0.0;
return BRect(0.0, 0.0, width, height);
}
// _LayoutItems
void
PropertyListView::_LayoutItems()
{
// figure out maximum label width
float labelWidth = Bounds().Width() * 0.5;
for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) {
if (item->PreferredLabelWidth() > labelWidth)
labelWidth = item->PreferredLabelWidth();
}
labelWidth = ceilf(labelWidth);
// layout items
float top = 0.0;
float width = Bounds().Width();
for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) {
item->MoveTo(BPoint(0.0, top));
float height = item->PreferredHeight();
item->SetLabelWidth(labelWidth);
item->ResizeTo(width, height);
item->FrameResized(item->Bounds().Width(),
item->Bounds().Height());
top += height + 1.0;
AddChild(item);
}
}
// _CheckMenuStatus
void
PropertyListView::_CheckMenuStatus()
{
if (!fPropertyM || !fSuspendUpdates)
return;
bool gotSelection = false;
for (int32 i = 0; PropertyItemView* item = _ItemAt(i); i++) {
if (item->IsSelected()) {
gotSelection = true;
break;
}
}
fCopyMI->SetEnabled(gotSelection);
bool clipboardHasData = false;
if (fClipboard->Lock()) {
if (BMessage* data = fClipboard->Data()) {
clipboardHasData = data->HasMessage("property");
}
fClipboard->Unlock();
}
fPasteMI->SetEnabled(clipboardHasData);
// LanguageManager* m = LanguageManager::Default();
if (IsEditingMultipleObjects())
// fPasteMI->SetLabel(m->GetString(MULTI_PASTE, "Multi Paste"));
fPasteMI->SetLabel("Multi Paste");
else
// fPasteMI->SetLabel(m->GetString(PASTE, "Paste"));
fPasteMI->SetLabel("Paste");
bool enableMenu = fPropertyObject;
if (fPropertyM->IsEnabled() != enableMenu)
fPropertyM->SetEnabled(enableMenu);
bool gotItems = _CountItems() > 0;
fSelectM->SetEnabled(gotItems);
}

View File

@ -0,0 +1,108 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef PROPERTY_LIST_VIEW_H
#define PROPERTY_LIST_VIEW_H
#include <List.h>
#include <View.h>
#include "MouseWheelFilter.h"
#include "Scrollable.h"
class BClipboard;
class BMenu;
class BMenuItem;
class CommandStack;
class Property;
class PropertyItemView;
class PropertyObject;
class ScrollView;
class TabFilter;
class PropertyListView : public BView,
public Scrollable,
private BList,
public MouseWheelTarget {
public:
PropertyListView();
virtual ~PropertyListView();
// BView interface
virtual void AttachedToWindow();
virtual void DetachedFromWindow();
virtual void FrameResized(float width, float height);
virtual void Draw(BRect updateRect);
virtual void MakeFocus(bool focus);
virtual void MouseDown(BPoint where);
virtual void MessageReceived(BMessage* message);
// Scrollable interface
virtual void ScrollOffsetChanged(BPoint oldOffset,
BPoint newOffset);
// MouseWheelTarget interface
virtual bool MouseWheelChanged(float x, float y) { return false; }
// PropertyListView
void SetTo(PropertyObject* object);
// takes ownership of the object
virtual void UpdateObject(uint32 propertyID);
// implement to know when a property changed
virtual void PasteProperties(const PropertyObject* object);
// implement to know when a property changed
virtual bool IsEditingMultipleObjects();
void SetMenu(BMenu* menu);
::ScrollView* ScrollView() const;
void UpdateStrings();
// interface for Property framework
bool TabFocus(bool shift);
void Select(PropertyItemView* item);
void DeselectAll();
void Clicked(PropertyItemView* item);
void DoubleClicked(PropertyItemView* item);
private:
bool _AddItem(PropertyItemView* item);
PropertyItemView* _RemoveItem(int32 index);
PropertyItemView* _ItemAt(int32 index) const;
int32 _CountItems() const;
void _MakeEmpty();
BRect _ItemsRect() const;
void _LayoutItems();
void _CheckMenuStatus();
BClipboard* fClipboard;
BMenu* fSelectM;
BMenuItem* fSelectAllMI;
BMenuItem* fSelectNoneMI;
BMenuItem* fInvertSelectionMI;
BMenu* fPropertyM;
BMenuItem* fCopyMI;
BMenuItem* fPasteMI;
PropertyObject* fPropertyObject;
PropertyItemView* fLastClickedItem;
bool fSuspendUpdates;
MouseWheelFilter* fMouseWheelFilter;
TabFilter* fTabFilter;
};
#endif // PROPERTY_LIST_VIEW_H

View File

@ -0,0 +1,164 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "BoolValueView.h"
#include <stdio.h>
#include "Property.h"
#include "ui_defines.h"
// constructor
BoolValueView::BoolValueView(BoolProperty* property)
: PropertyEditorView(property),
fProperty(property),
fCheckBoxRect(0.0, 0.0, -1.0, -1.0),
fEnabled(true)
{
}
// destructor
BoolValueView::~BoolValueView()
{
}
// Draw
void
BoolValueView::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);
}
// background
FillRect(b, B_SOLID_LOW);
// checkmark box
rgb_color crossOutline = kBlack;
rgb_color crossColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
if (!fEnabled) {
crossOutline = tint_color(crossOutline, B_LIGHTEN_2_TINT);
crossColor = tint_color(crossColor, B_LIGHTEN_2_TINT);
}
SetHighColor(crossOutline);
b = fCheckBoxRect;
StrokeRect(b);
// checkmark
if (fProperty && fProperty->Value()) {
SetHighColor(crossColor);
b.InsetBy(3.0, 3.0);
SetPenSize(2.0);
StrokeLine(b.LeftTop(), b.RightBottom());
StrokeLine(b.LeftBottom(), b.RightTop());
}
}
// FrameResized
void
BoolValueView::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
BoolValueView::MakeFocus(bool focused)
{
PropertyEditorView::MakeFocus(focused);
Invalidate();
}
// MouseDown
void
BoolValueView::MouseDown(BPoint where)
{
MakeFocus(true);
if (fCheckBoxRect.Contains(where)) {
_ToggleValue();
}
// NOTE: careful, when this function returns, the object might
// in fact have been deleted
}
// KeyDown
void
BoolValueView::KeyDown(const char* bytes, int32 numBytes)
{
bool handled = true;
if (numBytes > 0) {
switch (bytes[0]) {
case B_RETURN:
case B_SPACE:
case B_UP_ARROW:
case B_DOWN_ARROW:
case B_LEFT_ARROW:
case B_RIGHT_ARROW:
_ToggleValue();
break;
default:
handled = false;
break;
}
}
if (!handled)
PropertyEditorView::KeyDown(bytes, numBytes);
}
// _ToggleValue
void
BoolValueView::_ToggleValue()
{
if (!fEnabled)
return;
if (fProperty) {
fProperty->SetValue(!fProperty->Value());
BRect b(fCheckBoxRect);
b.InsetBy(1.0, 1.0);
Invalidate(b);
ValueChanged();
}
}
// SetEnabled
void
BoolValueView::SetEnabled(bool enabled)
{
if (fEnabled != enabled) {
fEnabled = enabled;
Invalidate();
}
}
// SetToProperty
bool
BoolValueView::AdoptProperty(Property* property)
{
BoolProperty* p = dynamic_cast<BoolProperty*>(property);
if (p) {
BRect b(fCheckBoxRect);
b.InsetBy(1.0, 1.0);
Invalidate(b);
fProperty = p;
return true;
}
return false;
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef BOOL_VALUE_VIEW_H
#define BOOL_VALUE_VIEW_H
#include "PropertyEditorView.h"
class BoolProperty;
class BoolValueView : public PropertyEditorView {
public:
BoolValueView(BoolProperty* property);
virtual ~BoolValueView();
// BView interface
virtual void Draw(BRect updateRect);
virtual void FrameResized(float width, float height);
virtual void MakeFocus(bool focused);
virtual void MouseDown(BPoint where);
virtual void KeyDown(const char* bytes, int32 numBytes);
// PropertyEditorView interface
virtual void SetEnabled(bool enabled);
virtual bool AdoptProperty(Property* property);
private:
void _ToggleValue();
BoolProperty* fProperty;
BRect fCheckBoxRect;
bool fEnabled;
};
#endif // BOOL_VALUE_VIEW_H

View File

@ -0,0 +1,136 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "ColorValueView.h"
#include <stdio.h>
#include <Message.h>
#include <String.h>
#include <Window.h>
#include "support_ui.h"
#include "ColorProperty.h"
#include "PropertyItemView.h"
#include "SwatchValueView.h"
enum {
MSG_VALUE_CHANGED = 'vchd',
};
// constructor
ColorValueView::ColorValueView(ColorProperty* property)
: PropertyEditorView(property),
fProperty(property)
{
fSwatchView = new SwatchValueView("swatch property view",
NULL, this,/*new BMessage(MSG_SET_COLOR), this,*/
fProperty->Value());
fSwatchView->SetDroppedMessage(new BMessage(MSG_VALUE_CHANGED));
AddChild(fSwatchView);
}
// destructor
ColorValueView::~ColorValueView()
{
}
// Draw
void
ColorValueView::Draw(BRect updateRect)
{
BRect b(Bounds());
if (fSwatchView->IsFocus()) {
SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
StrokeRect(b);
b.InsetBy(1.0, 1.0);
updateRect = updateRect & b;
}
FillRect(b, B_SOLID_LOW);
}
// FrameResized
void
ColorValueView::FrameResized(float width, float height)
{
BRect b(Bounds());
b.InsetBy(2.0, 2.0);
b.left = floorf(b.left + (b.Width() / 2.0) - b.Height() / 2.0);
b.right = b.left + b.Height();
fSwatchView->MoveTo(b.LeftTop());
fSwatchView->ResizeTo(b.Width(), b.Height());
}
// MakeFocus
void
ColorValueView::MakeFocus(bool focused)
{
fSwatchView->MakeFocus(focused);
}
// MessageReceived
void
ColorValueView::MessageReceived(BMessage* message)
{
switch (message->what) {
case B_PASTE:
fSwatchView->MessageReceived(message);
break;
// case MSG_SET_COLOR:
// if (BWindow* window = Window())
// window->PostMessage(message, window);
// break;
case MSG_VALUE_CHANGED: {
rgb_color c;
if (restore_color_from_message(message, c) >= B_OK
&& fProperty->SetValue(c)) {
ValueChanged();
}
break;
}
default:
PropertyEditorView::MessageReceived(message);
}
}
// SetEnabled
void
ColorValueView::SetEnabled(bool enabled)
{
// if (fEnabled != enabled) {
// fEnabled = enabled;
// Invalidate();
// }
}
// IsFocused
bool
ColorValueView::IsFocused() const
{
return fSwatchView->IsFocus();
}
// SetToProperty
bool
ColorValueView::AdoptProperty(Property* property)
{
ColorProperty* p = dynamic_cast<ColorProperty*>(property);
if (p) {
rgb_color ownColor = fProperty->Value();
rgb_color color = p->Value();
if (ownColor != color) {
fSwatchView->SetColor(color);
}
fProperty = p;
return true;
}
return false;
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef COLOR_VALUE_VIEW_H
#define COLOR_VALUE_VIEW_H
#include "PropertyEditorView.h"
class ColorProperty;
class SwatchValueView;
class ColorValueView : public PropertyEditorView {
public:
ColorValueView(ColorProperty* property);
virtual ~ColorValueView();
// BView interface
virtual void Draw(BRect updateRect);
virtual void FrameResized(float width, float height);
virtual void MakeFocus(bool focused);
virtual void MessageReceived(BMessage* message);
// PropertyEditorView interface
virtual void SetEnabled(bool enabled);
virtual bool IsFocused() const;
virtual bool AdoptProperty(Property* property);
protected:
ColorProperty* fProperty;
SwatchValueView* fSwatchView;
};
#endif // COLOR_VALUE_VIEW_H

View File

@ -0,0 +1,68 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "FloatValueView.h"
#include <stdio.h>
#include "Property.h"
#include "NummericalTextView.h"
// constructor
FloatValueView::FloatValueView(FloatProperty* property)
: TextInputValueView(property),
fProperty(property)
{
BRect b = Bounds();
fTextView = new NummericalTextView(b, "nummerical input", b,
B_FOLLOW_LEFT | B_FOLLOW_TOP,
B_WILL_DRAW);
AddChild(fTextView);
fTextView->SetFloatMode(true);
if (fProperty)
fTextView->SetValue(fProperty->Value());
}
// destructor
FloatValueView::~FloatValueView()
{
}
// TextView
InputTextView*
FloatValueView::TextView() const
{
return fTextView;
}
// ValueChanged
void
FloatValueView::ValueChanged()
{
if (fProperty) {
fProperty->SetValue(fTextView->FloatValue());
fTextView->SetValue(fProperty->Value());
TextInputValueView::ValueChanged();
}
}
// AdoptProperty
bool
FloatValueView::AdoptProperty(Property* property)
{
FloatProperty* p = dynamic_cast<FloatProperty*>(property);
if (p) {
if (fTextView->FloatValue() != p->Value())
fTextView->SetValue(p->Value());
fProperty = p;
return true;
}
return false;
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef FLOAT_VALUE_VIEW_H
#define FLOAT_VALUE_VIEW_H
#include "TextInputValueView.h"
class FloatProperty;
class NummericalTextView;
class FloatValueView : public TextInputValueView {
public:
FloatValueView(FloatProperty* property);
virtual ~FloatValueView();
// TextInputValueView interface
virtual InputTextView* TextView() const;
// PropertyEditorView interface
virtual void ValueChanged();
virtual bool AdoptProperty(Property* property);
private:
FloatProperty* fProperty;
NummericalTextView* fTextView;
};
#endif // FLOAT_VALUE_VIEW_H

View File

@ -0,0 +1,118 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include <stdio.h>
#include <string.h>
#include <Bitmap.h>
#include <Region.h>
#include "IconProperty.h"
#include "PropertyItemView.h"
#include "IconValueView.h"
// constructor
IconValueView::IconValueView(IconProperty* property)
: PropertyEditorView(property),
fProperty(property),
fIcon(NULL)
{
SetFlags(Flags() | B_NAVIGABLE_JUMP);
}
// destructor
IconValueView::~IconValueView()
{
delete fIcon;
}
// Draw
void
IconValueView::Draw(BRect updateRect)
{
BRect r;
BRegion originalClippingRegion;
GetClippingRegion(&originalClippingRegion);
if (fIcon) {
BRect b(Bounds());
// layout icon in the center
r = fIcon->Bounds();
r.OffsetTo(floorf(b.left + b.Width() / 2.0 - r.Width() / 2.0),
floorf(b.top + b.Height() / 2.0 - r.Height() / 2.0));
if (fIcon->ColorSpace() == B_RGBA32 || fIcon->ColorSpace() == B_RGBA32_BIG) {
// set up transparent drawing and let
// the base class draw the entire background
SetHighColor(255, 255, 255, 255);
SetDrawingMode(B_OP_ALPHA);
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
} else {
// constrain clipping region to exclude bitmap
BRegion region = originalClippingRegion;
region.Exclude(r);
ConstrainClippingRegion(&region);
}
}
// draw surrouing area (and possibly background for bitmap)
PropertyEditorView::Draw(updateRect);
ConstrainClippingRegion(&originalClippingRegion);
if (fIcon) {
DrawBitmap(fIcon, r.LeftTop());
}
}
// SetEnabled
void
IconValueView::SetEnabled(bool enabled)
{
// TODO: gray out icon...
}
// AdoptProperty
bool
IconValueView::AdoptProperty(Property* property)
{
IconProperty* p = dynamic_cast<IconProperty*>(property);
if (p) {
SetIcon(p->Icon(), p->Width(), p->Height(), p->Format());
Invalidate();
fProperty = p;
return true;
}
return false;
}
// #pragma mark -
// SetIcon
status_t
IconValueView::SetIcon(const unsigned char* bitsFromQuickRes,
uint32 width, uint32 height, color_space format)
{
status_t status = B_BAD_VALUE;
if (bitsFromQuickRes && width > 0 && height > 0) {
delete fIcon;
fIcon = new BBitmap(BRect(0.0, 0.0, width - 1.0, height - 1.0), format);
status = fIcon ? fIcon->InitCheck() : B_ERROR;
if (status >= B_OK) {
// It doesn't look right to copy BitsLength() bytes, but bitmaps
// exported from QuickRes or WonderBrush still contain their padding,
// so it is alright.
memcpy(fIcon->Bits(), bitsFromQuickRes, fIcon->BitsLength());
} else {
delete fIcon;
fIcon = NULL;
printf("IconValueView::SetIcon() - error allocating bitmap: %s\n", strerror(status));
}
}
return status;
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef ICON_VALUE_VIEW_H
#define ICON_VALUE_VIEW_H
#include "PropertyEditorView.h"
class IconProperty;
class NummericalTextView;
class IconValueView : public PropertyEditorView {
public:
IconValueView(IconProperty* property);
virtual ~IconValueView();
// BView interface
virtual void Draw(BRect updateRect);
// PropertyEditorView interface
virtual void SetEnabled(bool enabled);
virtual bool AdoptProperty(Property* property);
// IconValueView
status_t SetIcon(const unsigned char* bitsFromQuickRes,
uint32 width, uint32 height,
color_space format);
protected:
IconProperty* fProperty;
BBitmap* fIcon;
};
#endif // ICON_VALUE_VIEW_H

View File

@ -0,0 +1,72 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "Int64ValueView.h"
#include <stdio.h>
#include "Int64Property.h"
#include "NummericalTextView.h"
// constructor
Int64ValueView::Int64ValueView(Int64Property* property)
: TextInputValueView(property),
fProperty(property)
{
BRect b = Bounds();
fTextView = new NummericalTextView(b, "nummerical input", b,
B_FOLLOW_LEFT | B_FOLLOW_TOP,
B_WILL_DRAW);
AddChild(fTextView);
fTextView->SetFloatMode(false);
// TODO: make NummericalTextView support int64?
if (fProperty)
fTextView->SetValue((int32)fProperty->Value());
}
// destructor
Int64ValueView::~Int64ValueView()
{
}
// TextView
InputTextView*
Int64ValueView::TextView() const
{
return fTextView;
}
// ValueChanged
void
Int64ValueView::ValueChanged()
{
if (fProperty) {
fProperty->SetValue(fTextView->IntValue());
// TODO: make NummericalTextView support int64?
fTextView->SetValue((int32)fProperty->Value());
TextInputValueView::ValueChanged();
}
}
// AdoptProperty
bool
Int64ValueView::AdoptProperty(Property* property)
{
Int64Property* p = dynamic_cast<Int64Property*>(property);
if (p) {
// TODO: make NummericalTextView support int64?
if (fTextView->IntValue() != (int32)p->Value())
fTextView->SetValue((int32)p->Value());
fProperty = p;
return true;
}
return false;
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef INT64_VALUE_VIEW_H
#define INT64_VALUE_VIEW_H
#include "TextInputValueView.h"
class Int64Property;
class NummericalTextView;
class Int64ValueView : public TextInputValueView {
public:
Int64ValueView(Int64Property* property);
virtual ~Int64ValueView();
// TextInputValueView interface
virtual InputTextView* TextView() const;
// PropertyEditorView interface
virtual void ValueChanged();
virtual bool AdoptProperty(Property* property);
private:
Int64Property* fProperty;
NummericalTextView* fTextView;
};
#endif // INT64_VALUE_VIEW_H

View File

@ -0,0 +1,69 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "IntValueView.h"
#include <stdio.h>
#include "Property.h"
#include "NummericalTextView.h"
// constructor
IntValueView::IntValueView(IntProperty* property)
: TextInputValueView(property),
fProperty(property)
{
BRect b = Bounds();
fTextView = new NummericalTextView(b, "nummerical input", b,
B_FOLLOW_LEFT | B_FOLLOW_TOP,
B_WILL_DRAW);
AddChild(fTextView);
fTextView->SetFloatMode(false);
if (fProperty)
fTextView->SetValue(fProperty->Value());
}
// destructor
IntValueView::~IntValueView()
{
}
// TextView
InputTextView*
IntValueView::TextView() const
{
return fTextView;
}
// ValueChanged
void
IntValueView::ValueChanged()
{
if (fProperty) {
fProperty->SetValue(fTextView->IntValue());
fTextView->SetValue(fProperty->Value());
TextInputValueView::ValueChanged();
}
}
// AdoptProperty
bool
IntValueView::AdoptProperty(Property* property)
{
IntProperty* p = dynamic_cast<IntProperty*>(property);
if (p) {
if (fTextView->IntValue() != p->Value())
fTextView->SetValue(p->Value());
fProperty = p;
return true;
}
return false;
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef INT_VALUE_VIEW_H
#define INT_VALUE_VIEW_H
#include "TextInputValueView.h"
class IntProperty;
class NummericalTextView;
class IntValueView : public TextInputValueView {
public:
IntValueView(IntProperty* property);
virtual ~IntValueView();
// TextInputValueView interface
virtual InputTextView* TextView() const;
// PropertyEditorView interface
virtual void ValueChanged();
virtual bool AdoptProperty(Property* property);
private:
IntProperty* fProperty;
NummericalTextView* fTextView;
};
#endif // INT_VALUE_VIEW_H

View File

@ -0,0 +1,234 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include <stdio.h>
#include <Font.h>
#include <MenuItem.h>
#include <Message.h>
#include <PopUpMenu.h>
#include <Region.h>
#include "OptionProperty.h"
#include "OptionValueView.h"
enum {
MSG_OPTION_CHANGED = 'opch',
};
// constructor
OptionValueView::OptionValueView(OptionProperty* property)
: PropertyEditorView(property),
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(&currentOption);
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;
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef OPTION_VALUE_VIEW_H
#define OPTION_VALUE_VIEW_H
#include <String.h>
#include "PropertyEditorView.h"
class OptionProperty;
class OptionValueView : public PropertyEditorView {
public:
OptionValueView(OptionProperty* property);
virtual ~OptionValueView();
virtual void Draw(BRect updateRect);
virtual void FrameResized(float width, float height);
virtual void MakeFocus(bool focused);
virtual void MessageReceived(BMessage* message);
virtual void MouseDown(BPoint where);
virtual void KeyDown(const char* bytes, int32 numBytes);
virtual void SetEnabled(bool enabled);
virtual void ValueChanged();
virtual bool AdoptProperty(Property* property);
private:
OptionProperty* fProperty;
BString fCurrentOption;
bool fEnabled;
};
#endif // OPTION_VALUE_VIEW_H

View File

@ -0,0 +1,68 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "StringValueView.h"
#include <stdio.h>
#include <string.h>
#include "Property.h"
#include "StringTextView.h"
// constructor
StringValueView::StringValueView(StringProperty* property)
: TextInputValueView(property),
fProperty(property)
{
BRect b = Bounds();
fTextView = new StringTextView(b, "string input", b,
B_FOLLOW_LEFT | B_FOLLOW_TOP,
B_WILL_DRAW);
AddChild(fTextView);
if (fProperty)
fTextView->SetValue(fProperty->Value());
}
// destructor
StringValueView::~StringValueView()
{
}
// TextView
InputTextView*
StringValueView::TextView() const
{
return fTextView;
}
// ValueChanged
void
StringValueView::ValueChanged()
{
if (fProperty) {
fProperty->SetValue(fTextView->Value());
fTextView->SetValue(fProperty->Value());
TextInputValueView::ValueChanged();
}
}
// AdoptProperty
bool
StringValueView::AdoptProperty(Property* property)
{
StringProperty* p = dynamic_cast<StringProperty*>(property);
if (p) {
if (!fProperty || strcmp(p->Value(), fTextView->Text()) != 0) {
fTextView->SetValue(p->Value());
}
fProperty = p;
return true;
}
return false;
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef STRING_VALUE_VIEW_H
#define STRING_VALUE_VIEW_H
#include "TextInputValueView.h"
class StringProperty;
class StringTextView;
class StringValueView : public TextInputValueView {
public:
StringValueView(StringProperty* property);
virtual ~StringValueView();
// TextInputValueView interface
virtual InputTextView* TextView() const;
// PropertyEditorView interface
virtual void ValueChanged();
virtual bool AdoptProperty(Property* property);
private:
StringProperty* fProperty;
StringTextView* fTextView;
};
#endif // STRING_VALUE_VIEW_H

View File

@ -0,0 +1,63 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "SwatchValueView.h"
#include <stdio.h>
// constructor
SwatchValueView::SwatchValueView(const char* name,
BMessage* message,
BHandler* target,
rgb_color color,
float width,
float height)
: SwatchView(name, message, target, color, width, height)
{
uint32 flags = Flags();
flags |= B_NAVIGABLE;
SetFlags(flags);
}
// destructor
SwatchValueView::~SwatchValueView()
{
}
// MakeFocus
void
SwatchValueView::MakeFocus(bool focused)
{
BView::MakeFocus(focused);
if (BView* parent = Parent())
parent->Invalidate();
}
// Draw
void
SwatchValueView::Draw(BRect updateRect)
{
BRect b(Bounds());
if (BView* parent = Parent()) {
SetLowColor(tint_color(parent->LowColor(), B_DARKEN_1_TINT));
StrokeRect(b, B_SOLID_LOW);
b.InsetBy(1.0, 1.0);
}
FillRect(b);
}
// MouseDown
void
SwatchValueView::MouseDown(BPoint where)
{
// forward click
if (BView* parent = Parent())
parent->MouseDown(ConvertToParent(where));
SwatchView::MouseDown(where);
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef SWATCH_VALUE_VIEW_H
#define SWATCH_VALUE_VIEW_H
#include "SwatchView.h"
class SwatchValueView : public SwatchView {
public:
SwatchValueView(const char* name,
BMessage* message,
BHandler* target,
rgb_color color,
float width = 24.0,
float height = 24.0);
virtual ~SwatchValueView();
// BView
virtual void MakeFocus(bool focused);
virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint where);
};
#endif // SWATCH_VALUE_VIEW_H

View File

@ -0,0 +1,106 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "TextInputValueView.h"
#include <stdio.h>
#include <Message.h>
#include <String.h>
#include "NummericalTextView.h"
#include "PropertyItemView.h"
enum {
MSG_VALUE_CHANGED = 'vchd',
};
// constructor
TextInputValueView::TextInputValueView(Property* property)
: PropertyEditorView(property)
{
}
// destructor
TextInputValueView::~TextInputValueView()
{
}
// AttachedToWindow
void
TextInputValueView::AttachedToWindow()
{
TextView()->SetMessage(new BMessage(MSG_VALUE_CHANGED));
TextView()->SetTarget(this);
}
// Draw
void
TextInputValueView::Draw(BRect updateRect)
{
BRect b(Bounds());
if (TextView()->IsFocus())
SetLowColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
StrokeRect(b, B_SOLID_LOW);
}
// FrameResized
void
TextInputValueView::FrameResized(float width, float height)
{
BRect b(Bounds());
b.InsetBy(1.0, 1.0);
TextView()->MoveTo(b.LeftTop());
TextView()->ResizeTo(b.Width(), b.Height());
BRect tr(TextView()->Bounds());
tr.InsetBy(4.0, 1.0);
TextView()->SetTextRect(tr);
}
// MakeFocus
void
TextInputValueView::MakeFocus(bool focused)
{
TextView()->MakeFocus(focused);
}
// MessageReceived
void
TextInputValueView::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_VALUE_CHANGED:
ValueChanged();
break;
default:
PropertyEditorView::MessageReceived(message);
}
}
// SetEnabled
void
TextInputValueView::SetEnabled(bool enabled)
{
TextView()->MakeEditable(enabled);
rgb_color textColor = TextView()->LowColor();
if (enabled)
textColor = tint_color(textColor, B_DARKEN_MAX_TINT);
else
textColor = tint_color(textColor, B_DISABLED_LABEL_TINT);
TextView()->SetFontAndColor(NULL, 0, &textColor);
}
// IsFocused
bool
TextInputValueView::IsFocused() const
{
return TextView()->IsFocus();
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef TEXT_INPUT_VALUE_VIEW_H
#define TEXT_INPUT_VALUE_VIEW_H
#include "PropertyEditorView.h"
class InputTextView;
// Common base class for
// IntValueView,
// Int64ValueView,
// FloatValueView,
// StringValueView
class TextInputValueView : public PropertyEditorView {
public:
TextInputValueView(Property* property);
virtual ~TextInputValueView();
// BView interface
virtual void AttachedToWindow();
virtual void Draw(BRect updateRect);
virtual void FrameResized(float width, float height);
virtual void MakeFocus(bool focused);
virtual void MessageReceived(BMessage* message);
// PropertyItemValueView interface
virtual void SetEnabled(bool enabled);
virtual bool IsFocused() const;
// TextInputValueView
virtual InputTextView* TextView() const = 0;
};
#endif // TEXT_INPUT_VALUE_VIEW_H