From 4215c452a4a92759e04b8c221016fea48531f1bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Sat, 8 Jul 2006 13:04:05 +0000 Subject: [PATCH] * implemented MoveTransformersCommand (so Transformers can be drag sorted now) * implemented RemoveTransformersCommand * implemented StyleListView (I promise, this is the last list view :-) * implemented adding new styles via the Style menu * implemented selecting the Style of the currently selected Shape git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18072 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/icon-o-matic/Jamfile | 3 + src/apps/icon-o-matic/MainWindow.cpp | 46 +- src/apps/icon-o-matic/MainWindow.h | 3 + src/apps/icon-o-matic/gui/PathListView.cpp | 3 + src/apps/icon-o-matic/gui/StyleListView.cpp | 548 ++++++++++++++++++ src/apps/icon-o-matic/gui/StyleListView.h | 87 +++ .../icon-o-matic/gui/TransformerListView.cpp | 77 +-- .../icon-o-matic/gui/TransformerListView.h | 11 +- src/apps/icon-o-matic/shape/Shape.cpp | 20 +- src/apps/icon-o-matic/shape/Shape.h | 7 + .../shape/commands/MoveShapesCommand.h | 2 + .../commands/MoveTransformersCommand.cpp | 161 +++++ .../shape/commands/MoveTransformersCommand.h | 43 ++ .../commands/RemoveTransformersCommand.cpp | 107 ++++ .../commands/RemoveTransformersCommand.h | 42 ++ 15 files changed, 1120 insertions(+), 40 deletions(-) create mode 100644 src/apps/icon-o-matic/gui/StyleListView.cpp create mode 100644 src/apps/icon-o-matic/gui/StyleListView.h create mode 100644 src/apps/icon-o-matic/shape/commands/MoveTransformersCommand.cpp create mode 100644 src/apps/icon-o-matic/shape/commands/MoveTransformersCommand.h create mode 100644 src/apps/icon-o-matic/shape/commands/RemoveTransformersCommand.cpp create mode 100644 src/apps/icon-o-matic/shape/commands/RemoveTransformersCommand.h diff --git a/src/apps/icon-o-matic/Jamfile b/src/apps/icon-o-matic/Jamfile index 36e02e7ed1..a04ea38e6b 100644 --- a/src/apps/icon-o-matic/Jamfile +++ b/src/apps/icon-o-matic/Jamfile @@ -111,6 +111,7 @@ Application Icon-O-Matic : IconObjectListView.cpp PathListView.cpp ShapeListView.cpp + StyleListView.cpp SwatchGroup.cpp TransformerListView.cpp # shape @@ -124,9 +125,11 @@ Application Icon-O-Matic : ChangePointCommand.cpp InsertPointCommand.cpp MoveShapesCommand.cpp + MoveTransformersCommand.cpp PathCommand.cpp RemovePointsCommand.cpp RemoveShapesCommand.cpp + RemoveTransformersCommand.cpp # style Gradient.cpp Style.cpp diff --git a/src/apps/icon-o-matic/MainWindow.cpp b/src/apps/icon-o-matic/MainWindow.cpp index a15329eed4..3eadcf73d7 100644 --- a/src/apps/icon-o-matic/MainWindow.cpp +++ b/src/apps/icon-o-matic/MainWindow.cpp @@ -25,6 +25,7 @@ #include "PathListView.h" #include "ScrollView.h" #include "ShapeListView.h" +#include "StyleListView.h" #include "SwatchGroup.h" #include "TransformerFactory.h" #include "TransformerListView.h" @@ -49,6 +50,9 @@ enum { MSG_NEW_PATH = 'nwvp', MSG_PATH_SELECTED = 'vpsl', + MSG_NEW_STYLE = 'nwst', + MSG_STYLE_SELECTED = 'stsl', + MSG_NEW_SHAPE = 'nwsp', MSG_SHAPE_SELECTED = 'spsl', MSG_ADD_TRANSFORMER = 'adtr', @@ -56,7 +60,7 @@ enum { // constructor MainWindow::MainWindow(IconEditorApp* app, Document* document) - : BWindow(BRect(50, 50, 891, 781), "Icon-O-Matic", + : BWindow(BRect(20, 50, 1010, 781), "Icon-O-Matic", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS), fApp(app), @@ -107,11 +111,28 @@ case MSG_PATH_SELECTED: { } break; } +// TODO: use an AddStyleCommand +case MSG_NEW_STYLE: { + Style* style = new Style(); + style->SetColor((rgb_color){ rand() % 255, + rand() % 255, + rand() % 255, + 255 }); + StyleManager::Default()->AddStyle(style); + break; +} +// TODO: use an AddShapeCommand +case MSG_NEW_SHAPE: { + Shape* shape = new Shape(StyleManager::Default()->StyleAt(0)); + fDocument->Icon()->Shapes()->AddShape(shape); + break; +} case MSG_SHAPE_SELECTED: { Shape* shape; if (message->FindPointer("shape", (void**)&shape) < B_OK) shape = NULL; fPathListView->SetCurrentShape(shape); + fStyleListView->SetCurrentShape(shape); fTransformerListView->SetShape(shape); break; } @@ -200,13 +221,20 @@ MainWindow::_Init() fCanvasView->SetIcon(fDocument->Icon()); fPathListView->SetPathContainer(fDocument->Icon()->Paths()); + fPathListView->SetShapeContainer(fDocument->Icon()->Shapes()); // fPathListView->SetCommandStack(fDocument->CommandStack()); fPathListView->SetSelection(fDocument->Selection()); + fStyleListView->SetStyleManager(StyleManager::Default()); + fStyleListView->SetShapeContainer(fDocument->Icon()->Shapes()); +// fStyleListView->SetCommandStack(fDocument->CommandStack()); + fStyleListView->SetSelection(fDocument->Selection()); + fShapeListView->SetShapeContainer(fDocument->Icon()->Shapes()); fShapeListView->SetCommandStack(fDocument->CommandStack()); fShapeListView->SetSelection(fDocument->Selection()); + fTransformerListView->SetCommandStack(fDocument->CommandStack()); fTransformerListView->SetSelection(fDocument->Selection()); fPropertyListView->SetCommandStack(fDocument->CommandStack()); @@ -329,6 +357,11 @@ MainWindow::_CreateGUI(BRect bounds) fPathListView = new PathListView(bounds, "path list view", new BMessage(MSG_PATH_SELECTED), this); + // style list view + bounds.OffsetBy(bounds.Width() + 6 + B_V_SCROLL_BAR_WIDTH, 0); + fStyleListView = new StyleListView(bounds, "style list view", + new BMessage(MSG_STYLE_SELECTED), this); + // shape list view bounds.OffsetBy(bounds.Width() + 6 + B_V_SCROLL_BAR_WIDTH, 0); fShapeListView = new ShapeListView(bounds, "shape list view", @@ -354,6 +387,11 @@ MainWindow::_CreateGUI(BRect bounds) B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true, B_NO_BORDER)); + bg->AddChild(new BScrollView("style list scroll view", + fStyleListView, + B_FOLLOW_LEFT | B_FOLLOW_TOP, + 0, false, true, + B_NO_BORDER)); bg->AddChild(new BScrollView("shape list scroll view", fShapeListView, B_FOLLOW_LEFT | B_FOLLOW_TOP, @@ -367,6 +405,7 @@ MainWindow::_CreateGUI(BRect bounds) // scroll view around property list view bounds.OffsetBy(bounds.Width() + 6 + B_V_SCROLL_BAR_WIDTH, 0); + bounds.right = bg->Bounds().right - 5; bg->AddChild(new ScrollView(fPropertyListView, SCROLL_VERTICAL | SCROLL_NO_FRAME, bounds, "property scroll view", @@ -414,6 +453,11 @@ MainWindow::_CreateMenuBar(BRect frame) // Path pathMenu->AddItem(new BMenuItem("New", new BMessage(MSG_NEW_PATH))); + // Style + styleMenu->AddItem(new BMenuItem("New", new BMessage(MSG_NEW_STYLE))); + + // Shape + shapeMenu->AddItem(new BMenuItem("New", new BMessage(MSG_NEW_SHAPE))); // Transformer int32 cookie = 0; diff --git a/src/apps/icon-o-matic/MainWindow.h b/src/apps/icon-o-matic/MainWindow.h index 8bc2118596..a823302bf5 100644 --- a/src/apps/icon-o-matic/MainWindow.h +++ b/src/apps/icon-o-matic/MainWindow.h @@ -22,6 +22,7 @@ class IconEditorApp; class IconView; class PathListView; class ShapeListView; +class StyleListView; class SwatchGroup; class TransformerListView; @@ -61,6 +62,8 @@ class MainWindow : public BWindow, IconView* fIconPreview64; PathListView* fPathListView; + StyleListView* fStyleListView; + ShapeListView* fShapeListView; TransformerListView* fTransformerListView; IconObjectListView* fPropertyListView; diff --git a/src/apps/icon-o-matic/gui/PathListView.cpp b/src/apps/icon-o-matic/gui/PathListView.cpp index 029185953b..fe60c543b6 100644 --- a/src/apps/icon-o-matic/gui/PathListView.cpp +++ b/src/apps/icon-o-matic/gui/PathListView.cpp @@ -173,6 +173,7 @@ class ShapePathListener : public PathContainerListener, SetShape(NULL); } + // PathContainerListener interface virtual void PathAdded(VectorPath* path) { fListView->_SetPathMarked(path, true); @@ -182,12 +183,14 @@ class ShapePathListener : public PathContainerListener, fListView->_SetPathMarked(path, false); } + // ShapeContainerListener interface virtual void ShapeAdded(Shape* shape, int32 index) {} virtual void ShapeRemoved(Shape* shape) { fListView->SetCurrentShape(NULL); } + // ShapePathListener void SetShape(Shape* shape) { if (fShape == shape) diff --git a/src/apps/icon-o-matic/gui/StyleListView.cpp b/src/apps/icon-o-matic/gui/StyleListView.cpp new file mode 100644 index 0000000000..4f3c8a4244 --- /dev/null +++ b/src/apps/icon-o-matic/gui/StyleListView.cpp @@ -0,0 +1,548 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#include "StyleListView.h" + +#include + +#include +#include +#include +#include +#include + +#include "Style.h" +#include "Observer.h" +#include "Shape.h" +#include "ShapeContainer.h" +#include "Selection.h" + +static const float kMarkWidth = 14.0; +static const float kBorderOffset = 3.0; +static const float kTextOffset = 4.0; + +class StyleListItem : public SimpleItem, + public Observer { + public: + StyleListItem(Style* s, + StyleListView* listView, + bool markEnabled) + : SimpleItem(""), + style(NULL), + fListView(listView), + fMarkEnabled(markEnabled), + fMarked(false) + { + SetStyle(s); + } + + virtual ~StyleListItem() + { + SetStyle(NULL); + } + + // SimpleItem interface + virtual void Draw(BView* owner, BRect itemFrame, uint32 flags) + { + SimpleItem::DrawBackground(owner, itemFrame, flags); + + // text + owner->SetHighColor(0, 0, 0, 255); + font_height fh; + owner->GetFontHeight(&fh); + BString truncatedString(Text()); + owner->TruncateString(&truncatedString, B_TRUNCATE_MIDDLE, + itemFrame.Width() + - kBorderOffset + - kMarkWidth + - kTextOffset + - kBorderOffset); + float height = itemFrame.Height(); + float textHeight = fh.ascent + fh.descent; + BPoint pos; + pos.x = itemFrame.left + + kBorderOffset + kMarkWidth + kTextOffset; + pos.y = itemFrame.top + + ceilf((height - textHeight) / 2.0 + fh.ascent); + owner->DrawString(truncatedString.String(), pos); + + if (!fMarkEnabled) + return; + + // mark + BRect markRect = itemFrame; + markRect.left += kBorderOffset; + markRect.right = markRect.left + kMarkWidth; + markRect.top = (markRect.top + markRect.bottom - kMarkWidth) / 2.0; + markRect.bottom = markRect.top + kMarkWidth; + owner->SetHighColor(tint_color(owner->LowColor(), B_DARKEN_1_TINT)); + owner->StrokeRect(markRect); + markRect.InsetBy(1, 1); + owner->SetHighColor(tint_color(owner->LowColor(), 1.04)); + owner->FillRect(markRect); + if (fMarked) { + markRect.InsetBy(2, 2); + owner->SetHighColor(tint_color(owner->LowColor(), + B_DARKEN_4_TINT)); + owner->SetPenSize(2); + owner->StrokeLine(markRect.LeftTop(), markRect.RightBottom()); + owner->StrokeLine(markRect.LeftBottom(), markRect.RightTop()); + owner->SetPenSize(1); + } + } + + // Observer interface + virtual void ObjectChanged(const Observable* object) + { + UpdateText(); + } + + // StyleListItem + void SetStyle(Style* s) + { + if (s == style) + return; + + if (style) { + style->RemoveObserver(this); + style->Release(); + } + + style = s; + + if (style) { + style->Acquire(); + style->AddObserver(this); + UpdateText(); + } + } + void UpdateText() + { + SetText(style->Name()); + Invalidate(); + } + + void SetMarkEnabled(bool enabled) + { + if (fMarkEnabled == enabled) + return; + fMarkEnabled = enabled; + Invalidate(); + } + void SetMarked(bool marked) + { + if (fMarked == marked) + return; + fMarked = marked; + Invalidate(); + } + + void Invalidate() + { + // :-/ + if (fListView->LockLooper()) { + fListView->InvalidateItem( + fListView->IndexOf(this)); + fListView->UnlockLooper(); + } + } + + Style* style; + private: + StyleListView* fListView; + bool fMarkEnabled; + bool fMarked; +}; + + +class ShapeStyleListener : public ShapeListener, + public ShapeContainerListener { + public: + ShapeStyleListener(StyleListView* listView) + : fListView(listView), + fShape(NULL) + { + } + virtual ~ShapeStyleListener() + { + SetShape(NULL); + } + + // ShapeListener interface + virtual void TransformerAdded(Transformer* t, int32 index) {} + virtual void TransformerRemoved(Transformer* t) {} + + virtual void StyleChanged(Style* oldStyle, Style* newStyle) + { + fListView->_SetStyleMarked(oldStyle, false); + fListView->_SetStyleMarked(newStyle, true); + } + + // ShapeContainerListener interface + virtual void ShapeAdded(Shape* shape, int32 index) {} + virtual void ShapeRemoved(Shape* shape) + { + fListView->SetCurrentShape(NULL); + } + + // ShapeStyleListener + void SetShape(Shape* shape) + { + if (fShape == shape) + return; + + if (fShape) + fShape->RemoveListener(this); + + fShape = shape; + + if (fShape) + fShape->AddListener(this); + } + + Shape* CurrentShape() const + { + return fShape; + } + + private: + StyleListView* fListView; + Shape* fShape; +}; + +// #pragma mark - + +// constructor +StyleListView::StyleListView(BRect frame, + const char* name, + BMessage* message, BHandler* target) + : SimpleListView(frame, name, + NULL, B_SINGLE_SELECTION_LIST), + fMessage(message), + fStyleContainer(NULL), + fShapeContainer(NULL), + fSelection(NULL), + fCommandStack(NULL), + + fCurrentShape(NULL), + fShapeListener(new ShapeStyleListener(this)) +{ + SetTarget(target); +} + +// destructor +StyleListView::~StyleListView() +{ + _MakeEmpty(); + delete fMessage; + + if (fStyleContainer) + fStyleContainer->RemoveListener(this); + + if (fShapeContainer) + fShapeContainer->RemoveListener(fShapeListener); + + delete fShapeListener; +} + +// SelectionChanged +void +StyleListView::SelectionChanged() +{ + // NOTE: single selection list + + StyleListItem* item + = dynamic_cast(ItemAt(CurrentSelection(0))); + if (item && fMessage) { + BMessage message(*fMessage); + message.AddPointer("style", (void*)item->style); + Invoke(&message); + } + + // modify global Selection + if (!fSelection) + return; + + if (item) + fSelection->Select(item->style); + else + fSelection->DeselectAll(); +} + +// MouseDown +void +StyleListView::MouseDown(BPoint where) +{ + if (!fCurrentShape) { + SimpleListView::MouseDown(where); + return; + } + + bool handled = false; + int32 index = IndexOf(where); + StyleListItem* item = dynamic_cast(ItemAt(index)); + if (item) { + BRect itemFrame(ItemFrame(index)); + itemFrame.right = itemFrame.left + + kBorderOffset + kMarkWidth + + kTextOffset / 2.0; + Style* style = item->style; + if (itemFrame.Contains(where)) { + // set the style on the shape +// TODO: code this command... +// Command* command = new SetStyleToShapeCommand( +// fCurrentShape, style); +// fCommandStack->Perform(command); +fCurrentShape->SetStyle(style); + handled = true; + } + } + + if (!handled) + SimpleListView::MouseDown(where); +} + +// MessageReceived +void +StyleListView::MessageReceived(BMessage* message) +{ + SimpleListView::MessageReceived(message); +} + +// MakeDragMessage +void +StyleListView::MakeDragMessage(BMessage* message) const +{ +} + +// AcceptDragMessage +bool +StyleListView::AcceptDragMessage(const BMessage* message) const +{ + return false; +} + +// SetDropTargetRect +void +StyleListView::SetDropTargetRect(const BMessage* message, BPoint where) +{ +} + +// MoveItems +void +StyleListView::MoveItems(BList& items, int32 toIndex) +{ +} + +// CopyItems +void +StyleListView::CopyItems(BList& items, int32 toIndex) +{ +} + +// RemoveItemList +void +StyleListView::RemoveItemList(BList& indices) +{ + // TODO: allow removing items +} + +// CloneItem +BListItem* +StyleListView::CloneItem(int32 index) const +{ + if (StyleListItem* item = dynamic_cast(ItemAt(index))) { + return new StyleListItem(item->style, + const_cast(this), + fCurrentShape != NULL); + } + return NULL; +} + +// #pragma mark - + +// StyleAdded +void +StyleListView::StyleAdded(Style* style) +{ + // NOTE: we are in the thread that messed with the + // StyleManager, so no need to lock the + // container, when this is changed to asynchronous + // notifications, then it would need to be read-locked! + if (!LockLooper()) + return; + + // NOTE: shapes are always added at the end + // of the list, so the sorting is synced... + if (_AddStyle(style)) + Select(CountItems() - 1); + + UnlockLooper(); +} + +// StyleRemoved +void +StyleListView::StyleRemoved(Style* style) +{ + // NOTE: we are in the thread that messed with the + // StyleManager, so no need to lock the + // container, when this is changed to asynchronous + // notifications, then it would need to be read-locked! + if (!LockLooper()) + return; + + // NOTE: we're only interested in Style objects + _RemoveStyle(style); + + UnlockLooper(); +} + +// #pragma mark - + +// SetStyleManager +void +StyleListView::SetStyleManager(StyleManager* container) +{ + if (fStyleContainer == container) + return; + + // detach from old container + if (fStyleContainer) + fStyleContainer->RemoveListener(this); + + _MakeEmpty(); + + fStyleContainer = container; + + if (!fStyleContainer) + return; + + fStyleContainer->AddListener(this); + + // sync +// if (!fStyleContainer->ReadLock()) +// return; + + int32 count = fStyleContainer->CountStyles(); + for (int32 i = 0; i < count; i++) + _AddStyle(fStyleContainer->StyleAtFast(i)); + +// fStyleContainer->ReadUnlock(); +} + +// SetShapeContainer +void +StyleListView::SetShapeContainer(ShapeContainer* container) +{ + if (fShapeContainer == container) + return; + + // detach from old container + if (fShapeContainer) + fShapeContainer->RemoveListener(fShapeListener); + + fShapeContainer = container; + + if (fShapeContainer) + fShapeContainer->AddListener(fShapeListener); +} + +// SetSelection +void +StyleListView::SetSelection(Selection* selection) +{ + fSelection = selection; +} + +// SetCurrentShape +void +StyleListView::SetCurrentShape(Shape* shape) +{ + if (fCurrentShape == shape) + return; + + fCurrentShape = shape; + fShapeListener->SetShape(shape); + + _UpdateMarks(); +} + +// #pragma mark - + +// _AddStyle +bool +StyleListView::_AddStyle(Style* style) +{ + if (style) + return AddItem(new StyleListItem(style, this, fCurrentShape != NULL)); + return false; +} + +// _RemoveStyle +bool +StyleListView::_RemoveStyle(Style* style) +{ + StyleListItem* item = _ItemForStyle(style); + if (item && RemoveItem(item)) { + delete item; + return true; + } + return false; +} + +// _ItemForStyle +StyleListItem* +StyleListView::_ItemForStyle(Style* style) const +{ + for (int32 i = 0; + StyleListItem* item = dynamic_cast(ItemAt(i)); + i++) { + if (item->style == style) + return item; + } + return NULL; +} + +// #pragma mark - + +// _UpdateMarks +void +StyleListView::_UpdateMarks() +{ + int32 count = CountItems(); + if (fCurrentShape) { + // enable display of marks and mark items whoes + // style is contained in fCurrentShape + for (int32 i = 0; i < count; i++) { + StyleListItem* item = dynamic_cast(ItemAt(i)); + if (!item) + continue; + item->SetMarkEnabled(true); + item->SetMarked(fCurrentShape->Style() == item->style); + } + } else { + // disable display of marks + for (int32 i = 0; i < count; i++) { + StyleListItem* item = dynamic_cast(ItemAt(i)); + if (!item) + continue; + item->SetMarkEnabled(false); + } + } + + Invalidate(); +} + +// _SetStyleMarked +void +StyleListView::_SetStyleMarked(Style* style, bool marked) +{ + if (StyleListItem* item = _ItemForStyle(style)) { + item->SetMarked(marked); + } +} diff --git a/src/apps/icon-o-matic/gui/StyleListView.h b/src/apps/icon-o-matic/gui/StyleListView.h new file mode 100644 index 0000000000..74d705290f --- /dev/null +++ b/src/apps/icon-o-matic/gui/StyleListView.h @@ -0,0 +1,87 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#ifndef STYLE_LIST_VIEW_H +#define STYLE_LIST_VIEW_H + +#include "ListViews.h" +#include "StyleManager.h" + +class CommandStack; +class Selection; +class Shape; +class ShapeContainer; +class ShapeListener; +class Style; +class StyleListItem; + +class StyleListView : public SimpleListView, + public StyleManagerListener { + public: + StyleListView(BRect frame, + const char* name, + BMessage* selectionMessage = NULL, + BHandler* target = NULL); + virtual ~StyleListView(); + + // SimpleListView interface + virtual void SelectionChanged(); + + virtual void MouseDown(BPoint where); + virtual void MessageReceived(BMessage* message); + + virtual void MakeDragMessage(BMessage* message) const; + + virtual bool AcceptDragMessage(const BMessage* message) const; + virtual void SetDropTargetRect(const BMessage* message, + BPoint where); + + virtual void MoveItems(BList& items, int32 toIndex); + virtual void CopyItems(BList& items, int32 toIndex); + virtual void RemoveItemList(BList& indices); + + virtual BListItem* CloneItem(int32 atIndex) const; + + // StyleManagerListener interface + virtual void StyleAdded(Style* style); + virtual void StyleRemoved(Style* style); + + // StyleListView + void SetStyleManager(StyleManager* container); + void SetShapeContainer(ShapeContainer* container); + void SetSelection(Selection* selection); + + void SetCurrentShape(Shape* shape); + Shape* CurrentShape() const + { return fCurrentShape; } + + private: + bool _AddStyle(Style* style); + bool _RemoveStyle(Style* style); + + StyleListItem* _ItemForStyle(Style* style) const; + + friend class ShapeStyleListener; + void _UpdateMarks(); + void _SetStyleMarked(Style* style, bool marked); + + BMessage* fMessage; + + StyleManager* fStyleContainer; + ShapeContainer* fShapeContainer; + Selection* fSelection; + CommandStack* fCommandStack; + + Shape* fCurrentShape; + // the style item will be marked that + // is referenced by this shape + + ShapeStyleListener* fShapeListener; +}; + +#endif // STYLE_LIST_VIEW_H diff --git a/src/apps/icon-o-matic/gui/TransformerListView.cpp b/src/apps/icon-o-matic/gui/TransformerListView.cpp index 4694af0bda..903f9c8efe 100644 --- a/src/apps/icon-o-matic/gui/TransformerListView.cpp +++ b/src/apps/icon-o-matic/gui/TransformerListView.cpp @@ -18,8 +18,8 @@ #include #include "CommandStack.h" -//#include "MoveTransformersCommand.h" -//#include "RemoveTransformersCommand.h" +#include "MoveTransformersCommand.h" +#include "RemoveTransformersCommand.h" #include "Transformer.h" #include "Observer.h" #include "Selection.h" @@ -160,29 +160,29 @@ TransformerListView::MakeDragMessage(BMessage* message) const void TransformerListView::MoveItems(BList& items, int32 toIndex) { -// if (!fCommandStack || !fShape) -// return; -// -// int32 count = items.CountItems(); -// Transformer** transformers = new (nothrow) Transformer*[count]; -// if (!shapes) -// return; -// -// for (int32 i = 0; i < count; i++) { -// TransformerItem* item -// = dynamic_cast((BListItem*)items.ItemAtFast(i)); -// transformers[i] = item ? item->transformer : NULL; -// } -// -// MoveTransformersCommand* command -// = new (nothrow) MoveTransformersCommand(fShape, -// transformers, count, toIndex); -// if (!command) { -// delete[] transformers; -// return; -// } -// -// fCommandStack->Perform(command); + if (!fCommandStack || !fShape) + return; + + int32 count = items.CountItems(); + Transformer** transformers = new (nothrow) Transformer*[count]; + if (!transformers) + return; + + for (int32 i = 0; i < count; i++) { + TransformerItem* item + = dynamic_cast((BListItem*)items.ItemAtFast(i)); + transformers[i] = item ? item->transformer : NULL; + } + + MoveTransformersCommand* command + = new (nothrow) MoveTransformersCommand(fShape, + transformers, count, toIndex); + if (!command) { + delete[] transformers; + return; + } + + fCommandStack->Perform(command); } // CopyItems @@ -197,16 +197,16 @@ TransformerListView::CopyItems(BList& items, int32 toIndex) void TransformerListView::RemoveItemList(BList& indexList) { -// if (!fCommandStack || !fShape) -// return; -// -// int32 count = indexList.CountItems(); -// const int32* indices = (int32*)indexList.Items(); -// -// RemoveTransformersCommand* command -// = new (nothrow) RemoveTransformersCommand(fShape, -// indices, count); -// fCommandStack->Perform(command); + if (!fCommandStack || !fShape) + return; + + int32 count = indexList.CountItems(); + const int32* indices = (int32*)indexList.Items(); + + RemoveTransformersCommand* command + = new (nothrow) RemoveTransformersCommand(fShape, + indices, count); + fCommandStack->Perform(command); } // CloneItem @@ -254,6 +254,13 @@ TransformerListView::TransformerRemoved(Transformer* transformer) UnlockLooper(); } +// StyleChanged +void +TransformerListView::StyleChanged(Style* oldStyle, Style* newStyle) +{ + // we don't care +} + // #pragma mark - // SetShape diff --git a/src/apps/icon-o-matic/gui/TransformerListView.h b/src/apps/icon-o-matic/gui/TransformerListView.h index 3139bf8832..87018a94fc 100644 --- a/src/apps/icon-o-matic/gui/TransformerListView.h +++ b/src/apps/icon-o-matic/gui/TransformerListView.h @@ -42,16 +42,21 @@ class TransformerListView : public SimpleListView, int32 index); virtual void TransformerRemoved(Transformer* transformer); + virtual void StyleChanged(Style* oldStyle, Style* newStyle); + // TransformerListView void SetShape(Shape* shape); void SetSelection(Selection* selection); void SetCommandStack(CommandStack* stack); private: - bool _AddTransformer(Transformer* transformer, int32 index); - bool _RemoveTransformer(Transformer* transformer); + bool _AddTransformer( + Transformer* transformer, int32 index); + bool _RemoveTransformer( + Transformer* transformer); - TransformerItem* _ItemForTransformer(Transformer* transformer) const; + TransformerItem* _ItemForTransformer( + Transformer* transformer) const; BMessage* fMessage; diff --git a/src/apps/icon-o-matic/shape/Shape.cpp b/src/apps/icon-o-matic/shape/Shape.cpp index fcc6946c8e..4cd3e853b2 100644 --- a/src/apps/icon-o-matic/shape/Shape.cpp +++ b/src/apps/icon-o-matic/shape/Shape.cpp @@ -177,6 +177,8 @@ Shape::InitCheck() const return fPaths ? B_OK : B_NO_MEMORY; } +// #pragma mark - + // SetStyle void Shape::SetStyle(::Style* style) @@ -189,6 +191,7 @@ Shape::SetStyle(::Style* style) fStyle->Release(); } + ::Style* oldStyle = fStyle; fStyle = style; if (fStyle) { @@ -196,7 +199,7 @@ Shape::SetStyle(::Style* style) fStyle->AddObserver(this); } - _NotifyRerender(); + _NotifyStyleChanged(oldStyle, fStyle); } // #pragma mark - @@ -373,6 +376,21 @@ Shape::_NotifyTransformerRemoved(Transformer* transformer) const _NotifyRerender(); } +// _NotifyStyleChanged +void +Shape::_NotifyStyleChanged(::Style* oldStyle, ::Style* newStyle) const +{ + BList listeners(fListeners); + int32 count = listeners.CountItems(); + for (int32 i = 0; i < count; i++) { + ShapeListener* listener + = (ShapeListener*)listeners.ItemAtFast(i); + listener->StyleChanged(oldStyle, newStyle); + } + // TODO: merge Observable and ShapeListener interface + _NotifyRerender(); +} + // _NotifyRerender void Shape::_NotifyRerender() const diff --git a/src/apps/icon-o-matic/shape/Shape.h b/src/apps/icon-o-matic/shape/Shape.h index 58d120a57a..bbf0dd39e0 100644 --- a/src/apps/icon-o-matic/shape/Shape.h +++ b/src/apps/icon-o-matic/shape/Shape.h @@ -13,6 +13,7 @@ class Style; // TODO: merge Observer and ShapeListener interface +// ie add "AppearanceChanged(Shape* shape)" class ShapeListener { public: ShapeListener(); @@ -21,6 +22,9 @@ class ShapeListener { virtual void TransformerAdded(Transformer* t, int32 index) = 0; virtual void TransformerRemoved(Transformer* t) = 0; + + virtual void StyleChanged(::Style* oldStyle, + ::Style* newStyle) = 0; }; class Shape : public IconObject, @@ -84,6 +88,9 @@ class Shape : public IconObject, int32 index) const; void _NotifyTransformerRemoved(Transformer* t) const; + void _NotifyStyleChanged(::Style* oldStyle, + ::Style* newStyle) const; + void _NotifyRerender() const; PathContainer* fPaths; diff --git a/src/apps/icon-o-matic/shape/commands/MoveShapesCommand.h b/src/apps/icon-o-matic/shape/commands/MoveShapesCommand.h index bf6621613a..3efcc7e7f8 100644 --- a/src/apps/icon-o-matic/shape/commands/MoveShapesCommand.h +++ b/src/apps/icon-o-matic/shape/commands/MoveShapesCommand.h @@ -11,6 +11,8 @@ #include "Command.h" +// TODO: make a templated "move items" command? + class Shape; class ShapeContainer; diff --git a/src/apps/icon-o-matic/shape/commands/MoveTransformersCommand.cpp b/src/apps/icon-o-matic/shape/commands/MoveTransformersCommand.cpp new file mode 100644 index 0000000000..fe5fadc8b0 --- /dev/null +++ b/src/apps/icon-o-matic/shape/commands/MoveTransformersCommand.cpp @@ -0,0 +1,161 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#include "MoveTransformersCommand.h" + +#include +#include + +#include "Shape.h" +#include "Transformer.h" + +using std::nothrow; + +// constructor +MoveTransformersCommand::MoveTransformersCommand(Shape* container, + Transformer** transformers, + int32 count, + int32 toIndex) + : Command(), + fContainer(container), + fTransformers(transformers), + fIndices(count > 0 ? new (nothrow) int32[count] : NULL), + fToIndex(toIndex), + fCount(count) +{ + if (!fContainer || !fTransformers || !fIndices) + return; + + // init original shape indices and + // adjust toIndex compensating for items that + // are removed before that index + int32 itemsBeforeIndex = 0; + for (int32 i = 0; i < fCount; i++) { + fIndices[i] = fContainer->IndexOf(fTransformers[i]); + if (fIndices[i] >= 0 && fIndices[i] < fToIndex) + itemsBeforeIndex++; + } + fToIndex -= itemsBeforeIndex; +} + +// destructor +MoveTransformersCommand::~MoveTransformersCommand() +{ + delete[] fTransformers; + delete[] fIndices; +} + +// InitCheck +status_t +MoveTransformersCommand::InitCheck() +{ + if (!fContainer || !fTransformers || !fIndices) + return B_NO_INIT; + + // analyse the move, don't return B_OK in case + // the container state does not change... + + int32 index = fIndices[0]; + // NOTE: fIndices == NULL if fCount < 1 + + if (index != fToIndex) { + // a change is guaranteed + return B_OK; + } + + // the insertion index is the same as the index of the first + // moved item, a change only occures if the indices of the + // moved items is not contiguous + bool isContiguous = true; + for (int32 i = 1; i < fCount; i++) { + if (fIndices[i] != index + 1) { + isContiguous = false; + break; + } + index = fIndices[i]; + } + if (isContiguous) { + // the container state will not change because of the move + return B_ERROR; + } + + return B_OK; +} + +// Perform +status_t +MoveTransformersCommand::Perform() +{ + status_t ret = B_OK; + + // remove shapes from container + for (int32 i = 0; i < fCount; i++) { + if (fTransformers[i] + && !fContainer->RemoveTransformer(fTransformers[i])) { + ret = B_ERROR; + break; + } + } + if (ret < B_OK) + return ret; + + // add shapes to container at the insertion index + int32 index = fToIndex; + for (int32 i = 0; i < fCount; i++) { + if (fTransformers[i] + && !fContainer->AddTransformer(fTransformers[i], index++)) { + ret = B_ERROR; + break; + } + } + + return ret; +} + +// Undo +status_t +MoveTransformersCommand::Undo() +{ + status_t ret = B_OK; + + // remove shapes from container + for (int32 i = 0; i < fCount; i++) { + if (fTransformers[i] + && !fContainer->RemoveTransformer(fTransformers[i])) { + ret = B_ERROR; + break; + } + } + if (ret < B_OK) + return ret; + + // add shapes to container at remembered indices + for (int32 i = 0; i < fCount; i++) { + if (fTransformers[i] + && !fContainer->AddTransformer(fTransformers[i], fIndices[i])) { + ret = B_ERROR; + break; + } + } + + return ret; +} + +// GetName +void +MoveTransformersCommand::GetName(BString& name) +{ +// if (fCount > 1) +// name << _GetString(MOVE_TRANSFORMERS, "Move Transformers"); +// else +// name << _GetString(MOVE_TRANSFORMER, "Move Transformer"); + if (fCount > 1) + name << "Move Transformers"; + else + name << "Move Transformer"; +} diff --git a/src/apps/icon-o-matic/shape/commands/MoveTransformersCommand.h b/src/apps/icon-o-matic/shape/commands/MoveTransformersCommand.h new file mode 100644 index 0000000000..8c36203ea1 --- /dev/null +++ b/src/apps/icon-o-matic/shape/commands/MoveTransformersCommand.h @@ -0,0 +1,43 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#ifndef MOVE_TRANSFORMERS_COMMAND_H +#define MOVE_TRANSFORMERS_COMMAND_H + +#include "Command.h" + +// TODO: make a templated "move items" command? + +class Shape; +class Transformer; + +class MoveTransformersCommand : public Command { + public: + MoveTransformersCommand( + Shape* shape, + Transformer** transformers, + int32 count, + int32 toIndex); + virtual ~MoveTransformersCommand(); + + virtual status_t InitCheck(); + + virtual status_t Perform(); + virtual status_t Undo(); + + virtual void GetName(BString& name); + + private: + Shape* fContainer; + Transformer** fTransformers; + int32* fIndices; + int32 fToIndex; + int32 fCount; +}; + +#endif // MOVE_TRANSFORMERS_COMMAND_H diff --git a/src/apps/icon-o-matic/shape/commands/RemoveTransformersCommand.cpp b/src/apps/icon-o-matic/shape/commands/RemoveTransformersCommand.cpp new file mode 100644 index 0000000000..2feb381d44 --- /dev/null +++ b/src/apps/icon-o-matic/shape/commands/RemoveTransformersCommand.cpp @@ -0,0 +1,107 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#include "RemoveTransformersCommand.h" + +#include +#include +#include + +#include "ShapeContainer.h" +#include "Shape.h" + +using std::nothrow; + +// constructor +RemoveTransformersCommand::RemoveTransformersCommand(Shape* container, + const int32* indices, + int32 count) + : Command(), + fContainer(container), + fTransformers(count > 0 ? new (nothrow) Transformer*[count] : NULL), + fIndices(count > 0 ? new (nothrow) int32[count] : NULL), + fCount(count), + fTransformersRemoved(false) +{ + if (!fContainer || !fTransformers || !fIndices) + return; + + memcpy(fIndices, indices, sizeof(int32) * fCount); + for (int32 i = 0; i < fCount; i++) + fTransformers[i] = fContainer->TransformerAt(fIndices[i]); +} + +// destructor +RemoveTransformersCommand::~RemoveTransformersCommand() +{ + if (fTransformersRemoved && fTransformers) { + for (int32 i = 0; i < fCount; i++) + delete fTransformers[i]; + } + delete[] fTransformers; + delete[] fIndices; +} + +// InitCheck +status_t +RemoveTransformersCommand::InitCheck() +{ + return fContainer && fTransformers && fIndices ? B_OK : B_NO_INIT; +} + +// Perform +status_t +RemoveTransformersCommand::Perform() +{ + status_t ret = B_OK; + + // remove shapes from container + for (int32 i = 0; i < fCount; i++) { + if (fTransformers[i] + && !fContainer->RemoveTransformer(fTransformers[i])) { + ret = B_ERROR; + break; + } + } + fTransformersRemoved = true; + + return ret; +} + +// Undo +status_t +RemoveTransformersCommand::Undo() +{ + status_t ret = B_OK; + + // add shapes to container at remembered indices + for (int32 i = 0; i < fCount; i++) { + if (fTransformers[i] + && !fContainer->AddTransformer(fTransformers[i], fIndices[i])) { + ret = B_ERROR; + break; + } + } + fTransformersRemoved = false; + + return ret; +} + +// GetName +void +RemoveTransformersCommand::GetName(BString& name) +{ +// if (fCount > 1) +// name << _GetString(MOVE_TRANSFORMERS, "Move Transformers"); +// else +// name << _GetString(MOVE_TRANSFORMER, "Move Transformer"); + if (fCount > 1) + name << "Remove Transformers"; + else + name << "Remove Transformer"; +} diff --git a/src/apps/icon-o-matic/shape/commands/RemoveTransformersCommand.h b/src/apps/icon-o-matic/shape/commands/RemoveTransformersCommand.h new file mode 100644 index 0000000000..b8fbadb819 --- /dev/null +++ b/src/apps/icon-o-matic/shape/commands/RemoveTransformersCommand.h @@ -0,0 +1,42 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#ifndef REMOVE_TRANSFORMERS_COMMAND_H +#define REMOVE_TRANSFORMERS_COMMAND_H + +#include "Command.h" + +class Shape; +class Transformer; + +// TODO: make a templated "remove items" command? + +class RemoveTransformersCommand : public Command { + public: + RemoveTransformersCommand( + Shape* container, + const int32* indices, + int32 count); + virtual ~RemoveTransformersCommand(); + + virtual status_t InitCheck(); + + virtual status_t Perform(); + virtual status_t Undo(); + + virtual void GetName(BString& name); + + private: + Shape* fContainer; + Transformer** fTransformers; + int32* fIndices; + int32 fCount; + bool fTransformersRemoved; +}; + +#endif // REMOVE_TRANSFORMERS_COMMAND_H