* implemented more needed classes, Style, StyleManager, Gradient, Shape

* added Referenceable
TODO: Shape needs list of paths instead of one single path,
also transformers, and such stuff


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17867 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2006-06-17 19:02:32 +00:00
parent 2df2b98416
commit 6ebf703166
12 changed files with 1158 additions and 1 deletions

View File

@ -16,8 +16,10 @@ local sourceDirs =
generic/listener generic/listener
generic/selection generic/selection
generic/support generic/support
gradient
shape shape
shape/commands shape/commands
style
; ;
local sourceDir ; local sourceDir ;
@ -52,8 +54,12 @@ Application Icon-O-Matic :
#generic/support #generic/support
RWLocker.cpp RWLocker.cpp
support.cpp support.cpp
#style
Style.cpp
StyleManager.cpp
#shape #shape
PathManipulator.cpp PathManipulator.cpp
Shape.cpp
VectorPath.cpp VectorPath.cpp
#shape/commands #shape/commands
AddPointCommand.cpp AddPointCommand.cpp
@ -61,6 +67,8 @@ Application Icon-O-Matic :
InsertPointCommand.cpp InsertPointCommand.cpp
PathCommand.cpp PathCommand.cpp
RemovePointsCommand.cpp RemovePointsCommand.cpp
#gradient
Gradient.cpp
# #
CanvasView.cpp CanvasView.cpp
IconEditorApp.cpp IconEditorApp.cpp

View File

@ -0,0 +1,49 @@
/*
* Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* Axel Dörfler, axeld@pinc-software.de
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef REFERENCABLE_H
#define REFERENCABLE_H
#include <SupportDefs.h>
class Referenceable {
public:
Referenceable()
: fReferenceCount(1)
{}
virtual ~Referenceable()
{}
inline void Acquire();
inline bool Release();
private:
vint32 fReferenceCount;
};
// Acquire
inline void
Referenceable::Acquire()
{
atomic_add(&fReferenceCount, 1);
}
// Release
inline bool
Referenceable::Release()
{
if (atomic_add(&fReferenceCount, -1) == 1) {
delete this;
return true;
}
return false;
}
#endif // REFERENCABLE_H

View File

@ -0,0 +1,545 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "Gradient.h"
#include <math.h>
#include <stdio.h>
#include <Message.h>
#include "support.h"
// constructor
color_step::color_step(const rgb_color c, float o)
{
color.red = c.red;
color.green = c.green;
color.blue = c.blue;
color.alpha = c.alpha;
offset = o;
}
// constructor
color_step::color_step(uint8 r, uint8 g, uint8 b, uint8 a, float o)
{
color.red = r;
color.green = g;
color.blue = b;
color.alpha = a;
offset = o;
}
// constructor
color_step::color_step(const color_step& other)
{
color.red = other.color.red;
color.green = other.color.green;
color.blue = other.color.blue;
color.alpha = other.color.alpha;
offset = other.offset;
}
// constructor
color_step::color_step()
{
color.red = 0;
color.green = 0;
color.blue = 0;
color.alpha = 255;
offset = 0;
}
// operator!=
bool
color_step::operator!=(const color_step& other) const
{
return color.red != other.color.red ||
color.green != other.color.green ||
color.blue != other.color.blue ||
color.alpha != other.color.alpha ||
offset != other.offset;
}
// #pragma mark -
// constructor
Gradient::Gradient(bool empty)
: BArchivable(),
fColors(4),
fType(GRADIENT_LINEAR),
fInterpolation(INTERPOLATION_SMOOTH),
fInheritTransformation(true)
{
if (!empty) {
AddColor(color_step(0, 0, 0, 255, 0.0), 0);
AddColor(color_step(255, 255, 255, 255, 1.0), 1);
}
}
// constructor
Gradient::Gradient(BMessage* archive)
: BArchivable(archive),
fColors(4),
fType(GRADIENT_LINEAR),
fInterpolation(INTERPOLATION_SMOOTH),
fInheritTransformation(true)
{
if (!archive)
return;
color_step step;
for (int32 i = 0; archive->FindFloat("offset", i, &step.offset) >= B_OK; i++) {
if (archive->FindInt32("color", i, (int32*)&step.color) >= B_OK)
AddColor(step, i);
else
break;
}
if (archive->FindInt32("type", (int32*)&fType) < B_OK) {
fType = GRADIENT_LINEAR;
}
if (archive->FindInt32("interpolation", (int32*)&fInterpolation) < B_OK) {
fInterpolation = INTERPOLATION_SMOOTH;
}
if (archive->FindBool("inherit transformation", &fInheritTransformation) < B_OK) {
fInheritTransformation = true;
}
}
// constructor
Gradient::Gradient(const Gradient& other)
: BArchivable(other),
fColors(4),
fType(other.fType),
fInterpolation(other.fInterpolation),
fInheritTransformation(other.fInheritTransformation)
{
for (int32 i = 0; color_step* step = other.ColorAt(i); i++) {
AddColor(*step, i);
}
}
// destructor
Gradient::~Gradient()
{
_MakeEmpty();
}
// Archive
status_t
Gradient::Archive(BMessage* into, bool deep) const
{
status_t ret = BArchivable::Archive(into, deep);
// color steps
if (ret >= B_OK) {
for (int32 i = 0; color_step* step = ColorAt(i); i++) {
ret = into->AddInt32("color", (const uint32&)step->color);
if (ret < B_OK)
break;
ret = into->AddFloat("offset", step->offset);
if (ret < B_OK)
break;
}
}
// gradient and interpolation type
if (ret >= B_OK)
ret = into->AddInt32("type", (int32)fType);
if (ret >= B_OK)
ret = into->AddInt32("interpolation", (int32)fInterpolation);
if (ret >= B_OK)
ret = into->AddBool("inherit transformation", fInheritTransformation);
// finish off
if (ret >= B_OK)
ret = into->AddString("class", "Gradient");
return ret;
}
// #pragma mark -
// operator=
Gradient&
Gradient::operator=(const Gradient& other)
{
AutoNotificationSuspender _(this);
SetColors(other);
SetType(other.fType);
SetInterpolation(other.fInterpolation);
SetInheritTransformation(other.fInheritTransformation);
return *this;
}
// operator==
bool
Gradient::operator==(const Gradient& other) const
{
int32 count = CountColors();
if (count == other.CountColors() &&
fType == other.fType &&
fInterpolation == other.fInterpolation &&
fInheritTransformation == other.fInheritTransformation) {
bool equal = true;
for (int32 i = 0; i < count; i++) {
color_step* ourStep = ColorAtFast(i);
color_step* otherStep = other.ColorAtFast(i);
if (*ourStep != *otherStep) {
equal = false;
break;
}
}
return equal;
}
return false;
}
// operator!=
bool
Gradient::operator!=(const Gradient& other) const
{
return !(*this == other);
}
// SetColors
void
Gradient::SetColors(const Gradient& other)
{
AutoNotificationSuspender _(this);
_MakeEmpty();
for (int32 i = 0; color_step* step = other.ColorAt(i); i++)
AddColor(*step, i);
Notify();
}
// #pragma mark -
// AddColor
int32
Gradient::AddColor(const rgb_color& color, float offset)
{
// find the correct index (sorted by offset)
color_step* step = new color_step(color, offset);
int32 index = 0;
int32 count = CountColors();
for (; index < count; index++) {
color_step* s = ColorAtFast(index);
if (s->offset > step->offset)
break;
}
if (!fColors.AddItem((void*)step, index)) {
delete step;
return -1;
}
Notify();
return index;
}
// AddColor
bool
Gradient::AddColor(const color_step& color, int32 index)
{
color_step* step = new color_step(color);
if (!fColors.AddItem((void*)step, index)) {
delete step;
return false;
}
Notify();
return true;
}
// RemoveColor
bool
Gradient::RemoveColor(int32 index)
{
color_step* step = (color_step*)fColors.RemoveItem(index);
if (!step) {
return false;
}
delete step;
Notify();
return true;
}
// #pragma mark -
// SetColor
bool
Gradient::SetColor(int32 index, const color_step& color)
{
if (color_step* step = ColorAt(index)) {
step->color = color.color;
step->offset = color.offset;
Notify();
return true;
}
return false;
}
// SetColor
bool
Gradient::SetColor(int32 index, const rgb_color& color)
{
if (color_step* step = ColorAt(index)) {
step->color = color;
Notify();
return true;
}
return false;
}
// SetOffset
bool
Gradient::SetOffset(int32 index, float offset)
{
color_step* step = ColorAt(index);
if (step && step->offset != offset) {
step->offset = offset;
Notify();
return true;
}
return false;
}
// #pragma mark -
// CountColors
int32
Gradient::CountColors() const
{
return fColors.CountItems();
}
// ColorAt
color_step*
Gradient::ColorAt(int32 index) const
{
return (color_step*)fColors.ItemAt(index);
}
// ColorAtFast
color_step*
Gradient::ColorAtFast(int32 index) const
{
return (color_step*)fColors.ItemAtFast(index);
}
// #pragma mark -
// SetType
void
Gradient::SetType(gradient_type type)
{
if (fType != type) {
fType = type;
Notify();
}
}
// SetInterpolation
void
Gradient::SetInterpolation(interpolation_type type)
{
if (fInterpolation != type) {
fInterpolation = type;
Notify();
}
}
// SetInheritTransformation
void
Gradient::SetInheritTransformation(bool inherit)
{
if (fInheritTransformation != inherit) {
fInheritTransformation = inherit;
Notify();
}
}
// #pragma mark -
// MakeGradient
void
Gradient::MakeGradient(uint32* colors, int32 count) const
{
color_step* from = ColorAt(0);
if (!from)
return;
// find the step with the lowest offset
for (int32 i = 0; color_step* step = ColorAt(i); i++) {
if (step->offset < from->offset)
from = step;
}
// current index into "colors" array
int32 index = (int32)floorf(count * from->offset + 0.5);
if (index < 0)
index = 0;
if (index > count)
index = count;
// make sure we fill the entire array
if (index > 0) {
uint8* c = (uint8*)&colors[0];
for (int32 i = 0; i < index; i++) {
c[0] = from->color.blue;
c[1] = from->color.green;
c[2] = from->color.red;
c[3] = from->color.alpha;
c += 4;
}
}
// put all steps that we need to interpolate to into a list
BList nextSteps(fColors.CountItems() - 1);
for (int32 i = 0; color_step* step = ColorAt(i); i++) {
if (step != from)
nextSteps.AddItem((void*)step);
}
// interpolate "from" to "to"
while (!nextSteps.IsEmpty()) {
// find the step with the next offset
color_step* to = NULL;
float nextOffsetDist = 2.0;
for (int32 i = 0; color_step* step = (color_step*)nextSteps.ItemAt(i); i++) {
float d = step->offset - from->offset;
if (d < nextOffsetDist && d >= 0) {
to = step;
nextOffsetDist = d;
}
}
if (!to)
break;
nextSteps.RemoveItem((void*)to);
// interpolate
int32 offset = (int32)floorf((count - 1) * to->offset + 0.5);
if (offset >= count)
offset = count - 1;
int32 dist = offset - index;
if (dist >= 0) {
uint8* c = (uint8*)&colors[index];
#if GAMMA_BLEND
uint16 fromRed = kGammaTable[from->color.red];
uint16 fromGreen = kGammaTable[from->color.green];
uint16 fromBlue = kGammaTable[from->color.blue];
uint16 toRed = kGammaTable[to->color.red];
uint16 toGreen = kGammaTable[to->color.green];
uint16 toBlue = kGammaTable[to->color.blue];
for (int32 i = index; i <= offset; i++) {
float f = (float)(offset - i) / (float)(dist + 1);
if (fInterpolation == INTERPOLATION_SMOOTH)
f = gauss(1.0 - f);
float t = 1.0 - f;
c[0] = kInverseGammaTable[(uint16)floor(fromBlue * f + toBlue * t + 0.5)];
c[1] = kInverseGammaTable[(uint16)floor(fromGreen * f + toGreen * t + 0.5)];
c[2] = kInverseGammaTable[(uint16)floor(fromRed * f + toRed * t + 0.5)];
c[3] = (uint8)floor(from->color.alpha * f + to->color.alpha * t + 0.5);
c += 4;
}
#else // GAMMA_BLEND
for (int32 i = index; i <= offset; i++) {
float f = (float)(offset - i) / (float)(dist + 1);
if (fInterpolation == INTERPOLATION_SMOOTH)
f = gauss(1.0 - f);
float t = 1.0 - f;
c[0] = (uint8)floor(from->color.blue * f + to->color.blue * t + 0.5);
c[1] = (uint8)floor(from->color.green * f + to->color.green * t + 0.5);
c[2] = (uint8)floor(from->color.red * f + to->color.red * t + 0.5);
c[3] = (uint8)floor(from->color.alpha * f + to->color.alpha * t + 0.5);
c += 4;
}
#endif // GAMMA_BLEND
}
index = offset + 1;
// the current "to" will be the "from" in the next interpolation
from = to;
}
// make sure we fill the entire array
if (index < count) {
uint8* c = (uint8*)&colors[index];
for (int32 i = index; i < count; i++) {
c[0] = from->color.blue;
c[1] = from->color.green;
c[2] = from->color.red;
c[3] = from->color.alpha;
c += 4;
}
}
}
// string_for_type
static const char*
string_for_type(gradient_type type)
{
switch (type) {
case GRADIENT_LINEAR:
return "GRADIENT_LINEAR";
case GRADIENT_CIRCULAR:
return "GRADIENT_CIRCULAR";
case GRADIENT_DIAMONT:
return "GRADIENT_DIAMONT";
case GRADIENT_CONIC:
return "GRADIENT_CONIC";
case GRADIENT_XY:
return "GRADIENT_XY";
case GRADIENT_SQRT_XY:
return "GRADIENT_SQRT_XY";
}
return "<unkown>";
}
//string_for_interpolation
static const char*
string_for_interpolation(interpolation_type type)
{
switch (type) {
case INTERPOLATION_LINEAR:
return "INTERPOLATION_LINEAR";
case INTERPOLATION_SMOOTH:
return "INTERPOLATION_SMOOTH";
}
return "<unkown>";
}
// PrintToStream
void
Gradient::PrintToStream() const
{
printf("Gradient: type: %s, interpolation: %s, inherits transform: %d\n",
string_for_type(fType),
string_for_interpolation(fInterpolation),
fInheritTransformation);
for (int32 i = 0; color_step* step = ColorAt(i); i++) {
printf(" %ld: offset: %.1f -> color(%d, %d, %d, %d)\n",
i, step->offset,
step->color.red,
step->color.green,
step->color.blue,
step->color.alpha);
}
}
// _MakeEmpty
void
Gradient::_MakeEmpty()
{
int32 count = CountColors();
for (int32 i = 0; i < count; i++)
delete ColorAtFast(i);
fColors.MakeEmpty();
}

View File

@ -0,0 +1,104 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef GRADIENT_H
#define GRADIENT_H
#include <Archivable.h>
#include <GraphicsDefs.h>
#include <List.h>
#include "Observable.h"
class BMessage;
enum gradient_type {
GRADIENT_LINEAR = 0,
GRADIENT_CIRCULAR,
GRADIENT_DIAMONT,
GRADIENT_CONIC,
GRADIENT_XY,
GRADIENT_SQRT_XY,
};
enum interpolation_type {
INTERPOLATION_LINEAR = 0,
INTERPOLATION_SMOOTH,
};
struct color_step {
color_step(const rgb_color c, float o);
color_step(uint8 r, uint8 g, uint8 b, uint8 a, float o);
color_step(const color_step& other);
color_step();
bool operator!=(const color_step& other) const;
rgb_color color;
float offset;
};
class Gradient : public BArchivable,
public Observable {
public:
Gradient(bool empty = false);
Gradient(BMessage* archive);
Gradient(const Gradient& other);
virtual ~Gradient();
status_t Archive(BMessage* into, bool deep = true) const;
Gradient& operator=(const Gradient& other);
bool operator==(const Gradient& other) const;
bool operator!=(const Gradient& other) const;
void SetColors(const Gradient& other);
int32 AddColor(const rgb_color& color, float offset);
bool AddColor(const color_step& color, int32 index);
bool RemoveColor(int32 index);
bool SetColor(int32 index, const color_step& step);
bool SetColor(int32 index, const rgb_color& color);
bool SetOffset(int32 index, float offset);
int32 CountColors() const;
color_step* ColorAt(int32 index) const;
color_step* ColorAtFast(int32 index) const;
void SetType(gradient_type type);
gradient_type Type() const
{ return fType; }
void SetInterpolation(interpolation_type type);
interpolation_type Interpolation() const
{ return fInterpolation; }
void SetInheritTransformation(bool inherit);
bool InheritTransformation() const
{ return fInheritTransformation; }
void MakeGradient(uint32* colors,
int32 count) const;
void PrintToStream() const;
private:
void _MakeEmpty();
BList fColors;
gradient_type fType;
interpolation_type fInterpolation;
bool fInheritTransformation;
};
#endif // GRADIENT_H

View File

@ -0,0 +1,69 @@
#include "Shape.h"
#include "Style.h"
#include "VectorPath.h"
// constructor
Shape::Shape(VectorPath* path, ::Style* style)
: fPath(path),
fStyle(style)
{
if (fPath)
fPath->Acquire();
if (fStyle)
fStyle->Acquire();
}
// destructor
Shape::~Shape()
{
if (fPath)
fPath->Release();
if (fStyle)
fStyle->Release();
}
// SetPath
void
Shape::SetPath(VectorPath* path)
{
if (fPath == path)
return;
if (fPath)
fPath->Release();
fPath = path;
if (fPath)
fPath->Acquire();
Notify();
}
// SetStyle
void
Shape::SetStyle(::Style* style)
{
if (fStyle == style)
return;
if (fStyle)
fStyle->Release();
fStyle = style;
if (fStyle)
fStyle->Acquire();
Notify();
}
// Bounds
BRect
Shape::Bounds() const
{
if (fPath)
return fPath->Bounds();
return BRect(0, 0, -1, -1);
}

View File

@ -0,0 +1,32 @@
#ifndef SHAPE_H
#define SHAPE_H
#include <Rect.h>
#include "Observable.h"
class Style;
class VectorPath;
class Shape : public Observable {
public:
Shape(VectorPath* path,
::Style* style);
virtual ~Shape();
void SetPath(VectorPath* path);
inline VectorPath* Path() const
{ return fPath; }
void SetStyle(::Style* style);
inline ::Style* Style() const
{ return fStyle; }
BRect Bounds() const;
private:
VectorPath* fPath;
::Style* fStyle;
};
#endif // SHAPE_H

View File

@ -72,6 +72,8 @@ get_path_storage(agg::path_storage& path,
// constructor // constructor
VectorPath::VectorPath() VectorPath::VectorPath()
: BArchivable(), : BArchivable(),
Observable(),
Referenceable(),
fPath(NULL), fPath(NULL),
fClosed(false), fClosed(false),
fPointCount(0), fPointCount(0),
@ -84,6 +86,7 @@ VectorPath::VectorPath()
VectorPath::VectorPath(const VectorPath& from) VectorPath::VectorPath(const VectorPath& from)
: BArchivable(), : BArchivable(),
Observable(), Observable(),
Referenceable(),
fPath(NULL), fPath(NULL),
fPointCount(0), fPointCount(0),
fAllocCount(0), fAllocCount(0),
@ -96,6 +99,7 @@ VectorPath::VectorPath(const VectorPath& from)
VectorPath::VectorPath(const BMessage* archive) VectorPath::VectorPath(const BMessage* archive)
: BArchivable(), : BArchivable(),
Observable(), Observable(),
Referenceable(),
fPath(NULL), fPath(NULL),
fClosed(false), fClosed(false),
fPointCount(0), fPointCount(0),

View File

@ -15,6 +15,7 @@
#include <agg_path_storage.h> #include <agg_path_storage.h>
#include "Observable.h" #include "Observable.h"
#include "Referenceable.h"
class BBitmap; class BBitmap;
class BMessage; class BMessage;
@ -28,7 +29,8 @@ struct control_point {
}; };
class VectorPath : public BArchivable, class VectorPath : public BArchivable,
public Observable { public Observable,
public Referenceable {
public: public:
class Iterator { class Iterator {

View File

@ -0,0 +1,40 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "Style.h"
#include "Gradient.h"
// constructor
Style::Style()
: Referenceable(),
fColor(),
fGradient(NULL)
{
}
// destructor
Style::~Style()
{
delete fGradient;
}
// SetColor
void
Style::SetColor(const rgb_color& color)
{
fColor = color;
}
// SetGradient
void
Style::SetGradient(::Gradient* gradient)
{
delete fGradient;
fGradient = gradient;
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef STYLE_H
#define STYLE_H
#include <GraphicsDefs.h>
#include "Referenceable.h"
class Gradient;
class Style : public Referenceable {
public:
Style();
virtual ~Style();
void SetColor(const rgb_color& color);
inline rgb_color Color() const
{ return fColor; }
void SetGradient(::Gradient* gradient);
::Gradient* Gradient() const
{ return fGradient; }
private:
rgb_color fColor;
::Gradient* fGradient;
};
#endif // STYLE_H

View File

@ -0,0 +1,208 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "StyleManager.h"
#include <stdio.h>
#include <string.h>
#include <OS.h>
#include "Style.h"
// constructor
StyleManagerListener::StyleManagerListener()
{
}
// destructor
StyleManagerListener::~StyleManagerListener()
{
}
// constructor
StyleManager::StyleManager()
: RWLocker()
{
}
// destructor
StyleManager::~StyleManager()
{
int32 count = fListeners.CountItems();
if (count > 0) {
debugger("~StyleManager() - there are still"
"listeners attached\n");
}
_MakeEmpty();
}
// #pragma mark -
// AddStyle
bool
StyleManager::AddStyle(Style* style)
{
if (!style)
return false;
// prevent adding the same style twice
if (HasStyle(style))
return false;
if (fStyles.AddItem((void*)style)) {
_NotifyStyleAdded(style);
_StateChanged();
return true;
}
fprintf(stderr, "StyleManager::AddStyle() - out of memory!\n");
return false;
}
// RemoveStyle
bool
StyleManager::RemoveStyle(Style* style)
{
if (fStyles.RemoveItem((void*)style)) {
_NotifyStyleRemoved(style);
_StateChanged();
return true;
}
return false;
}
// RemoveStyle
Style*
StyleManager::RemoveStyle(int32 index)
{
Style* style = (Style*)fStyles.RemoveItem(index);
if (style) {
_NotifyStyleRemoved(style);
_StateChanged();
}
return style;
}
// MakeEmpty
void
StyleManager::MakeEmpty()
{
_MakeEmpty();
_StateChanged();
}
// #pragma mark -
// CountStyles
int32
StyleManager::CountStyles() const
{
return fStyles.CountItems();
}
// HasStyle
bool
StyleManager::HasStyle(Style* style) const
{
return fStyles.HasItem((void*)style);
}
// StyleAt
Style*
StyleManager::StyleAt(int32 index) const
{
return (Style*)fStyles.ItemAt(index);
}
// StyleAtFast
Style*
StyleManager::StyleAtFast(int32 index) const
{
return (Style*)fStyles.ItemAtFast(index);
}
// StateChanged
void
StyleManager::StateChanged()
{
// empty
}
// #pragma mark -
// AddListener
bool
StyleManager::AddListener(StyleManagerListener* listener)
{
if (listener && !fListeners.HasItem((void*)listener))
return fListeners.AddItem(listener);
return false;
}
// RemoveListener
bool
StyleManager::RemoveListener(StyleManagerListener* listener)
{
return fListeners.RemoveItem(listener);
}
// #pragma mark -
// _StateChanged
void
StyleManager::_StateChanged()
{
StateChanged();
}
// _MakeEmpty
void
StyleManager::_MakeEmpty()
{
int32 count = CountStyles();
for (int32 i = 0; i < count; i++) {
Style* style = StyleAtFast(i);
_NotifyStyleRemoved(style);
style->Release();
}
fStyles.MakeEmpty();
}
// #pragma mark -
// _NotifyStyleAdded
void
StyleManager::_NotifyStyleAdded(Style* style) const
{
BList listeners(fListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
StyleManagerListener* listener
= (StyleManagerListener*)listeners.ItemAtFast(i);
listener->StyleAdded(style);
}
}
// _NotifyStyleRemoved
void
StyleManager::_NotifyStyleRemoved(Style* style) const
{
BList listeners(fListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
StyleManagerListener* listener
= (StyleManagerListener*)listeners.ItemAtFast(i);
listener->StyleRemoved(style);
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef STYLE_MANAGER_H
#define STYLE_MANAGER_H
#include <List.h>
#include "RWLocker.h"
class Style;
class StyleManagerListener {
public:
StyleManagerListener();
virtual ~StyleManagerListener();
virtual void StyleAdded(Style* style) = 0;
virtual void StyleRemoved(Style* style) = 0;
};
class StyleManager : public RWLocker {
public:
StyleManager();
virtual ~StyleManager();
bool AddStyle(Style* style);
bool RemoveStyle(Style* style);
Style* RemoveStyle(int32 index);
void MakeEmpty();
int32 CountStyles() const;
bool HasStyle(Style* style) const;
Style* StyleAt(int32 index) const;
Style* StyleAtFast(int32 index) const;
virtual void StateChanged();
bool AddListener(StyleManagerListener* listener);
bool RemoveListener(StyleManagerListener* listener);
private:
void _StateChanged();
void _MakeEmpty();
void _NotifyStyleAdded(Style* style) const;
void _NotifyStyleRemoved(Style* style) const;
BList fStyles;
BList fListeners;
};
#endif // STYLE_MANAGER_H