diff --git a/src/apps/icon-o-matic/Jamfile b/src/apps/icon-o-matic/Jamfile index 38bf148e0d..8ba1a2608e 100644 --- a/src/apps/icon-o-matic/Jamfile +++ b/src/apps/icon-o-matic/Jamfile @@ -16,8 +16,10 @@ local sourceDirs = generic/listener generic/selection generic/support + gradient shape shape/commands + style ; local sourceDir ; @@ -52,8 +54,12 @@ Application Icon-O-Matic : #generic/support RWLocker.cpp support.cpp + #style + Style.cpp + StyleManager.cpp #shape PathManipulator.cpp + Shape.cpp VectorPath.cpp #shape/commands AddPointCommand.cpp @@ -61,6 +67,8 @@ Application Icon-O-Matic : InsertPointCommand.cpp PathCommand.cpp RemovePointsCommand.cpp + #gradient + Gradient.cpp # CanvasView.cpp IconEditorApp.cpp diff --git a/src/apps/icon-o-matic/generic/support/Referenceable.h b/src/apps/icon-o-matic/generic/support/Referenceable.h new file mode 100644 index 0000000000..26aa0955c5 --- /dev/null +++ b/src/apps/icon-o-matic/generic/support/Referenceable.h @@ -0,0 +1,49 @@ +/* + * Copyright 2001-2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * DarkWyrm + * Axel Dörfler, axeld@pinc-software.de + * Stephan Aßmus + */ +#ifndef REFERENCABLE_H +#define REFERENCABLE_H + +#include + +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 diff --git a/src/apps/icon-o-matic/gradient/Gradient.cpp b/src/apps/icon-o-matic/gradient/Gradient.cpp new file mode 100644 index 0000000000..5c76082c59 --- /dev/null +++ b/src/apps/icon-o-matic/gradient/Gradient.cpp @@ -0,0 +1,545 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#include "Gradient.h" + +#include +#include + +#include + +#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 ""; +} + +//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 ""; +} + +// 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(); +} diff --git a/src/apps/icon-o-matic/gradient/Gradient.h b/src/apps/icon-o-matic/gradient/Gradient.h new file mode 100644 index 0000000000..4bee078e15 --- /dev/null +++ b/src/apps/icon-o-matic/gradient/Gradient.h @@ -0,0 +1,104 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#ifndef GRADIENT_H +#define GRADIENT_H + +#include +#include +#include + +#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 diff --git a/src/apps/icon-o-matic/shape/Shape.cpp b/src/apps/icon-o-matic/shape/Shape.cpp new file mode 100644 index 0000000000..636f5ec994 --- /dev/null +++ b/src/apps/icon-o-matic/shape/Shape.cpp @@ -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); +} diff --git a/src/apps/icon-o-matic/shape/Shape.h b/src/apps/icon-o-matic/shape/Shape.h new file mode 100644 index 0000000000..8a82e75c61 --- /dev/null +++ b/src/apps/icon-o-matic/shape/Shape.h @@ -0,0 +1,32 @@ +#ifndef SHAPE_H +#define SHAPE_H + +#include + +#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 diff --git a/src/apps/icon-o-matic/shape/VectorPath.cpp b/src/apps/icon-o-matic/shape/VectorPath.cpp index 488ec315f3..8e645244f3 100644 --- a/src/apps/icon-o-matic/shape/VectorPath.cpp +++ b/src/apps/icon-o-matic/shape/VectorPath.cpp @@ -72,6 +72,8 @@ get_path_storage(agg::path_storage& path, // constructor VectorPath::VectorPath() : BArchivable(), + Observable(), + Referenceable(), fPath(NULL), fClosed(false), fPointCount(0), @@ -84,6 +86,7 @@ VectorPath::VectorPath() VectorPath::VectorPath(const VectorPath& from) : BArchivable(), Observable(), + Referenceable(), fPath(NULL), fPointCount(0), fAllocCount(0), @@ -96,6 +99,7 @@ VectorPath::VectorPath(const VectorPath& from) VectorPath::VectorPath(const BMessage* archive) : BArchivable(), Observable(), + Referenceable(), fPath(NULL), fClosed(false), fPointCount(0), diff --git a/src/apps/icon-o-matic/shape/VectorPath.h b/src/apps/icon-o-matic/shape/VectorPath.h index 59f288268b..2a5c78c949 100644 --- a/src/apps/icon-o-matic/shape/VectorPath.h +++ b/src/apps/icon-o-matic/shape/VectorPath.h @@ -15,6 +15,7 @@ #include #include "Observable.h" +#include "Referenceable.h" class BBitmap; class BMessage; @@ -28,7 +29,8 @@ struct control_point { }; class VectorPath : public BArchivable, - public Observable { + public Observable, + public Referenceable { public: class Iterator { diff --git a/src/apps/icon-o-matic/style/Style.cpp b/src/apps/icon-o-matic/style/Style.cpp new file mode 100644 index 0000000000..900d714507 --- /dev/null +++ b/src/apps/icon-o-matic/style/Style.cpp @@ -0,0 +1,40 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#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; +} diff --git a/src/apps/icon-o-matic/style/Style.h b/src/apps/icon-o-matic/style/Style.h new file mode 100644 index 0000000000..f04b1d5e99 --- /dev/null +++ b/src/apps/icon-o-matic/style/Style.h @@ -0,0 +1,36 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#ifndef STYLE_H +#define STYLE_H + +#include + +#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 diff --git a/src/apps/icon-o-matic/style/StyleManager.cpp b/src/apps/icon-o-matic/style/StyleManager.cpp new file mode 100644 index 0000000000..14385ff855 --- /dev/null +++ b/src/apps/icon-o-matic/style/StyleManager.cpp @@ -0,0 +1,208 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#include "StyleManager.h" + +#include +#include + +#include + +#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); + } +} + diff --git a/src/apps/icon-o-matic/style/StyleManager.h b/src/apps/icon-o-matic/style/StyleManager.h new file mode 100644 index 0000000000..1d2978dede --- /dev/null +++ b/src/apps/icon-o-matic/style/StyleManager.h @@ -0,0 +1,60 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#ifndef STYLE_MANAGER_H +#define STYLE_MANAGER_H + +#include + +#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