From 61b0e9e3149012ccbd48a10dcbc7f83600bb4769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Wed, 12 Jul 2006 15:46:01 +0000 Subject: [PATCH] * added a little bit of tracing to object destruction, since there seems to be a problem when quitting the app * added Undo/Redo commands for numerous operations - (un)assigning VectorPaths to Shapes - adding new VectorPaths - removing VectorPaths - adding Shapes - transforming Shapes - adding Styles - changing Style color * there was a mix up in classes inheriting from SimpleListView, RemoveItemList() gives a list of item pointers, not indices * GradientControl sent the focus notification to the window instead of the set BHandler target * StyleView takes care of transfering the current Style color or the focused gradient stop color to the CurrentColor object, so the current color of the SwatchGroup is synced * small improvement to layout of SwatchGroup * SwatchGroup no longer knows anything about a Style * fixed syncing the global Selection to the listview selection at least for ShapeListView * implemented cloning Shapes - added Transformer::Clone(VectorSource& source) to all Transformers - ShapeListView uses this when dropping shapes with shift pressed * updated NOTES * added Transformable::matrix_size, so that "6" isn't hardcoded everywhere (though it still is at most places) * added listener interface to TransformBox, this is used by the new TransformObjectsCommand, as long as the TransformBox still exists, the command modifies the TransformBox transformation instead of messing with the objects itself * fixed hotspot size in TransformBox by using the zoom level of the CanvasView * TransformBox rotates/scales correctly around the visible pivot * fixed TransformCommand toggling to transformation (the diff was bogus) * Gradient doesn't trigger unnecessary notifications in SetColor() * CanvasView doesn't eat keyboard events when the GradientControl or one of the ListViews has focus (is a hack currently...) * fixed bug in PropertyListView when it calls the PropertyChanged() hook: because of the notification mechanism, the Properties might be toast after the hook returns * moved all GetProperty() implementations from headers into .cpp files git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18122 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/icon-o-matic/IconEditorApp.cpp | 2 + src/apps/icon-o-matic/Jamfile | 8 ++ src/apps/icon-o-matic/MainWindow.cpp | 74 ++++++---- src/apps/icon-o-matic/NOTES | 16 +-- src/apps/icon-o-matic/document/Document.cpp | 8 +- src/apps/icon-o-matic/document/Icon.cpp | 1 + .../generic/gui/stateview/StateView.cpp | 21 ++- .../generic/property/CommonPropertyIDs.cpp | 3 + .../generic/property/CommonPropertyIDs.h | 1 + .../generic/property/PropertyObject.cpp | 7 + .../generic/property/PropertyObject.h | 1 + .../property/view/PropertyListView.cpp | 9 +- .../specific_properties/BoolValueView.cpp | 9 +- .../view/specific_properties/BoolValueView.h | 3 +- .../specific_properties/ColorValueView.cpp | 13 +- .../view/specific_properties/ColorValueView.h | 3 +- .../specific_properties/FloatValueView.cpp | 10 ++ .../view/specific_properties/FloatValueView.h | 3 +- .../specific_properties/IconValueView.cpp | 7 + .../view/specific_properties/IconValueView.h | 3 +- .../specific_properties/Int64ValueView.cpp | 7 + .../view/specific_properties/Int64ValueView.h | 3 +- .../view/specific_properties/IntValueView.cpp | 7 + .../view/specific_properties/IntValueView.h | 3 +- .../specific_properties/OptionValueView.cpp | 7 + .../specific_properties/OptionValueView.h | 3 +- .../specific_properties/StringValueView.cpp | 7 + .../specific_properties/StringValueView.h | 3 +- .../generic/support/Referenceable.cpp | 77 +++++++++++ .../generic/support/Referenceable.h | 30 +--- src/apps/icon-o-matic/gui/GradientControl.cpp | 12 +- src/apps/icon-o-matic/gui/PathListView.cpp | 69 +++++++--- src/apps/icon-o-matic/gui/PathListView.h | 3 +- src/apps/icon-o-matic/gui/ShapeListView.cpp | 49 +++++-- src/apps/icon-o-matic/gui/ShapeListView.h | 2 +- src/apps/icon-o-matic/gui/StyleListView.cpp | 2 +- src/apps/icon-o-matic/gui/StyleListView.h | 2 +- src/apps/icon-o-matic/gui/StyleView.cpp | 73 +++++++++- src/apps/icon-o-matic/gui/StyleView.h | 5 + src/apps/icon-o-matic/gui/SwatchGroup.cpp | 38 +----- src/apps/icon-o-matic/gui/SwatchGroup.h | 3 - .../icon-o-matic/gui/TransformerListView.cpp | 8 +- .../icon-o-matic/gui/TransformerListView.h | 2 +- src/apps/icon-o-matic/shape/PathContainer.cpp | 1 + src/apps/icon-o-matic/shape/Shape.cpp | 12 +- src/apps/icon-o-matic/shape/VectorPath.cpp | 14 ++ src/apps/icon-o-matic/shape/VectorPath.h | 3 + .../shape/commands/AddPathsCommand.cpp | 108 +++++++++++++++ .../shape/commands/AddPathsCommand.h | 43 ++++++ .../shape/commands/AddShapesCommand.cpp | 99 ++++++++++++++ .../shape/commands/AddShapesCommand.h | 41 ++++++ .../shape/commands/RemovePathsCommand.cpp | 128 ++++++++++++++++++ .../shape/commands/RemovePathsCommand.h | 46 +++++++ .../shape/commands/RemoveShapesCommand.cpp | 4 +- .../shape/commands/RemoveShapesCommand.h | 2 +- .../shape/commands/UnassignPathCommand.cpp | 66 +++++++++ .../shape/commands/UnassignPathCommand.h | 36 +++++ .../icon-o-matic/style/AddStylesCommand.cpp | 99 ++++++++++++++ .../icon-o-matic/style/AddStylesCommand.h | 41 ++++++ src/apps/icon-o-matic/style/Gradient.cpp | 18 ++- .../icon-o-matic/style/SetColorCommand.cpp | 82 +++++++++++ src/apps/icon-o-matic/style/SetColorCommand.h | 38 ++++++ .../transformable/ChannelTransform.cpp | 8 +- .../transformable/TransformBox.cpp | 75 ++++++++-- .../icon-o-matic/transformable/TransformBox.h | 31 ++++- .../transformable/TransformBoxStates.cpp | 8 +- .../transformable/TransformCommand.cpp | 20 +-- .../transformable/TransformCommand.h | 2 +- .../transformable/TransformObjectsCommand.cpp | 115 ++++++++++++++++ .../transformable/TransformObjectsCommand.h | 56 ++++++++ .../transformable/TransformShapesBox.cpp | 43 ++++-- .../transformable/TransformShapesBox.h | 5 +- .../transformable/Transformable.cpp | 16 +-- .../transformable/Transformable.h | 8 +- .../transformer/AffineTransformer.cpp | 14 ++ .../transformer/AffineTransformer.h | 4 +- .../transformer/ContourTransformer.cpp | 20 +++ .../transformer/ContourTransformer.h | 4 +- .../transformer/PerspectiveTransformer.cpp | 17 +++ .../transformer/PerspectiveTransformer.h | 6 +- .../transformer/StrokeTransformer.cpp | 32 +++++ .../transformer/StrokeTransformer.h | 6 +- .../icon-o-matic/transformer/Transformer.h | 4 +- 83 files changed, 1750 insertions(+), 242 deletions(-) create mode 100644 src/apps/icon-o-matic/generic/support/Referenceable.cpp create mode 100644 src/apps/icon-o-matic/shape/commands/AddPathsCommand.cpp create mode 100644 src/apps/icon-o-matic/shape/commands/AddPathsCommand.h create mode 100644 src/apps/icon-o-matic/shape/commands/AddShapesCommand.cpp create mode 100644 src/apps/icon-o-matic/shape/commands/AddShapesCommand.h create mode 100644 src/apps/icon-o-matic/shape/commands/RemovePathsCommand.cpp create mode 100644 src/apps/icon-o-matic/shape/commands/RemovePathsCommand.h create mode 100644 src/apps/icon-o-matic/shape/commands/UnassignPathCommand.cpp create mode 100644 src/apps/icon-o-matic/shape/commands/UnassignPathCommand.h create mode 100644 src/apps/icon-o-matic/style/AddStylesCommand.cpp create mode 100644 src/apps/icon-o-matic/style/AddStylesCommand.h create mode 100644 src/apps/icon-o-matic/style/SetColorCommand.cpp create mode 100644 src/apps/icon-o-matic/style/SetColorCommand.h create mode 100644 src/apps/icon-o-matic/transformable/TransformObjectsCommand.cpp create mode 100644 src/apps/icon-o-matic/transformable/TransformObjectsCommand.h diff --git a/src/apps/icon-o-matic/IconEditorApp.cpp b/src/apps/icon-o-matic/IconEditorApp.cpp index 548f8049a3..23384825cf 100644 --- a/src/apps/icon-o-matic/IconEditorApp.cpp +++ b/src/apps/icon-o-matic/IconEditorApp.cpp @@ -28,10 +28,12 @@ IconEditorApp::IconEditorApp() // destructor IconEditorApp::~IconEditorApp() { +printf("~IconEditorApp() - deleting document\n"); // NOTE: it is important that the GUI has been deleted // at this point, so that all the listener/observer // stuff is properly detached delete fDocument; +printf("~IconEditorApp() - done\n"); } // #pragma mark - diff --git a/src/apps/icon-o-matic/Jamfile b/src/apps/icon-o-matic/Jamfile index 8513ca5dd8..2636299573 100644 --- a/src/apps/icon-o-matic/Jamfile +++ b/src/apps/icon-o-matic/Jamfile @@ -105,6 +105,7 @@ Application Icon-O-Matic : Selectable.cpp Selection.cpp # generic/support + Referenceable.cpp RWLocker.cpp support.cpp support_ui.cpp @@ -124,18 +125,24 @@ Application Icon-O-Matic : ShapeContainer.cpp VectorPath.cpp # shape/commands + AddPathsCommand.cpp AddPointCommand.cpp + AddShapesCommand.cpp ChangePointCommand.cpp InsertPointCommand.cpp MoveShapesCommand.cpp MoveTransformersCommand.cpp PathCommand.cpp + RemovePathsCommand.cpp RemovePointsCommand.cpp RemoveShapesCommand.cpp RemoveTransformersCommand.cpp + UnassignPathCommand.cpp # style + AddStylesCommand.cpp CurrentColor.cpp Gradient.cpp + SetColorCommand.cpp SetGradientCommand.cpp Style.cpp StyleManager.cpp @@ -144,6 +151,7 @@ Application Icon-O-Matic : Transformable.cpp TransformBox.cpp TransformBoxStates.cpp + TransformObjectsCommand.cpp TransformCommand.cpp TransformShapesBox.cpp # transformer diff --git a/src/apps/icon-o-matic/MainWindow.cpp b/src/apps/icon-o-matic/MainWindow.cpp index 6c19e18cc7..32868f2904 100644 --- a/src/apps/icon-o-matic/MainWindow.cpp +++ b/src/apps/icon-o-matic/MainWindow.cpp @@ -8,6 +8,7 @@ #include "MainWindow.h" +#include #include #include @@ -16,6 +17,9 @@ #include #include +#include "AddPathsCommand.h" +#include "AddShapesCommand.h" +#include "AddStylesCommand.h" #include "Document.h" #include "CanvasView.h" #include "CommandStack.h" @@ -47,6 +51,8 @@ #include "StyleManager.h" #include "VectorPath.h" +using std::nothrow; + enum { MSG_UNDO = 'undo', MSG_REDO = 'redo', @@ -98,44 +104,62 @@ MainWindow::MessageReceived(BMessage* message) fDocument->CommandStack()->Redo(); break; -// TODO: use an AddPathCommand and listen to -// selection in CanvasView to add a manipulator +// TODO: listen to selection in CanvasView to add a manipulator case MSG_NEW_PATH: { - VectorPath* path = new VectorPath(); - fDocument->Icon()->Paths()->AddPath(path); + VectorPath* path = new (nothrow) VectorPath(); + VectorPath* paths[1]; + paths[0] = path; + PathContainer* container = fDocument->Icon()->Paths(); + AddPathsCommand* command = new (nothrow) AddPathsCommand( + container, paths, 1, true, + container->CountPaths()); + fDocument->CommandStack()->Perform(command); break; } case MSG_PATH_SELECTED: { VectorPath* path; - if (message->FindPointer("path", (void**)&path) == B_OK) { - PathManipulator* pathManipulator = new PathManipulator(path); - fState->DeleteManipulators(); + if (message->FindPointer("path", (void**)&path) < B_OK) + path = NULL; + + fState->DeleteManipulators(); + if (path) { + PathManipulator* pathManipulator = new (nothrow) PathManipulator(path); fState->AddManipulator(pathManipulator); } 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); + Style* style = new (nothrow) Style(); + if (style) { + style->SetColor((rgb_color){ rand() % 255, + rand() % 255, + rand() % 255, + 255 }); + Style* styles[1]; + styles[0] = style; + StyleManager* container = StyleManager::Default(); + AddStylesCommand* command = new (nothrow) AddStylesCommand( + container, styles, 1, + container->CountStyles()); + fDocument->CommandStack()->Perform(command); + } break; } case MSG_STYLE_SELECTED: { Style* style; if (message->FindPointer("style", (void**)&style) < B_OK) style = NULL; - fSwatchGroup->SetCurrentStyle(style); fStyleView->SetStyle(style); break; } -// TODO: use an AddShapeCommand case MSG_NEW_SHAPE: { - Shape* shape = new Shape(StyleManager::Default()->StyleAt(0)); - fDocument->Icon()->Shapes()->AddShape(shape); + Shape* shape = new (nothrow) Shape(StyleManager::Default()->StyleAt(0)); + Shape* shapes[1]; + shapes[0] = shape; + AddShapesCommand* command = new (nothrow) AddShapesCommand( + fDocument->Icon()->Shapes(), shapes, 1, + fDocument->Icon()->Shapes()->CountShapes()); + fDocument->CommandStack()->Perform(command); break; } case MSG_SHAPE_SELECTED: { @@ -157,7 +181,7 @@ case MSG_SHAPE_SELECTED: { } if (selectedShapes.CountItems() > 0) { - TransformShapesBox* transformBox = new TransformShapesBox( + TransformShapesBox* transformBox = new (nothrow) TransformShapesBox( fCanvasView, (const Shape**)selectedShapes.Items(), selectedShapes.CountItems()); @@ -251,7 +275,7 @@ MainWindow::_Init() fPathListView->SetPathContainer(fDocument->Icon()->Paths()); fPathListView->SetShapeContainer(fDocument->Icon()->Shapes()); -// fPathListView->SetCommandStack(fDocument->CommandStack()); + fPathListView->SetCommandStack(fDocument->CommandStack()); fPathListView->SetSelection(fDocument->Selection()); fStyleListView->SetStyleManager(StyleManager::Default()); @@ -260,6 +284,7 @@ MainWindow::_Init() fStyleListView->SetSelection(fDocument->Selection()); fStyleView->SetCommandStack(fDocument->CommandStack()); + fStyleView->SetCurrentColor(CurrentColor::Default()); fShapeListView->SetShapeContainer(fDocument->Icon()->Shapes()); fShapeListView->SetCommandStack(fDocument->CommandStack()); @@ -290,11 +315,13 @@ MainWindow::_Init() fDocument->Icon()->Paths()->AddPath(path); Style* style1 = new Style(); + style1->SetName("Style White"); style1->SetColor((rgb_color){ 255, 255, 255, 255 }); StyleManager::Default()->AddStyle(style1); Style* style2 = new Style(); + style2->SetName("Style Gradient"); Gradient gradient(true); gradient.AddColor((rgb_color){ 255, 211, 6, 255 }, 0.0); gradient.AddColor((rgb_color){ 255, 238, 160, 255 }, 0.5); @@ -320,6 +347,7 @@ MainWindow::_Init() fDocument->Icon()->Shapes()->AddShape(shape); Style* style3 = new Style(); + style3->SetName("Style Red"); style3->SetColor((rgb_color){ 255, 0, 169,200 }); StyleManager::Default()->AddStyle(style3); @@ -579,13 +607,13 @@ MainWindow::_CreateMenuBar(BRect frame) editMenu->AddItem(fRedoMI); // Path - fPathMenu->AddItem(new BMenuItem("New", new BMessage(MSG_NEW_PATH))); + fPathMenu->AddItem(new BMenuItem("Add", new BMessage(MSG_NEW_PATH))); // Style - fStyleMenu->AddItem(new BMenuItem("New", new BMessage(MSG_NEW_STYLE))); + fStyleMenu->AddItem(new BMenuItem("Add", new BMessage(MSG_NEW_STYLE))); // Shape - fShapeMenu->AddItem(new BMenuItem("New", new BMessage(MSG_NEW_SHAPE))); + fShapeMenu->AddItem(new BMenuItem("Add", new BMessage(MSG_NEW_SHAPE))); // Transformer diff --git a/src/apps/icon-o-matic/NOTES b/src/apps/icon-o-matic/NOTES index fb531693d1..fbca9d983e 100644 --- a/src/apps/icon-o-matic/NOTES +++ b/src/apps/icon-o-matic/NOTES @@ -13,11 +13,10 @@ * "add points" mode is problematic when having multiple manipulators for different paths showing at the same time... + -> "add points" only available when one path is selected, otherwise + "select points" is used -* solve the problem of individual gradient transformation per shape - -> introduce "StyleInstance", a Shape would not reference a Style - directly but via a StyleInstance... this object can have additional - information like the gradient transformation +* solve the problem of individual gradient transformation per shape [done] * IconRenderer should construct a separate StyleManager and append the styles in the order of shapes, also adding styles multiple @@ -25,17 +24,16 @@ rendering uses the style index for z ordering) [done] * add more functionality to Transformer/VertexSource interface: - - (inverse) Transformation - - Cloning + - Cloning [done] * add more powerful listener interface to Shape (TransformerAdded()/Removed()...) [done] -* implement commands for the newly added editing features +* implement commands for the newly added editing features [done] -* built-in transformation for Gradient and Shape? +* built-in transformation for Gradient and Shape? [done for Shape] -* Transformation manipulator +* Transformation manipulator [done] --------- user interface diff --git a/src/apps/icon-o-matic/document/Document.cpp b/src/apps/icon-o-matic/document/Document.cpp index 5e38fff098..34cd39636d 100644 --- a/src/apps/icon-o-matic/document/Document.cpp +++ b/src/apps/icon-o-matic/document/Document.cpp @@ -25,18 +25,22 @@ Document::Document(const char* name) fCommandStack(new (nothrow) ::CommandStack()), fSelection(new (nothrow) ::Selection()), + fName(name), fRef(NULL) { - SetName(name); } // destructor Document::~Document() { - delete fIcon; delete fCommandStack; +printf("~Document() - fCommandStack deleted\n"); delete fSelection; +printf("~Document() - fSelection deleted\n"); + delete fIcon; +printf("~Document() - fIcon deleted\n"); delete fRef; +printf("~Document() - fRef deleted\n"); } // SetName diff --git a/src/apps/icon-o-matic/document/Icon.cpp b/src/apps/icon-o-matic/document/Icon.cpp index 4b6a42b033..2477469a84 100644 --- a/src/apps/icon-o-matic/document/Icon.cpp +++ b/src/apps/icon-o-matic/document/Icon.cpp @@ -9,6 +9,7 @@ #include "Icon.h" #include +#include #include "PathContainer.h" #include "Shape.h" diff --git a/src/apps/icon-o-matic/generic/gui/stateview/StateView.cpp b/src/apps/icon-o-matic/generic/gui/stateview/StateView.cpp index e339d94b8d..1350014408 100644 --- a/src/apps/icon-o-matic/generic/gui/stateview/StateView.cpp +++ b/src/apps/icon-o-matic/generic/gui/stateview/StateView.cpp @@ -15,6 +15,11 @@ #include "Command.h" #include "CommandStack.h" +// TODO: hack - somehow figure out of catching +// key events for a given control is ok +#include "GradientControl.h" +#include "ListViews.h" +// #include "RWLocker.h" @@ -33,8 +38,12 @@ class EventFilter : public BMessageFilter { filter_result result = B_DISPATCH_MESSAGE; switch (message->what) { case B_KEY_DOWN: { - if (dynamic_cast(*target)) - break; +if (dynamic_cast(*target)) + break; +if (dynamic_cast(*target)) + break; +if (dynamic_cast(*target)) + break; uint32 key; uint32 modifiers; if (message->FindInt32("raw_char", (int32*)&key) >= B_OK @@ -44,8 +53,12 @@ class EventFilter : public BMessageFilter { break; } case B_KEY_UP: { - if (dynamic_cast(*target)) - break; +if (dynamic_cast(*target)) + break; +if (dynamic_cast(*target)) + break; +if (dynamic_cast(*target)) + break; uint32 key; uint32 modifiers; if (message->FindInt32("raw_char", (int32*)&key) >= B_OK diff --git a/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.cpp b/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.cpp index e3587b1629..2a7ffc054e 100644 --- a/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.cpp +++ b/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.cpp @@ -45,6 +45,9 @@ name_for_id(int32 id) case PROPERTY_MITER_LIMIT: name = "Miter Limit"; break; + case PROPERTY_STROKE_SHORTEN: + name = "Shorten"; + break; case PROPERTY_CLOSED: name = "Closed"; diff --git a/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.h b/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.h index 7465d21ef3..51d355d630 100644 --- a/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.h +++ b/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.h @@ -23,6 +23,7 @@ enum { PROPERTY_CAP_MODE = 'cpmd', PROPERTY_JOIN_MODE = 'jnmd', PROPERTY_MITER_LIMIT = 'mtlm', + PROPERTY_STROKE_SHORTEN = 'srtn', PROPERTY_CLOSED = 'clsd', diff --git a/src/apps/icon-o-matic/generic/property/PropertyObject.cpp b/src/apps/icon-o-matic/generic/property/PropertyObject.cpp index 9c2e23914b..98467acb32 100644 --- a/src/apps/icon-o-matic/generic/property/PropertyObject.cpp +++ b/src/apps/icon-o-matic/generic/property/PropertyObject.cpp @@ -166,6 +166,13 @@ PropertyObject::FindProperty(uint32 propertyID) const return NULL; } +//HasProperty +bool +PropertyObject::HasProperty(Property* property) const +{ + return fProperties.HasItem((void*)property); +} + // ContainsSameProperties bool PropertyObject::ContainsSameProperties(const PropertyObject& other) const diff --git a/src/apps/icon-o-matic/generic/property/PropertyObject.h b/src/apps/icon-o-matic/generic/property/PropertyObject.h index 312243ec4e..549148823c 100644 --- a/src/apps/icon-o-matic/generic/property/PropertyObject.h +++ b/src/apps/icon-o-matic/generic/property/PropertyObject.h @@ -31,6 +31,7 @@ class PropertyObject : public Observable { int32 CountProperties() const; Property* FindProperty(uint32 propertyID) const; + bool HasProperty(Property* property) const; bool ContainsSameProperties( const PropertyObject& other) const; diff --git a/src/apps/icon-o-matic/generic/property/view/PropertyListView.cpp b/src/apps/icon-o-matic/generic/property/view/PropertyListView.cpp index 51f7d6fb97..71af685324 100644 --- a/src/apps/icon-o-matic/generic/property/view/PropertyListView.cpp +++ b/src/apps/icon-o-matic/generic/property/view/PropertyListView.cpp @@ -468,8 +468,13 @@ PropertyListView::UpdateObject(uint32 propertyID) if (previous && current) { // call hook function PropertyChanged(previous, current); - // update saved property - previous->SetValue(current); + // update saved property if it is still contained + // in the saved properties (if not, the notification + // mechanism has caused to update the properties + // and "previous" and "current" are toast) + if (fSavedProperties->HasProperty(previous) + && fPropertyObject->HasProperty(current)) + previous->SetValue(current); } } diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/BoolValueView.cpp b/src/apps/icon-o-matic/generic/property/view/specific_properties/BoolValueView.cpp index 75b798353a..67961aa37b 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/BoolValueView.cpp +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/BoolValueView.cpp @@ -144,7 +144,7 @@ BoolValueView::SetEnabled(bool enabled) } } -// SetToProperty +// AdoptProperty bool BoolValueView::AdoptProperty(Property* property) { @@ -160,3 +160,10 @@ BoolValueView::AdoptProperty(Property* property) return false; } +// GetProperty +Property* +BoolValueView::GetProperty() const +{ + return fProperty; +} + diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/BoolValueView.h b/src/apps/icon-o-matic/generic/property/view/specific_properties/BoolValueView.h index 5ef9767190..313375cc1d 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/BoolValueView.h +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/BoolValueView.h @@ -30,8 +30,7 @@ class BoolValueView : public PropertyEditorView { virtual void SetEnabled(bool enabled); virtual bool AdoptProperty(Property* property); - virtual Property* GetProperty() const - { return fProperty; } + virtual Property* GetProperty() const; private: void _ToggleValue(); diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/ColorValueView.cpp b/src/apps/icon-o-matic/generic/property/view/specific_properties/ColorValueView.cpp index 66fda1d72f..240a5f81c8 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/ColorValueView.cpp +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/ColorValueView.cpp @@ -116,8 +116,7 @@ ColorValueView::IsFocused() const return fSwatchView->IsFocus(); } - -// SetToProperty +// AdoptProperty bool ColorValueView::AdoptProperty(Property* property) { @@ -133,3 +132,13 @@ ColorValueView::AdoptProperty(Property* property) } return false; } + +// GetProperty +Property* +ColorValueView::GetProperty() const +{ + return fProperty; +} + + + diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/ColorValueView.h b/src/apps/icon-o-matic/generic/property/view/specific_properties/ColorValueView.h index 63d8778243..e7684d1e93 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/ColorValueView.h +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/ColorValueView.h @@ -32,8 +32,7 @@ class ColorValueView : public PropertyEditorView { virtual bool IsFocused() const; virtual bool AdoptProperty(Property* property); - virtual Property* GetProperty() const - { return fProperty; } + virtual Property* GetProperty() const; protected: ColorProperty* fProperty; diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/FloatValueView.cpp b/src/apps/icon-o-matic/generic/property/view/specific_properties/FloatValueView.cpp index ef2b6b67c0..8d8763f9c3 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/FloatValueView.cpp +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/FloatValueView.cpp @@ -65,3 +65,13 @@ FloatValueView::AdoptProperty(Property* property) } return false; } + +// GetProperty +Property* +FloatValueView::GetProperty() const +{ + return fProperty; +} + + + diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/FloatValueView.h b/src/apps/icon-o-matic/generic/property/view/specific_properties/FloatValueView.h index 481433436c..a16ee0b2d3 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/FloatValueView.h +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/FloatValueView.h @@ -26,8 +26,7 @@ class FloatValueView : public TextInputValueView { virtual void ValueChanged(); virtual bool AdoptProperty(Property* property); - virtual Property* GetProperty() const - { return fProperty; } + virtual Property* GetProperty() const; private: FloatProperty* fProperty; diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/IconValueView.cpp b/src/apps/icon-o-matic/generic/property/view/specific_properties/IconValueView.cpp index a07abef665..e67ce8c921 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/IconValueView.cpp +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/IconValueView.cpp @@ -88,6 +88,13 @@ IconValueView::AdoptProperty(Property* property) return false; } +// GetProperty +Property* +IconValueView::GetProperty() const +{ + return fProperty; +} + // #pragma mark - // SetIcon diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/IconValueView.h b/src/apps/icon-o-matic/generic/property/view/specific_properties/IconValueView.h index b97d898f05..5f4cdb98e6 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/IconValueView.h +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/IconValueView.h @@ -26,8 +26,7 @@ class IconValueView : public PropertyEditorView { virtual void SetEnabled(bool enabled); virtual bool AdoptProperty(Property* property); - virtual Property* GetProperty() const - { return fProperty; } + virtual Property* GetProperty() const; // IconValueView status_t SetIcon(const unsigned char* bitsFromQuickRes, diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/Int64ValueView.cpp b/src/apps/icon-o-matic/generic/property/view/specific_properties/Int64ValueView.cpp index c6d8e3ee1f..85c411b86b 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/Int64ValueView.cpp +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/Int64ValueView.cpp @@ -69,3 +69,10 @@ Int64ValueView::AdoptProperty(Property* property) return false; } +// GetProperty +Property* +Int64ValueView::GetProperty() const +{ + return fProperty; +} + diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/Int64ValueView.h b/src/apps/icon-o-matic/generic/property/view/specific_properties/Int64ValueView.h index 44dd3457ac..6eec85e7d7 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/Int64ValueView.h +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/Int64ValueView.h @@ -26,8 +26,7 @@ class Int64ValueView : public TextInputValueView { virtual void ValueChanged(); virtual bool AdoptProperty(Property* property); - virtual Property* GetProperty() const - { return fProperty; } + virtual Property* GetProperty() const; private: Int64Property* fProperty; diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/IntValueView.cpp b/src/apps/icon-o-matic/generic/property/view/specific_properties/IntValueView.cpp index 6c6de21c33..de49e08b51 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/IntValueView.cpp +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/IntValueView.cpp @@ -66,3 +66,10 @@ IntValueView::AdoptProperty(Property* property) return false; } +// GetProperty +Property* +IntValueView::GetProperty() const +{ + return fProperty; +} + diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/IntValueView.h b/src/apps/icon-o-matic/generic/property/view/specific_properties/IntValueView.h index 5257d75c1f..f9a4b8e730 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/IntValueView.h +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/IntValueView.h @@ -26,8 +26,7 @@ class IntValueView : public TextInputValueView { virtual void ValueChanged(); virtual bool AdoptProperty(Property* property); - virtual Property* GetProperty() const - { return fProperty; } + virtual Property* GetProperty() const; private: IntProperty* fProperty; diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/OptionValueView.cpp b/src/apps/icon-o-matic/generic/property/view/specific_properties/OptionValueView.cpp index 0abea905fa..0e6626229a 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/OptionValueView.cpp +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/OptionValueView.cpp @@ -230,3 +230,10 @@ OptionValueView::AdoptProperty(Property* property) return false; } +// GetProperty +Property* +OptionValueView::GetProperty() const +{ + return fProperty; +} + diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/OptionValueView.h b/src/apps/icon-o-matic/generic/property/view/specific_properties/OptionValueView.h index c9b12c3fea..5cbc068a8e 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/OptionValueView.h +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/OptionValueView.h @@ -34,8 +34,7 @@ class OptionValueView : public PropertyEditorView { virtual void ValueChanged(); virtual bool AdoptProperty(Property* property); - virtual Property* GetProperty() const - { return fProperty; } + virtual Property* GetProperty() const; private: OptionProperty* fProperty; diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/StringValueView.cpp b/src/apps/icon-o-matic/generic/property/view/specific_properties/StringValueView.cpp index cc3dfba6d0..204716d520 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/StringValueView.cpp +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/StringValueView.cpp @@ -65,3 +65,10 @@ StringValueView::AdoptProperty(Property* property) } return false; } + +// GetProperty +Property* +StringValueView::GetProperty() const +{ + return fProperty; +} diff --git a/src/apps/icon-o-matic/generic/property/view/specific_properties/StringValueView.h b/src/apps/icon-o-matic/generic/property/view/specific_properties/StringValueView.h index fb85bf1f41..c36b286760 100644 --- a/src/apps/icon-o-matic/generic/property/view/specific_properties/StringValueView.h +++ b/src/apps/icon-o-matic/generic/property/view/specific_properties/StringValueView.h @@ -27,8 +27,7 @@ class StringValueView : public TextInputValueView { virtual void ValueChanged(); virtual bool AdoptProperty(Property* property); - virtual Property* GetProperty() const - { return fProperty; } + virtual Property* GetProperty() const; private: StringProperty* fProperty; diff --git a/src/apps/icon-o-matic/generic/support/Referenceable.cpp b/src/apps/icon-o-matic/generic/support/Referenceable.cpp new file mode 100644 index 0000000000..3db27219da --- /dev/null +++ b/src/apps/icon-o-matic/generic/support/Referenceable.cpp @@ -0,0 +1,77 @@ +/* + * Copyright 2001-2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * DarkWyrm + * Axel Dörfler, axeld@pinc-software.de + * Stephan Aßmus + */ + +#include "Referenceable.h" + +#define TRACE 1 +#define ICON 1 + +#if TRACE +#include +#include + +#if ICON +#include "IconObject.h" +#endif +#endif + +// constructor +Referenceable::Referenceable() + : fReferenceCount(1) +{ +} + +// destructor +Referenceable::~Referenceable() +{ +} + +// Acquire +void +Referenceable::Acquire() +{ + atomic_add(&fReferenceCount, 1); +} + +// Release +bool +Referenceable::Release() +{ +#if TRACE + int32 old = atomic_add(&fReferenceCount, -1); +//#if ICON +// if (old > 1) { +//IconObject* object = dynamic_cast(this); +//printf("Referenceable::Release() - %s: %ld\n", +// object ? object->Name() : "unkown", fReferenceCount); +// } else +//#endif + if (old == 1) { +#if ICON +IconObject* object = dynamic_cast(this); +printf("Referenceable::Release() - deleting %s\n", + object ? object->Name() : "unkown"); +#else +printf("Referenceable::Release() - deleting\n"); +#endif + delete this; + return true; + } else if (old < 1) + debugger("Referenceable::Release() - already deleted"); +#else + if (atomic_add(&fReferenceCount, -1) == 1) { + delete this; + return true; + } +#endif + + return false; +} + diff --git a/src/apps/icon-o-matic/generic/support/Referenceable.h b/src/apps/icon-o-matic/generic/support/Referenceable.h index 26aa0955c5..00cdf55438 100644 --- a/src/apps/icon-o-matic/generic/support/Referenceable.h +++ b/src/apps/icon-o-matic/generic/support/Referenceable.h @@ -14,36 +14,14 @@ class Referenceable { public: - Referenceable() - : fReferenceCount(1) - {} - virtual ~Referenceable() - {} + Referenceable(); + virtual ~Referenceable(); - inline void Acquire(); - inline bool Release(); + void Acquire(); + 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/gui/GradientControl.cpp b/src/apps/icon-o-matic/gui/GradientControl.cpp index c286f72348..32ac8d4f05 100644 --- a/src/apps/icon-o-matic/gui/GradientControl.cpp +++ b/src/apps/icon-o-matic/gui/GradientControl.cpp @@ -87,9 +87,10 @@ GradientControl::MakeFocus(bool focus) if (focus != IsFocus()) { _UpdateCurrentColor(); Invalidate(); - // keep the window informed when the focus of this object changes - if (BWindow* window = Window()) - window->PostMessage(MSG_GRADIENT_CONTROL_FOCUS_CHANGED); + if (fTarget) { + if (BLooper* looper = fTarget->Looper()) + looper->PostMessage(MSG_GRADIENT_CONTROL_FOCUS_CHANGED, fTarget); + } } BView::MakeFocus(focus); } @@ -125,9 +126,9 @@ GradientControl::MouseDown(BPoint where) rgb_color color; uint8* bits = temp; bits += 4 * (uint32)((width - 1) * offset); - color.red = bits[2]; + color.red = bits[0]; color.green = bits[1]; - color.blue = bits[0]; + color.blue = bits[2]; color.alpha = bits[3]; fCurrentStepIndex = fGradient->AddColor(color, offset); fDraggingStepIndex = -1; @@ -625,6 +626,7 @@ void GradientControl::_UpdateCurrentColor() const { if (!fMessage || !fTarget || !fTarget->Looper()) + return; // set the CanvasView current color if (color_step* step = fGradient->ColorAt(fCurrentStepIndex)) { BMessage message(*fMessage); diff --git a/src/apps/icon-o-matic/gui/PathListView.cpp b/src/apps/icon-o-matic/gui/PathListView.cpp index fe60c543b6..1f5edb554d 100644 --- a/src/apps/icon-o-matic/gui/PathListView.cpp +++ b/src/apps/icon-o-matic/gui/PathListView.cpp @@ -16,11 +16,15 @@ #include #include -#include "VectorPath.h" +#include "AddPathsCommand.h" +#include "CommandStack.h" #include "Observer.h" +#include "RemovePathsCommand.h" #include "Shape.h" #include "ShapeContainer.h" #include "Selection.h" +#include "UnassignPathCommand.h" +#include "VectorPath.h" static const float kMarkWidth = 14.0; static const float kBorderOffset = 3.0; @@ -258,9 +262,9 @@ PathListView::SelectionChanged() PathListItem* item = dynamic_cast(ItemAt(CurrentSelection(0))); - if (item && fMessage) { + if (fMessage) { BMessage message(*fMessage); - message.AddPointer("path", (void*)item->path); + message.AddPointer("path", item ? (void*)item->path : NULL); Invoke(&message); } @@ -292,23 +296,21 @@ PathListView::MouseDown(BPoint where) + kBorderOffset + kMarkWidth + kTextOffset / 2.0; VectorPath* path = item->path; - if (itemFrame.Contains(where)) { + if (itemFrame.Contains(where) && fCommandStack) { // add or remove the path to the shape -// TODO: code these commands... -// Command* command; -// if (fCurrentShape->Paths()->HasPath(path)) { -// command = new RemovePathFromShapeCommand( -// fCurrentShape, path); -// } else { -// command = new AddPathToShapeCommand( -// fCurrentShape, path); -// } -// fCommandStack->Perform(command); -if (fCurrentShape->Paths()->HasPath(path)) { - fCurrentShape->Paths()->RemovePath(path); -} else { - fCurrentShape->Paths()->AddPath(path); -} + ::Command* command; + if (fCurrentShape->Paths()->HasPath(path)) { + command = new UnassignPathCommand( + fCurrentShape, path); + } else { + VectorPath* paths[1]; + paths[0] = path; + command = new AddPathsCommand( + fCurrentShape->Paths(), + paths, 1, false, + fCurrentShape->Paths()->CountPaths()); + } + fCommandStack->Perform(command); handled = true; } } @@ -353,13 +355,31 @@ PathListView::MoveItems(BList& items, int32 toIndex) void PathListView::CopyItems(BList& items, int32 toIndex) { + // TODO: allow to copy path } // RemoveItemList void -PathListView::RemoveItemList(BList& indices) +PathListView::RemoveItemList(BList& items) { - // TODO: allow removing items + if (!fCommandStack || !fPathContainer) + return; + + int32 count = items.CountItems(); + VectorPath* paths[count]; + for (int32 i = 0; i < count; i++) { + PathListItem* item = dynamic_cast( + (SimpleItem*)items.ItemAtFast(i)); + if (item) + paths[i] = item->path; + else + paths[i] = NULL; + } + + RemovePathsCommand* command + = new (nothrow) RemovePathsCommand(fPathContainer, + paths, count); + fCommandStack->Perform(command); } // CloneItem @@ -469,6 +489,13 @@ PathListView::SetSelection(Selection* selection) fSelection = selection; } +// SetCommandStack +void +PathListView::SetCommandStack(CommandStack* stack) +{ + fCommandStack = stack; +} + // SetCurrentShape void PathListView::SetCurrentShape(Shape* shape) diff --git a/src/apps/icon-o-matic/gui/PathListView.h b/src/apps/icon-o-matic/gui/PathListView.h index e21c757ed0..3aa91ceebc 100644 --- a/src/apps/icon-o-matic/gui/PathListView.h +++ b/src/apps/icon-o-matic/gui/PathListView.h @@ -43,7 +43,7 @@ class PathListView : public SimpleListView, virtual void MoveItems(BList& items, int32 toIndex); virtual void CopyItems(BList& items, int32 toIndex); - virtual void RemoveItemList(BList& indices); + virtual void RemoveItemList(BList& items); virtual BListItem* CloneItem(int32 atIndex) const; @@ -55,6 +55,7 @@ class PathListView : public SimpleListView, void SetPathContainer(PathContainer* container); void SetShapeContainer(ShapeContainer* container); void SetSelection(Selection* selection); + void SetCommandStack(CommandStack* stack); void SetCurrentShape(Shape* shape); Shape* CurrentShape() const diff --git a/src/apps/icon-o-matic/gui/ShapeListView.cpp b/src/apps/icon-o-matic/gui/ShapeListView.cpp index f5cab0e9c1..68359704b4 100644 --- a/src/apps/icon-o-matic/gui/ShapeListView.cpp +++ b/src/apps/icon-o-matic/gui/ShapeListView.cpp @@ -17,6 +17,7 @@ #include #include +#include "AddShapesCommand.h" #include "CommandStack.h" #include "MoveShapesCommand.h" #include "RemoveShapesCommand.h" @@ -117,8 +118,6 @@ ShapeListView::~ShapeListView() void ShapeListView::SelectionChanged() { - // TODO: single selection versus multiple selection - ShapeListItem* item = dynamic_cast(ItemAt(CurrentSelection(0))); if (fMessage) { BMessage message(*fMessage); @@ -130,10 +129,16 @@ ShapeListView::SelectionChanged() if (!fSelection) return; - if (item) - fSelection->Select(item->shape); - else + if (!item) { fSelection->DeselectAll(); + return; + } + + for (int32 i = 0; + (item = dynamic_cast(ItemAt(CurrentSelection(i)))); + i++) { + fSelection->Select(item->shape, i > 0); + } } // MessageReceived @@ -220,19 +225,41 @@ ShapeListView::MoveItems(BList& items, int32 toIndex) void ShapeListView::CopyItems(BList& items, int32 toIndex) { - MoveItems(items, toIndex); - // TODO: allow copying items + if (!fCommandStack || !fShapeContainer) + return; + + int32 count = items.CountItems(); + Shape* shapes[count]; + + for (int32 i = 0; i < count; i++) { + ShapeListItem* item + = dynamic_cast((BListItem*)items.ItemAtFast(i)); + shapes[i] = item ? new (nothrow) Shape(*item->shape) : NULL; + } + + AddShapesCommand* command + = new (nothrow) AddShapesCommand(fShapeContainer, + shapes, count, toIndex); + if (!command) { + for (int32 i = 0; i < count; i++) + delete shapes[i]; + return; + } + + fCommandStack->Perform(command); } // RemoveItemList void -ShapeListView::RemoveItemList(BList& indexList) +ShapeListView::RemoveItemList(BList& items) { if (!fCommandStack || !fShapeContainer) return; - int32 count = indexList.CountItems(); - const int32* indices = (int32*)indexList.Items(); + int32 count = items.CountItems(); + int32 indices[count]; + for (int32 i = 0; i < count; i++) + indices[i] = IndexOf((SimpleItem*)items.ItemAtFast(i)); RemoveShapesCommand* command = new (nothrow) RemoveShapesCommand(fShapeContainer, @@ -264,8 +291,6 @@ ShapeListView::ShapeAdded(Shape* shape, int32 index) if (!LockLooper()) return; - // NOTE: shapes are always added at the end - // of the list, so the sorting is synced... _AddShape(shape, index); UnlockLooper(); diff --git a/src/apps/icon-o-matic/gui/ShapeListView.h b/src/apps/icon-o-matic/gui/ShapeListView.h index cef7e76bed..649eeef7c6 100644 --- a/src/apps/icon-o-matic/gui/ShapeListView.h +++ b/src/apps/icon-o-matic/gui/ShapeListView.h @@ -39,7 +39,7 @@ class ShapeListView : public SimpleListView, virtual void MoveItems(BList& items, int32 toIndex); virtual void CopyItems(BList& items, int32 toIndex); - virtual void RemoveItemList(BList& indices); + virtual void RemoveItemList(BList& items); virtual BListItem* CloneItem(int32 atIndex) const; diff --git a/src/apps/icon-o-matic/gui/StyleListView.cpp b/src/apps/icon-o-matic/gui/StyleListView.cpp index 5d70096086..978aa6cbc7 100644 --- a/src/apps/icon-o-matic/gui/StyleListView.cpp +++ b/src/apps/icon-o-matic/gui/StyleListView.cpp @@ -347,7 +347,7 @@ StyleListView::CopyItems(BList& items, int32 toIndex) // RemoveItemList void -StyleListView::RemoveItemList(BList& indices) +StyleListView::RemoveItemList(BList& items) { // TODO: allow removing items } diff --git a/src/apps/icon-o-matic/gui/StyleListView.h b/src/apps/icon-o-matic/gui/StyleListView.h index 74d705290f..e01add6055 100644 --- a/src/apps/icon-o-matic/gui/StyleListView.h +++ b/src/apps/icon-o-matic/gui/StyleListView.h @@ -43,7 +43,7 @@ class StyleListView : public SimpleListView, virtual void MoveItems(BList& items, int32 toIndex); virtual void CopyItems(BList& items, int32 toIndex); - virtual void RemoveItemList(BList& indices); + virtual void RemoveItemList(BList& items); virtual BListItem* CloneItem(int32 atIndex) const; diff --git a/src/apps/icon-o-matic/gui/StyleView.cpp b/src/apps/icon-o-matic/gui/StyleView.cpp index bd0d270b9c..57d5237d1f 100644 --- a/src/apps/icon-o-matic/gui/StyleView.cpp +++ b/src/apps/icon-o-matic/gui/StyleView.cpp @@ -16,8 +16,10 @@ #include #include "CommandStack.h" +#include "CurrentColor.h" #include "Gradient.h" #include "GradientControl.h" +#include "SetColorCommand.h" #include "SetGradientCommand.h" #include "Style.h" @@ -37,6 +39,7 @@ enum { StyleView::StyleView(BRect frame) : BView(frame, "style view", B_FOLLOW_LEFT | B_FOLLOW_TOP, 0), fCommandStack(NULL), + fCurrentColor(NULL), fStyle(NULL), fGradient(NULL) { @@ -112,6 +115,7 @@ StyleView::StyleView(BRect frame) StyleView::~StyleView() { SetStyle(NULL); + SetCurrentColor(NULL); fGradientControl->Gradient()->RemoveObserver(this); } @@ -140,6 +144,10 @@ StyleView::MessageReceived(BMessage* message) _SetGradientType(type); break; } + case MSG_SET_COLOR: + case MSG_GRADIENT_CONTROL_FOCUS_CHANGED: + _TransferGradientStopColor(); + break; default: BView::MessageReceived(message); @@ -169,6 +177,8 @@ StyleView::ObjectChanged(const Observable* object) } else { *fGradient = *controlGradient; } + // transfer the current gradient color to the current color + _TransferGradientStopColor(); } } else if (object == fGradient) { if (*fGradient != *controlGradient) { @@ -177,7 +187,12 @@ StyleView::ObjectChanged(const Observable* object) } } else if (object == fStyle) { // maybe the gradient was added or removed + // or the color changed _SetGradient(fStyle->Gradient()); + if (fCurrentColor && !fStyle->Gradient()) + fCurrentColor->SetColor(fStyle->Color()); + } else if (object == fCurrentColor) { + _AdoptCurrentColor(fCurrentColor->Color()); } } @@ -190,15 +205,21 @@ StyleView::SetStyle(Style* style) if (fStyle == style) return; - if (fStyle) + if (fStyle) { fStyle->RemoveObserver(this); + fStyle->Release(); + } fStyle = style; Gradient* gradient = NULL; if (fStyle) { + fStyle->Acquire(); fStyle->AddObserver(this); gradient = fStyle->Gradient(); + + if (fCurrentColor && !gradient) + fCurrentColor->SetColor(fStyle->Color()); } _SetGradient(gradient); @@ -211,6 +232,22 @@ StyleView::SetCommandStack(CommandStack* stack) fCommandStack = stack; } +// SetCurrentColor +void +StyleView::SetCurrentColor(CurrentColor* color) +{ + if (fCurrentColor == color) + return; + + if (fCurrentColor) + fCurrentColor->RemoveObserver(this); + + fCurrentColor = color; + + if (fCurrentColor) + fCurrentColor->AddObserver(this); +} + // #pragma mark - // _SetGradient @@ -287,3 +324,37 @@ StyleView::_SetGradientType(int32 type) { fGradientControl->Gradient()->SetType((gradient_type)type); } + +// _AdoptCurrentColor +void +StyleView::_AdoptCurrentColor(rgb_color color) +{ + if (!fStyle) + return; + + if (fGradient) { + // set the focused gradient color stop + if (fGradientControl->IsFocus()) { + fGradientControl->SetCurrentStop(color); + } + } else { + if (fCommandStack) { + fCommandStack->Perform( + new (nothrow) SetColorCommand(fStyle, color)); + } else { + fStyle->SetColor(color); + } + } +} + +// _TransferGradientStopColor +void +StyleView::_TransferGradientStopColor() +{ + if (fCurrentColor && fGradientControl->IsFocus()) { + rgb_color color; + if (fGradientControl->GetCurrentStop(&color)) + fCurrentColor->SetColor(color); + } +} + diff --git a/src/apps/icon-o-matic/gui/StyleView.h b/src/apps/icon-o-matic/gui/StyleView.h index 1d02353c31..6d353cc810 100644 --- a/src/apps/icon-o-matic/gui/StyleView.h +++ b/src/apps/icon-o-matic/gui/StyleView.h @@ -16,6 +16,7 @@ class BMenu; class BMenuField; class CommandStack; +class CurrentColor; class Gradient; class GradientControl; class Style; @@ -38,6 +39,7 @@ class StyleView : public BView, // StyleView void SetStyle(Style* style); void SetCommandStack(CommandStack* stack); + void SetCurrentColor(CurrentColor* color); private: void _SetGradient(Gradient* gradient); @@ -45,9 +47,12 @@ class StyleView : public BView, int32 type) const; void _SetStyleType(int32 type); void _SetGradientType(int32 type); + void _AdoptCurrentColor(rgb_color color); + void _TransferGradientStopColor(); CommandStack* fCommandStack; + CurrentColor* fCurrentColor; Style* fStyle; Gradient* fGradient; diff --git a/src/apps/icon-o-matic/gui/SwatchGroup.cpp b/src/apps/icon-o-matic/gui/SwatchGroup.cpp index 9fa180546f..77d6f9b4ae 100644 --- a/src/apps/icon-o-matic/gui/SwatchGroup.cpp +++ b/src/apps/icon-o-matic/gui/SwatchGroup.cpp @@ -19,7 +19,6 @@ #include "ColorSlider.h" #include "CurrentColor.h" #include "Group.h" -#include "Style.h" #include "SwatchView.h" enum { @@ -35,7 +34,6 @@ SwatchGroup::SwatchGroup(BRect frame) : BView(frame, "style view", B_FOLLOW_NONE, 0), fCurrentColor(NULL), - fCurrentStyle(NULL), fIgnoreNotifications(false), fColorPickerPanel(NULL), @@ -93,12 +91,15 @@ SwatchGroup::SwatchGroup(BRect frame) fBottomSwatchViews->ResizeToPreferred(); fBottomSwatchViews->SetResizingMode(B_FOLLOW_ALL); - fTopSwatchViews->MoveTo(30, 4); - fBottomSwatchViews->MoveTo(30, fTopSwatchViews->Frame().bottom + 1); + float paletteHeight = fBottomSwatchViews->Frame().Height() + + fTopSwatchViews->Frame().Height() + 1; + + fTopSwatchViews->MoveTo(paletteHeight + 2, 4); + fBottomSwatchViews->MoveTo(paletteHeight + 2, + fTopSwatchViews->Frame().bottom + 1); fCurrentColorSV->MoveTo(0, fTopSwatchViews->Frame().top); - fCurrentColorSV->ResizeTo(28, fBottomSwatchViews->Frame().bottom - - fTopSwatchViews->Frame().top); + fCurrentColorSV->ResizeTo(paletteHeight, paletteHeight); fCurrentColorSV->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_TOP); float width = fTopSwatchViews->Frame().right @@ -128,7 +129,6 @@ SwatchGroup::SwatchGroup(BRect frame) SwatchGroup::~SwatchGroup() { SetCurrentColor(NULL); - SetCurrentStyle(NULL); } // ObjectChanged @@ -147,10 +147,6 @@ SwatchGroup::ObjectChanged(const Observable* object) _SetColor(h, s, v); } - - if (fCurrentStyle && !fCurrentStyle->Gradient()) { - fCurrentStyle->SetColor(color); - } } } @@ -264,26 +260,6 @@ SwatchGroup::SetCurrentColor(CurrentColor* color) } } -// SetCurrentStyle -void -SwatchGroup::SetCurrentStyle(Style* style) -{ - if (fCurrentStyle == style) - return; - - if (fCurrentStyle) - fCurrentStyle->Release(); - - fCurrentStyle = style; - - if (fCurrentStyle) { - fCurrentStyle->Acquire(); - - if (fCurrentColor && !fCurrentStyle->Gradient()) - fCurrentColor->SetColor(fCurrentStyle->Color()); - } -} - // #pragma mark - // _SetColor diff --git a/src/apps/icon-o-matic/gui/SwatchGroup.h b/src/apps/icon-o-matic/gui/SwatchGroup.h index bdeaf7bf1e..b8a28612dc 100644 --- a/src/apps/icon-o-matic/gui/SwatchGroup.h +++ b/src/apps/icon-o-matic/gui/SwatchGroup.h @@ -20,7 +20,6 @@ class ColorPickerPanel; class ColorSlider; class CurrentColor; class Group; -class Style; class SwatchView; class SwatchGroup : public BView, @@ -38,7 +37,6 @@ class SwatchGroup : public BView, // SwatchGroup void SetCurrentColor(CurrentColor* color); - void SetCurrentStyle(Style* style); private: void _SetColor(rgb_color color); @@ -53,7 +51,6 @@ class SwatchGroup : public BView, Group* fBottomSwatchViews; CurrentColor* fCurrentColor; - Style* fCurrentStyle; bool fIgnoreNotifications; ColorPickerPanel* fColorPickerPanel; diff --git a/src/apps/icon-o-matic/gui/TransformerListView.cpp b/src/apps/icon-o-matic/gui/TransformerListView.cpp index 903f9c8efe..3d1174fd79 100644 --- a/src/apps/icon-o-matic/gui/TransformerListView.cpp +++ b/src/apps/icon-o-matic/gui/TransformerListView.cpp @@ -195,13 +195,15 @@ TransformerListView::CopyItems(BList& items, int32 toIndex) // RemoveItemList void -TransformerListView::RemoveItemList(BList& indexList) +TransformerListView::RemoveItemList(BList& items) { if (!fCommandStack || !fShape) return; - int32 count = indexList.CountItems(); - const int32* indices = (int32*)indexList.Items(); + int32 count = items.CountItems(); + int32 indices[count]; + for (int32 i = 0; i < count; i++) + indices[i] = IndexOf((SimpleItem*)items.ItemAtFast(i)); RemoveTransformersCommand* command = new (nothrow) RemoveTransformersCommand(fShape, diff --git a/src/apps/icon-o-matic/gui/TransformerListView.h b/src/apps/icon-o-matic/gui/TransformerListView.h index 87018a94fc..0117a9f99e 100644 --- a/src/apps/icon-o-matic/gui/TransformerListView.h +++ b/src/apps/icon-o-matic/gui/TransformerListView.h @@ -33,7 +33,7 @@ class TransformerListView : public SimpleListView, virtual void MoveItems(BList& items, int32 toIndex); virtual void CopyItems(BList& items, int32 toIndex); - virtual void RemoveItemList(BList& indices); + virtual void RemoveItemList(BList& items); virtual BListItem* CloneItem(int32 atIndex) const; diff --git a/src/apps/icon-o-matic/shape/PathContainer.cpp b/src/apps/icon-o-matic/shape/PathContainer.cpp index c5ae4934c3..4648f0d6d0 100644 --- a/src/apps/icon-o-matic/shape/PathContainer.cpp +++ b/src/apps/icon-o-matic/shape/PathContainer.cpp @@ -38,6 +38,7 @@ PathContainer::PathContainer(bool ownsPaths) // destructor PathContainer::~PathContainer() { +printf("PathContainer::~PathContainer()\n"); int32 count = fListeners.CountItems(); if (count > 0) { debugger("~PathContainer() - there are still" diff --git a/src/apps/icon-o-matic/shape/Shape.cpp b/src/apps/icon-o-matic/shape/Shape.cpp index ad0fae5306..9138b6c8c5 100644 --- a/src/apps/icon-o-matic/shape/Shape.cpp +++ b/src/apps/icon-o-matic/shape/Shape.cpp @@ -72,7 +72,16 @@ Shape::Shape(const Shape& other) } } } - // TODO: clone vertex transformers + // clone vertex transformers + int32 count = other.CountTransformers(); + for (int32 i = 0; i < count; i++) { + Transformer* original = other.TransformerAtFast(i); + Transformer* cloned = original->Clone(fPathSource); + if (!AddTransformer(cloned)) { + delete cloned; + break; + } + } SetStyle(other.fStyle); } @@ -80,6 +89,7 @@ Shape::Shape(const Shape& other) // destructor Shape::~Shape() { +printf("~Shape()\n"); int32 count = fTransformers.CountItems(); for (int32 i = 0; i < count; i++) { Transformer* t = (Transformer*)fTransformers.ItemAtFast(i); diff --git a/src/apps/icon-o-matic/shape/VectorPath.cpp b/src/apps/icon-o-matic/shape/VectorPath.cpp index f15b2e70a3..e17ee3fc1c 100644 --- a/src/apps/icon-o-matic/shape/VectorPath.cpp +++ b/src/apps/icon-o-matic/shape/VectorPath.cpp @@ -888,6 +888,20 @@ VectorPath::RemoveListener(PathListener* listener) return fListeners.RemoveItem((void*)listener); } +// CountListeners +int32 +VectorPath::CountListeners() const +{ + return fListeners.CountItems(); +} + +// ListenerAtFast +PathListener* +VectorPath::ListenerAtFast(int32 index) const +{ + return (PathListener*)fListeners.ItemAtFast(index); +} + // #pragma mark - // _SetPoint diff --git a/src/apps/icon-o-matic/shape/VectorPath.h b/src/apps/icon-o-matic/shape/VectorPath.h index b0a363f0ad..f19a6eb687 100644 --- a/src/apps/icon-o-matic/shape/VectorPath.h +++ b/src/apps/icon-o-matic/shape/VectorPath.h @@ -142,6 +142,9 @@ class VectorPath : public BArchivable, bool AddListener(PathListener* listener); bool RemoveListener(PathListener* listener); + int32 CountListeners() const; + PathListener* ListenerAtFast(int32 index) const; + private: BRect _Bounds() const; diff --git a/src/apps/icon-o-matic/shape/commands/AddPathsCommand.cpp b/src/apps/icon-o-matic/shape/commands/AddPathsCommand.cpp new file mode 100644 index 0000000000..e2a1439726 --- /dev/null +++ b/src/apps/icon-o-matic/shape/commands/AddPathsCommand.cpp @@ -0,0 +1,108 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#include "AddPathsCommand.h" + +#include +#include +#include + +#include "PathContainer.h" +#include "VectorPath.h" + +using std::nothrow; + +// constructor +AddPathsCommand::AddPathsCommand(PathContainer* container, + VectorPath** const paths, + int32 count, + bool ownsPaths, + int32 index) + : Command(), + fContainer(container), + fPaths(paths && count > 0 ? new (nothrow) VectorPath*[count] : NULL), + fCount(count), + fOwnsPaths(ownsPaths), + fIndex(index), + fPathsAdded(false) +{ + if (!fContainer || !fPaths) + return; + + memcpy(fPaths, paths, sizeof(VectorPath*) * fCount); +} + +// destructor +AddPathsCommand::~AddPathsCommand() +{ + if (fOwnsPaths && !fPathsAdded && fPaths) { + for (int32 i = 0; i < fCount; i++) + fPaths[i]->Release(); + } + delete[] fPaths; +} + +// InitCheck +status_t +AddPathsCommand::InitCheck() +{ + return fContainer && fPaths ? B_OK : B_NO_INIT; +} + +// Perform +status_t +AddPathsCommand::Perform() +{ + status_t ret = B_OK; + + // add shapes to container + int32 index = fIndex; + for (int32 i = 0; i < fCount; i++) { + if (fPaths[i] && !fContainer->AddPath(fPaths[i]/*, index*/)) { + ret = B_ERROR; + // roll back + for (int32 j = i - 1; j >= 0; j--) + fContainer->RemovePath(fPaths[j]); + break; + } + index++; + } + fPathsAdded = true; + + return ret; +} + +// Undo +status_t +AddPathsCommand::Undo() +{ + // remove shapes from container + for (int32 i = 0; i < fCount; i++) { + fContainer->RemovePath(fPaths[i]); + } + fPathsAdded = false; + + return B_OK; +} + +// GetName +void +AddPathsCommand::GetName(BString& name) +{ + if (fOwnsPaths) { + if (fCount > 1) + name << "Add Paths"; + else + name << "Add Path"; + } else { + if (fCount > 1) + name << "Assign Paths"; + else + name << "Assign Path"; + } +} diff --git a/src/apps/icon-o-matic/shape/commands/AddPathsCommand.h b/src/apps/icon-o-matic/shape/commands/AddPathsCommand.h new file mode 100644 index 0000000000..e7d3956fd1 --- /dev/null +++ b/src/apps/icon-o-matic/shape/commands/AddPathsCommand.h @@ -0,0 +1,43 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#ifndef ADD_PATHS_COMMAND_H +#define ADD_PATHS_COMMAND_H + +#include "Command.h" + +class VectorPath; +class PathContainer; + +class AddPathsCommand : public Command { + public: + AddPathsCommand( + PathContainer* container, + VectorPath** const paths, + int32 count, + bool ownsPaths, + int32 index); + virtual ~AddPathsCommand(); + + virtual status_t InitCheck(); + + virtual status_t Perform(); + virtual status_t Undo(); + + virtual void GetName(BString& name); + + private: + PathContainer* fContainer; + VectorPath** fPaths; + int32 fCount; + bool fOwnsPaths; + int32 fIndex; + bool fPathsAdded; +}; + +#endif // ADD_PATHS_COMMAND_H diff --git a/src/apps/icon-o-matic/shape/commands/AddShapesCommand.cpp b/src/apps/icon-o-matic/shape/commands/AddShapesCommand.cpp new file mode 100644 index 0000000000..9484ddbca4 --- /dev/null +++ b/src/apps/icon-o-matic/shape/commands/AddShapesCommand.cpp @@ -0,0 +1,99 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#include "AddShapesCommand.h" + +#include +#include +#include + +#include "ShapeContainer.h" +#include "Shape.h" + +using std::nothrow; + +// constructor +AddShapesCommand::AddShapesCommand(ShapeContainer* container, + Shape** const shapes, + int32 count, + int32 index) + : Command(), + fContainer(container), + fShapes(shapes && count > 0 ? new (nothrow) Shape*[count] : NULL), + fCount(count), + fIndex(index), + fShapesAdded(false) +{ + if (!fContainer || !fShapes) + return; + + memcpy(fShapes, shapes, sizeof(Shape*) * fCount); +} + +// destructor +AddShapesCommand::~AddShapesCommand() +{ + if (!fShapesAdded && fShapes) { + for (int32 i = 0; i < fCount; i++) + fShapes[i]->Release(); + } + delete[] fShapes; +} + +// InitCheck +status_t +AddShapesCommand::InitCheck() +{ + return fContainer && fShapes ? B_OK : B_NO_INIT; +} + +// Perform +status_t +AddShapesCommand::Perform() +{ + status_t ret = B_OK; + + // add shapes to container + int32 index = fIndex; + for (int32 i = 0; i < fCount; i++) { + if (fShapes[i] && !fContainer->AddShape(fShapes[i], index)) { + ret = B_ERROR; + // roll back + for (int32 j = i - 1; j >= 0; j--) + fContainer->RemoveShape(fShapes[j]); + break; + } + index++; + } + fShapesAdded = true; + + return ret; +} + +// Undo +status_t +AddShapesCommand::Undo() +{ + // remove shapes from container + for (int32 i = 0; i < fCount; i++) { + fContainer->RemoveShape(fShapes[i]); + } + fShapesAdded = false; + + return B_OK; +} + +// GetName +void +AddShapesCommand::GetName(BString& name) +{ + if (fCount > 1) + name << "Add Shapes"; + else + name << "Add Shape"; +} diff --git a/src/apps/icon-o-matic/shape/commands/AddShapesCommand.h b/src/apps/icon-o-matic/shape/commands/AddShapesCommand.h new file mode 100644 index 0000000000..d3fb8d871e --- /dev/null +++ b/src/apps/icon-o-matic/shape/commands/AddShapesCommand.h @@ -0,0 +1,41 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#ifndef ADD_SHAPES_COMMAND_H +#define ADD_SHAPES_COMMAND_H + +#include "Command.h" + +class Shape; +class ShapeContainer; + +class AddShapesCommand : public Command { + public: + AddShapesCommand( + ShapeContainer* container, + Shape** const shapes, + int32 count, + int32 index); + virtual ~AddShapesCommand(); + + virtual status_t InitCheck(); + + virtual status_t Perform(); + virtual status_t Undo(); + + virtual void GetName(BString& name); + + private: + ShapeContainer* fContainer; + Shape** fShapes; + int32 fCount; + int32 fIndex; + bool fShapesAdded; +}; + +#endif // ADD_SHAPES_COMMAND_H diff --git a/src/apps/icon-o-matic/shape/commands/RemovePathsCommand.cpp b/src/apps/icon-o-matic/shape/commands/RemovePathsCommand.cpp new file mode 100644 index 0000000000..d2e086b1e1 --- /dev/null +++ b/src/apps/icon-o-matic/shape/commands/RemovePathsCommand.cpp @@ -0,0 +1,128 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#include "RemovePathsCommand.h" + +#include +#include + +#include "PathContainer.h" +#include "Shape.h" +#include "VectorPath.h" + +using std::nothrow; + +// constructor +RemovePathsCommand::RemovePathsCommand(PathContainer* container, + VectorPath** const paths, + int32 count) + : Command(), + fContainer(container), + fInfos(paths && count > 0 ? new (nothrow) PathInfo[count] : NULL), + fCount(count), + fPathsRemoved(false) +{ + if (!fContainer || !fInfos) + return; + + for (int32 i = 0; i < fCount; i++) { + fInfos[i].path = paths[i]; + fInfos[i].index = 0;//fContainer->IndexOf(paths[i]); + if (paths[i]) { + int32 listenerCount = paths[i]->CountListeners(); + for (int32 j = 0; j < listenerCount; j++) { + Shape* shape = dynamic_cast(paths[i]->ListenerAtFast(j)); + if (shape) + fInfos[i].shapes.AddItem((void*)shape); + } + } + } +} + +// destructor +RemovePathsCommand::~RemovePathsCommand() +{ + if (fPathsRemoved && fInfos) { + for (int32 i = 0; i < fCount; i++) { + if (fInfos[i].path) + fInfos[i].path->Release(); + } + } + delete[] fInfos; +} + +// InitCheck +status_t +RemovePathsCommand::InitCheck() +{ + return fContainer && fInfos ? B_OK : B_NO_INIT; +} + +// Perform +status_t +RemovePathsCommand::Perform() +{ + // remove paths from container and shapes that reference them + for (int32 i = 0; i < fCount; i++) { + if (!fInfos[i].path) + continue; + fContainer->RemovePath(fInfos[i].path); + int32 shapeCount = fInfos[i].shapes.CountItems(); + for (int32 j = 0; j < shapeCount; j++) { + Shape* shape = (Shape*)fInfos[i].shapes.ItemAtFast(j); + shape->Paths()->RemovePath(fInfos[i].path); + } + } + fPathsRemoved = true; + + return B_OK; +} + +// Undo +status_t +RemovePathsCommand::Undo() +{ + status_t ret = B_OK; + + // add paths to container and shapes which previously referenced them + for (int32 i = 0; i < fCount; i++) { + if (!fInfos[i].path) + continue; + if (!fContainer->AddPath(fInfos[i].path/*, fInfos[i].index*/)) { + // roll back + ret = B_ERROR; + for (int32 j = i - 1; j >= 0; j--) { + fContainer->RemovePath(fInfos[j].path); + int32 shapeCount = fInfos[j].shapes.CountItems(); + for (int32 k = 0; k < shapeCount; k++) { + Shape* shape = (Shape*)fInfos[j].shapes.ItemAtFast(k); + shape->Paths()->RemovePath(fInfos[j].path); + } + } + break; + } + int32 shapeCount = fInfos[i].shapes.CountItems(); + for (int32 j = 0; j < shapeCount; j++) { + Shape* shape = (Shape*)fInfos[i].shapes.ItemAtFast(j); + shape->Paths()->AddPath(fInfos[i].path); + } + } + fPathsRemoved = false; + + return ret; +} + +// GetName +void +RemovePathsCommand::GetName(BString& name) +{ + if (fCount > 1) + name << "Remove Paths"; + else + name << "Remove Path"; +} diff --git a/src/apps/icon-o-matic/shape/commands/RemovePathsCommand.h b/src/apps/icon-o-matic/shape/commands/RemovePathsCommand.h new file mode 100644 index 0000000000..ecbd49c79a --- /dev/null +++ b/src/apps/icon-o-matic/shape/commands/RemovePathsCommand.h @@ -0,0 +1,46 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#ifndef REMOVE_PATHS_COMMAND_H +#define REMOVE_PATHS_COMMAND_H + +#include + +#include "Command.h" + +class VectorPath; +class PathContainer; + +class RemovePathsCommand : public Command { + public: + RemovePathsCommand( + PathContainer* container, + VectorPath** const paths, + int32 count); + virtual ~RemovePathsCommand(); + + virtual status_t InitCheck(); + + virtual status_t Perform(); + virtual status_t Undo(); + + virtual void GetName(BString& name); + + private: + PathContainer* fContainer; + struct PathInfo { + VectorPath* path; + int32 index; + BList shapes; + }; + PathInfo* fInfos; + int32 fCount; + bool fPathsRemoved; +}; + +#endif // REMOVE_PATHS_COMMAND_H diff --git a/src/apps/icon-o-matic/shape/commands/RemoveShapesCommand.cpp b/src/apps/icon-o-matic/shape/commands/RemoveShapesCommand.cpp index 6f86fc3c4a..fc54a89ef4 100644 --- a/src/apps/icon-o-matic/shape/commands/RemoveShapesCommand.cpp +++ b/src/apps/icon-o-matic/shape/commands/RemoveShapesCommand.cpp @@ -19,7 +19,7 @@ using std::nothrow; // constructor RemoveShapesCommand::RemoveShapesCommand(ShapeContainer* container, - const int32* indices, + int32* const indices, int32 count) : Command(), fContainer(container), @@ -41,7 +41,7 @@ RemoveShapesCommand::~RemoveShapesCommand() { if (fShapesRemoved && fShapes) { for (int32 i = 0; i < fCount; i++) - delete fShapes[i]; + fShapes[i]->Release(); } delete[] fShapes; delete[] fIndices; diff --git a/src/apps/icon-o-matic/shape/commands/RemoveShapesCommand.h b/src/apps/icon-o-matic/shape/commands/RemoveShapesCommand.h index 8ed56dbcc0..1d74fc1f30 100644 --- a/src/apps/icon-o-matic/shape/commands/RemoveShapesCommand.h +++ b/src/apps/icon-o-matic/shape/commands/RemoveShapesCommand.h @@ -18,7 +18,7 @@ class RemoveShapesCommand : public Command { public: RemoveShapesCommand( ShapeContainer* container, - const int32* indices, + int32* const indices, int32 count); virtual ~RemoveShapesCommand(); diff --git a/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.cpp b/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.cpp new file mode 100644 index 0000000000..3a3085db53 --- /dev/null +++ b/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.cpp @@ -0,0 +1,66 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#include "UnassignPathCommand.h" + +#include "PathContainer.h" +#include "Shape.h" +#include "VectorPath.h" + +// constructor +UnassignPathCommand::UnassignPathCommand(Shape* shape, + VectorPath* path) + : Command(), + fShape(shape), + fPath(path), + fPathRemoved(false) +{ +} + +// destructor +UnassignPathCommand::~UnassignPathCommand() +{ + if (fPathRemoved && fPath) + fPath->Release(); +} + +// InitCheck +status_t +UnassignPathCommand::InitCheck() +{ + return fShape && fPath ? B_OK : B_NO_INIT; +} + +// Perform +status_t +UnassignPathCommand::Perform() +{ + // remove path from shape + fShape->Paths()->RemovePath(fPath); + fPathRemoved = true; + + return B_OK; +} + +// Undo +status_t +UnassignPathCommand::Undo() +{ + // add path to shape + fShape->Paths()->AddPath(fPath); + fPathRemoved = false; + + return B_OK; +} + +// GetName +void +UnassignPathCommand::GetName(BString& name) +{ + name << "Unassign Path"; +} diff --git a/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.h b/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.h new file mode 100644 index 0000000000..52bc37968d --- /dev/null +++ b/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.h @@ -0,0 +1,36 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#ifndef UNASSIGN_PATH_COMMAND_H +#define UNASSIGN_PATH_COMMAND_H + +#include "Command.h" + +class Shape; +class VectorPath; + +class UnassignPathCommand : public Command { + public: + UnassignPathCommand(Shape* shape, + VectorPath* path); + virtual ~UnassignPathCommand(); + + virtual status_t InitCheck(); + + virtual status_t Perform(); + virtual status_t Undo(); + + virtual void GetName(BString& name); + + private: + Shape* fShape; + VectorPath* fPath; + bool fPathRemoved; +}; + +#endif // UNASSIGN_PATH_COMMAND_H diff --git a/src/apps/icon-o-matic/style/AddStylesCommand.cpp b/src/apps/icon-o-matic/style/AddStylesCommand.cpp new file mode 100644 index 0000000000..8b384560f6 --- /dev/null +++ b/src/apps/icon-o-matic/style/AddStylesCommand.cpp @@ -0,0 +1,99 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#include "AddStylesCommand.h" + +#include +#include +#include + +#include "StyleManager.h" +#include "Style.h" + +using std::nothrow; + +// constructor +AddStylesCommand::AddStylesCommand(StyleManager* container, + Style** const styles, + int32 count, + int32 index) + : Command(), + fContainer(container), + fStyles(styles && count > 0 ? new (nothrow) Style*[count] : NULL), + fCount(count), + fIndex(index), + fStylesAdded(false) +{ + if (!fContainer || !fStyles) + return; + + memcpy(fStyles, styles, sizeof(Style*) * fCount); +} + +// destructor +AddStylesCommand::~AddStylesCommand() +{ + if (!fStylesAdded && fStyles) { + for (int32 i = 0; i < fCount; i++) + fStyles[i]->Release(); + } + delete[] fStyles; +} + +// InitCheck +status_t +AddStylesCommand::InitCheck() +{ + return fContainer && fStyles ? B_OK : B_NO_INIT; +} + +// Perform +status_t +AddStylesCommand::Perform() +{ + status_t ret = B_OK; + + // add shapes to container + int32 index = fIndex; + for (int32 i = 0; i < fCount; i++) { + if (fStyles[i] && !fContainer->AddStyle(fStyles[i]/*, index*/)) { + ret = B_ERROR; + // roll back + for (int32 j = i - 1; j >= 0; j--) + fContainer->RemoveStyle(fStyles[j]); + break; + } + index++; + } + fStylesAdded = true; + + return ret; +} + +// Undo +status_t +AddStylesCommand::Undo() +{ + // remove shapes from container + for (int32 i = 0; i < fCount; i++) { + fContainer->RemoveStyle(fStyles[i]); + } + fStylesAdded = false; + + return B_OK; +} + +// GetName +void +AddStylesCommand::GetName(BString& name) +{ + if (fCount > 1) + name << "Add Styles"; + else + name << "Add Style"; +} diff --git a/src/apps/icon-o-matic/style/AddStylesCommand.h b/src/apps/icon-o-matic/style/AddStylesCommand.h new file mode 100644 index 0000000000..3f43e39fc6 --- /dev/null +++ b/src/apps/icon-o-matic/style/AddStylesCommand.h @@ -0,0 +1,41 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#ifndef ADD_STYLES_COMMAND_H +#define ADD_STYLES_COMMAND_H + +#include "Command.h" + +class Style; +class StyleManager; + +class AddStylesCommand : public Command { + public: + AddStylesCommand( + StyleManager* container, + Style** const styles, + int32 count, + int32 index); + virtual ~AddStylesCommand(); + + virtual status_t InitCheck(); + + virtual status_t Perform(); + virtual status_t Undo(); + + virtual void GetName(BString& name); + + private: + StyleManager* fContainer; + Style** fStyles; + int32 fCount; + int32 fIndex; + bool fStylesAdded; +}; + +#endif // ADD_STYLES_COMMAND_H diff --git a/src/apps/icon-o-matic/style/Gradient.cpp b/src/apps/icon-o-matic/style/Gradient.cpp index 8539c7b474..fc6ae02138 100644 --- a/src/apps/icon-o-matic/style/Gradient.cpp +++ b/src/apps/icon-o-matic/style/Gradient.cpp @@ -277,10 +277,12 @@ 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; + if (*step != color) { + step->color = color.color; + step->offset = color.offset; + Notify(); + return true; + } } return false; } @@ -290,9 +292,11 @@ bool Gradient::SetColor(int32 index, const rgb_color& color) { if (color_step* step = ColorAt(index)) { - step->color = color; - Notify(); - return true; + if ((uint32&)step->color != (uint32&)color) { + step->color = color; + Notify(); + return true; + } } return false; } diff --git a/src/apps/icon-o-matic/style/SetColorCommand.cpp b/src/apps/icon-o-matic/style/SetColorCommand.cpp new file mode 100644 index 0000000000..2311e5b0f7 --- /dev/null +++ b/src/apps/icon-o-matic/style/SetColorCommand.cpp @@ -0,0 +1,82 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#include "SetColorCommand.h" + +#include +#include + +#include "Gradient.h" +#include "Style.h" + +using std::nothrow; + +// constructor +SetColorCommand::SetColorCommand(Style* style, + const rgb_color& color) + : Command(), + fStyle(style), + fColor(color) +{ +} + +// destructor +SetColorCommand::~SetColorCommand() +{ +} + +// InitCheck +status_t +SetColorCommand::InitCheck() +{ + return fStyle ? B_OK : B_NO_INIT; +} + +// Perform +status_t +SetColorCommand::Perform() +{ + // toggle the color + rgb_color previous = fStyle->Color(); + fStyle->SetColor(fColor); + fColor = previous; + + return B_OK; +} + +// Undo +status_t +SetColorCommand::Undo() +{ + return Perform(); +} + +// GetName +void +SetColorCommand::GetName(BString& name) +{ + name << "Change Color"; +} + +// CombineWithNext +bool +SetColorCommand::CombineWithNext(const Command* command) +{ + const SetColorCommand* next + = dynamic_cast(command); + + if (next && next->fTimeStamp - fTimeStamp < 1000000) { + fTimeStamp = next->fTimeStamp; + // NOTE: next was already performed, but + // when undoing, we want to use our + // remembered color + return true; + } + return false; +} + diff --git a/src/apps/icon-o-matic/style/SetColorCommand.h b/src/apps/icon-o-matic/style/SetColorCommand.h new file mode 100644 index 0000000000..4cf4d3e98b --- /dev/null +++ b/src/apps/icon-o-matic/style/SetColorCommand.h @@ -0,0 +1,38 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#ifndef SET_COLOR_COMMAND_H +#define SET_COLOR_COMMAND_H + +#include + +#include "Command.h" + +class Style; + +class SetColorCommand : public Command { + public: + SetColorCommand(Style* style, + const rgb_color& color); + virtual ~SetColorCommand(); + + virtual status_t InitCheck(); + + virtual status_t Perform(); + virtual status_t Undo(); + + virtual void GetName(BString& name); + + virtual bool CombineWithNext(const Command* next); + + private: + Style* fStyle; + rgb_color fColor; +}; + +#endif // SET_COLOR_COMMAND_H diff --git a/src/apps/icon-o-matic/transformable/ChannelTransform.cpp b/src/apps/icon-o-matic/transformable/ChannelTransform.cpp index d03480c513..c242bf13e9 100644 --- a/src/apps/icon-o-matic/transformable/ChannelTransform.cpp +++ b/src/apps/icon-o-matic/transformable/ChannelTransform.cpp @@ -40,10 +40,10 @@ ChannelTransform::~ChannelTransform() // SetTransformation void ChannelTransform::SetTransformation(BPoint pivot, - BPoint translation, - double rotation, - double xScale, - double yScale) + BPoint translation, + double rotation, + double xScale, + double yScale) { if (fTranslation != translation || fPivot != pivot || diff --git a/src/apps/icon-o-matic/transformable/TransformBox.cpp b/src/apps/icon-o-matic/transformable/TransformBox.cpp index 4f05edb5f5..8f04e4faf6 100644 --- a/src/apps/icon-o-matic/transformable/TransformBox.cpp +++ b/src/apps/icon-o-matic/transformable/TransformBox.cpp @@ -23,6 +23,11 @@ #define INSET 8.0 +TransformBoxListener::TransformBoxListener() {} +TransformBoxListener::~TransformBoxListener() {} + +// #pragma mark - + // constructor TransformBox::TransformBox(StateView* view, BRect box) : ChannelTransform(), @@ -68,6 +73,8 @@ TransformBox::TransformBox(StateView* view, BRect box) // destructor TransformBox::~TransformBox() { + _NotifyDeleted(); + delete fCurrentCommand; delete fDragLTState; @@ -137,8 +144,8 @@ TransformBox::MouseDown(BPoint where) fCurrentState->SetOrigin(where); delete fCurrentCommand; - fCurrentCommand = MakeAction(fCurrentState->ActionName(), - fCurrentState->ActionNameIndex()); + fCurrentCommand = MakeCommand(fCurrentState->ActionName(), + fCurrentState->ActionNameIndex()); } return true; @@ -173,7 +180,7 @@ TransformBox::MouseOver(BPoint where) { TransformToCanvas(where); - _SetState(_DragStateFor(where, 1.0 /*zoom*/)); + _SetState(_DragStateFor(where, ZoomLevel())); fMousePos = where; if (fCurrentState) { fCurrentState->UpdateViewCursor(fView, fMousePos); @@ -200,7 +207,7 @@ TransformBox::Bounds() BPoint rt = fRightTop; BPoint lb = fLeftBottom; BPoint rb = fRightBottom; - BPoint c = Pivot(); + BPoint c = fPivot; TransformFromCanvas(lt); TransformFromCanvas(rt); @@ -301,9 +308,9 @@ TransformBox::Update(bool deep) Transform(&fPivot); } -// OffsetPivot +// OffsetCenter void -TransformBox::OffsetPivot(BPoint offset) +TransformBox::OffsetCenter(BPoint offset) { if (offset != BPoint(0.0, 0.0)) { fPivotOffset += offset; @@ -311,6 +318,13 @@ TransformBox::OffsetPivot(BPoint offset) } } +// Center +BPoint +TransformBox::Center() const +{ + return fPivot; +} + // SetBox void TransformBox::SetBox(BRect box) @@ -342,7 +356,7 @@ void TransformBox::NudgeBy(BPoint offset) { if (!fNudging && !fCurrentCommand) { - fCurrentCommand = MakeAction("Move", 0/*MOVE*/); + fCurrentCommand = MakeCommand("Move", 0/*MOVE*/); fNudging = true; } if (fNudging) { @@ -370,6 +384,13 @@ TransformBox::TransformToCanvas(BPoint& point) const { } +// ZoomLevel +float +TransformBox::ZoomLevel() const +{ + return 1.0; +} + // ViewSpaceRotation double TransformBox::ViewSpaceRotation() const @@ -378,6 +399,26 @@ TransformBox::ViewSpaceRotation() const return LocalRotation(); } +// #pragma mark - + +// AddListener +bool +TransformBox::AddListener(TransformBoxListener* listener) +{ + if (listener && !fListeners.HasItem((void*)listener)) + return fListeners.AddItem((void*)listener); + return false; +} + +// RemoveListener +bool +TransformBox::RemoveListener(TransformBoxListener* listener) +{ + return fListeners.RemoveItem((void*)listener); +} + +// #pragma mark - + // TODO: why another version? // point_line_dist float @@ -414,7 +455,7 @@ TransformBox::_DragStateFor(BPoint where, float canvasZoom) // priorities: // transformation center point has highest priority ?!? - if (point_point_distance(where, Pivot()) < inset) + if (point_point_distance(where, fPivot) < inset) state = fOffsetCenterState; if (!state) { @@ -581,6 +622,23 @@ TransformBox::_StrokeBWPoint(BView* into, BPoint point, double angle) const into->StrokeLine(p[3], p[0], B_SOLID_LOW); } +// #pragma mark - + +// _NotifyDeleted +void +TransformBox::_NotifyDeleted() const +{ + BList listeners(fListeners); + int32 count = listeners.CountItems(); + for (int32 i = 0; i < count; i++) { + TransformBoxListener* listener + = (TransformBoxListener*)listeners.ItemAtFast(i); + listener->TransformBoxDeleted(this); + } +} + +// #pragma mark - + // _SetState void TransformBox::_SetState(DragState* state) @@ -591,4 +649,3 @@ TransformBox::_SetState(DragState* state) } } - diff --git a/src/apps/icon-o-matic/transformable/TransformBox.h b/src/apps/icon-o-matic/transformable/TransformBox.h index 0bdc85dfe3..f46976e8b7 100644 --- a/src/apps/icon-o-matic/transformable/TransformBox.h +++ b/src/apps/icon-o-matic/transformable/TransformBox.h @@ -9,14 +9,26 @@ #ifndef TRANSFORM_BOX_H #define TRANSFORM_BOX_H +#include + #include "ChannelTransform.h" #include "Manipulator.h" class Command; class StateView; class DragState; +class TransformBox; class TransformCommand; +class TransformBoxListener { + public: + TransformBoxListener(); + virtual ~TransformBoxListener(); + + virtual void TransformBoxDeleted( + const TransformBox* box) = 0; +}; + class TransformBox : public ChannelTransform, public Manipulator { public: @@ -50,7 +62,8 @@ class TransformBox : public ChannelTransform, // TransformBox virtual void Update(bool deep = true); - void OffsetPivot(BPoint offset); + void OffsetCenter(BPoint offset); + BPoint Center() const; void SetBox(BRect box); BRect Box() const { return fOriginalBox; } @@ -64,22 +77,28 @@ class TransformBox : public ChannelTransform, virtual void TransformFromCanvas(BPoint& point) const; virtual void TransformToCanvas(BPoint& point) const; + virtual float ZoomLevel() const; - virtual TransformCommand* MakeAction(const char* actionName, - uint32 nameIndex) const = 0; + virtual TransformCommand* MakeCommand(const char* actionName, + uint32 nameIndex) = 0; bool IsRotating() const { return fCurrentState == fRotateState; } virtual double ViewSpaceRotation() const; + // Listener support + bool AddListener(TransformBoxListener* listener); + bool RemoveListener(TransformBoxListener* listener); + private: DragState* _DragStateFor(BPoint canvasWhere, float canvasZoom); void _StrokeBWLine(BView* into, BPoint from, BPoint to) const; void _StrokeBWPoint(BView* into, - BPoint point, double angle) const; + BPoint point, + double angle) const; BRect fOriginalBox; @@ -100,7 +119,11 @@ class TransformBox : public ChannelTransform, bool fNudging; + BList fListeners; + protected: + void _NotifyDeleted() const; + // "static" state objects void _SetState(DragState* state); diff --git a/src/apps/icon-o-matic/transformable/TransformBoxStates.cpp b/src/apps/icon-o-matic/transformable/TransformBoxStates.cpp index 24e32c74e6..1ce9b718ee 100644 --- a/src/apps/icon-o-matic/transformable/TransformBoxStates.cpp +++ b/src/apps/icon-o-matic/transformable/TransformBoxStates.cpp @@ -509,7 +509,7 @@ RotateBoxState::SetOrigin(BPoint origin) void RotateBoxState::DragTo(BPoint current, uint32 modifiers) { - double angle = calc_angle(fParent->Pivot(), fOrigin, current); + double angle = calc_angle(fParent->Center(), fOrigin, current); if (modifiers & B_SHIFT_KEY) { if (angle < 0.0) @@ -521,14 +521,14 @@ RotateBoxState::DragTo(BPoint current, uint32 modifiers) double newAngle = fOldAngle + angle; - fParent->RotateBy(newAngle - fParent->LocalRotation()); + fParent->RotateBy(fParent->Center(), newAngle - fParent->LocalRotation()); } // UpdateViewCursor void RotateBoxState::UpdateViewCursor(BView* view, BPoint current) const { - BPoint origin(fParent->Pivot()); + BPoint origin(fParent->Center()); fParent->TransformToCanvas(origin); fParent->TransformToCanvas(current); BPoint from = origin + BPoint(sinf(22.5 * 180.0 / PI) * 50.0, @@ -587,7 +587,7 @@ void OffsetCenterState::DragTo(BPoint current, uint32 modifiers) { fParent->InverseTransform(¤t); - fParent->OffsetPivot(current - fOrigin); + fParent->OffsetCenter(current - fOrigin); fOrigin = current; } diff --git a/src/apps/icon-o-matic/transformable/TransformCommand.cpp b/src/apps/icon-o-matic/transformable/TransformCommand.cpp index 0348c76ff9..d2a518bedb 100644 --- a/src/apps/icon-o-matic/transformable/TransformCommand.cpp +++ b/src/apps/icon-o-matic/transformable/TransformCommand.cpp @@ -90,11 +90,11 @@ TransformCommand::Undo() { status_t status = InitCheck(); if (status >= B_OK) { - _SetTransformation(fOldPivot - fNewPivot, - fOldTranslation - fNewTranslation, - fOldRotation - fNewRotation, - fOldXScale - fNewXScale, - fOldYScale - fNewYScale); + _SetTransformation(fOldPivot, + fOldTranslation, + fOldRotation, + fOldXScale, + fOldYScale); } return status; } @@ -105,11 +105,11 @@ TransformCommand::Redo() { status_t status = InitCheck(); if (status >= B_OK) { - _SetTransformation(fNewPivot - fOldPivot, - fNewTranslation - fOldTranslation, - fNewRotation - fOldRotation, - fNewXScale - fOldXScale, - fNewYScale - fOldYScale); + _SetTransformation(fNewPivot, + fNewTranslation, + fNewRotation, + fNewXScale, + fNewYScale); } return status; } diff --git a/src/apps/icon-o-matic/transformable/TransformCommand.h b/src/apps/icon-o-matic/transformable/TransformCommand.h index db1ec84105..6ed18f65e9 100644 --- a/src/apps/icon-o-matic/transformable/TransformCommand.h +++ b/src/apps/icon-o-matic/transformable/TransformCommand.h @@ -39,7 +39,7 @@ class TransformCommand : public Command { virtual void GetName(BString& name); - // TransformCommand + // TransformCommand void SetNewTransformation(BPoint pivot, BPoint translation, double rotation, diff --git a/src/apps/icon-o-matic/transformable/TransformObjectsCommand.cpp b/src/apps/icon-o-matic/transformable/TransformObjectsCommand.cpp new file mode 100644 index 0000000000..7841c045d4 --- /dev/null +++ b/src/apps/icon-o-matic/transformable/TransformObjectsCommand.cpp @@ -0,0 +1,115 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#include "TransformObjectsCommand.h" + +#include +#include + +#include "ChannelTransform.h" + +// constructor +TransformObjectsCommand::TransformObjectsCommand( + TransformBox* box, + const Transformable** objects, + const double* originals, + int32 count, + + BPoint pivot, + BPoint translation, + double rotation, + double xScale, + double yScale, + + const char* name, + int32 nameIndex) + : TransformCommand(pivot, + translation, + rotation, + xScale, + yScale, + name, + nameIndex), + fTransformBox(box), + fObjects(objects && count > 0 ? + new (nothrow) Transformable*[count] : NULL), + fOriginals(originals && count > 0 ? + new (nothrow) double[ + count * Transformable::matrix_size] : NULL), + fCount(count) +{ + if (!fObjects || !fOriginals) + return; + + memcpy(fObjects, objects, fCount * sizeof(Transformable*)); + memcpy(fOriginals, originals, + fCount * Transformable::matrix_size * sizeof(double)); + + if (fTransformBox) + fTransformBox->AddListener(this); +} + +// destructor +TransformObjectsCommand::~TransformObjectsCommand() +{ + if (fTransformBox) + fTransformBox->RemoveListener(this); + + delete[] fObjects; + delete[] fOriginals; +} + +// InitCheck +status_t +TransformObjectsCommand::InitCheck() +{ + return fObjects && fOriginals ? TransformCommand::InitCheck() + : B_NO_INIT; +} + +// #pragma mark - + +// TransformBoxDeleted +void +TransformObjectsCommand::TransformBoxDeleted( + const TransformBox* box) +{ + if (fTransformBox == box) + fTransformBox = NULL; +} + +// #pragma mark - + +// _SetTransformation +status_t +TransformObjectsCommand::_SetTransformation( + BPoint pivot, BPoint translation, + double rotation, + double xScale, double yScale) const +{ + if (fTransformBox) { + fTransformBox->SetTransformation(pivot, translation, + rotation, xScale, yScale); + return B_OK; + } + + + ChannelTransform transform; + transform.SetTransformation(pivot, translation, + rotation, xScale, yScale); + // restore original transformations + int32 matrixSize = Transformable::matrix_size; + for (int32 i = 0; i < fCount; i++) { + if (fObjects[i]) { + fObjects[i]->LoadFrom(&fOriginals[i * matrixSize]); + fObjects[i]->Multiply(transform); + } + } + return B_OK; +} + diff --git a/src/apps/icon-o-matic/transformable/TransformObjectsCommand.h b/src/apps/icon-o-matic/transformable/TransformObjectsCommand.h new file mode 100644 index 0000000000..cb84f6d3c0 --- /dev/null +++ b/src/apps/icon-o-matic/transformable/TransformObjectsCommand.h @@ -0,0 +1,56 @@ +/* + * Copyright 2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +#ifndef TRANSFORM_OBJECTS_COMMAND_H +#define TRANSFORM_OBJECTS_COMMAND_H + +#include "TransformBox.h" +#include "TransformCommand.h" + +class Transformable; + +class TransformObjectsCommand : public TransformCommand, + public TransformBoxListener { + public: + TransformObjectsCommand( + TransformBox* box, + const Transformable** objects, + const double* originals, + int32 count, + + BPoint pivot, + BPoint translation, + double rotation, + double xScale, + double yScale, + + const char* name, + int32 nameIndex); + virtual ~TransformObjectsCommand(); + + // Command interface + virtual status_t InitCheck(); + + // TransformBoxListener interface + virtual void TransformBoxDeleted( + const TransformBox* box); + protected: + // TransformCommand interface + virtual status_t _SetTransformation(BPoint pivotDiff, + BPoint translationDiff, + double rotationDiff, + double xScaleDiff, + double yScaleDiff) const; + + TransformBox* fTransformBox; + Transformable** fObjects; + double* fOriginals; + int32 fCount; +}; + +#endif // TRANSFORM_OBJECTS_COMMAND_H diff --git a/src/apps/icon-o-matic/transformable/TransformShapesBox.cpp b/src/apps/icon-o-matic/transformable/TransformShapesBox.cpp index 2a3bffd628..637c6cf487 100644 --- a/src/apps/icon-o-matic/transformable/TransformShapesBox.cpp +++ b/src/apps/icon-o-matic/transformable/TransformShapesBox.cpp @@ -15,7 +15,7 @@ #include "CanvasView.h" #include "Shape.h" #include "StateView.h" -//#include "TransformShapesCommand.h" +#include "TransformObjectsCommand.h" using std::nothrow; @@ -116,6 +116,10 @@ TransformShapesBox::ObjectChanged(const Observable* object) box = box | fShapes[i]->Bounds(); fShapes[i]->StoreTo(&fOriginals[i * 6]); } + // any TransformObjectsCommand cannot use the TransformBox + // anymore + _NotifyDeleted(); + Reset(); SetBox(box); @@ -154,6 +158,13 @@ TransformShapesBox::TransformToCanvas(BPoint& point) const fParentTransform.Transform(&point); } +// ZoomLevel +float +TransformShapesBox::ZoomLevel() const +{ + return fCanvasView->ZoomLevel(); +} + // ViewSpaceRotation double TransformShapesBox::ViewSpaceRotation() const @@ -163,19 +174,23 @@ TransformShapesBox::ViewSpaceRotation() const return t.rotation() * 180.0 / PI; } -// MakeAction +// MakeCommand TransformCommand* -TransformShapesBox::MakeAction(const char* actionName, uint32 nameIndex) const +TransformShapesBox::MakeCommand(const char* commandName, uint32 nameIndex) { -// return new TransformShapesCommand(fShapes, fCount, -// -// Pivot(), -// Translation(), -// LocalRotation(), -// LocalXScale(), -// LocalYScale(), -// -// actionName, -// nameIndex); - return NULL; + const Transformable* objects[fCount]; + for (int32 i = 0; i < fCount; i++) + objects[i] = fShapes[i]; + + return new TransformObjectsCommand(this, objects, fOriginals, fCount, + + Pivot(), + Translation(), + LocalRotation(), + LocalXScale(), + LocalYScale(), + + commandName, + nameIndex); } + diff --git a/src/apps/icon-o-matic/transformable/TransformShapesBox.h b/src/apps/icon-o-matic/transformable/TransformShapesBox.h index d1775563f9..9eaf5b51b5 100644 --- a/src/apps/icon-o-matic/transformable/TransformShapesBox.h +++ b/src/apps/icon-o-matic/transformable/TransformShapesBox.h @@ -29,10 +29,11 @@ class TransformShapesBox : public TransformBox { virtual void TransformFromCanvas(BPoint& point) const; virtual void TransformToCanvas(BPoint& point) const; + virtual float ZoomLevel() const; virtual double ViewSpaceRotation() const; - virtual TransformCommand* MakeAction(const char* actionName, - uint32 nameIndex) const; + virtual TransformCommand* MakeCommand(const char* actionName, + uint32 nameIndex); // TransformShapesBox Command* Perform(); diff --git a/src/apps/icon-o-matic/transformable/Transformable.cpp b/src/apps/icon-o-matic/transformable/Transformable.cpp index e8e5d55833..fb75a29021 100644 --- a/src/apps/icon-o-matic/transformable/Transformable.cpp +++ b/src/apps/icon-o-matic/transformable/Transformable.cpp @@ -32,14 +32,14 @@ Transformable::~Transformable() // StoreTo void -Transformable::StoreTo(double matrix[6]) const +Transformable::StoreTo(double matrix[matrix_size]) const { store_to(matrix); } // LoadFrom void -Transformable::LoadFrom(double matrix[6]) +Transformable::LoadFrom(double matrix[matrix_size]) { // before calling the potentially heavy TransformationChanged() // hook function, make sure that the transformation @@ -103,7 +103,7 @@ Transformable::Invert() bool Transformable::IsIdentity() const { - double m[6]; + double m[matrix_size]; store_to(m); if (m[0] == 1.0 && m[1] == 0.0 && @@ -119,7 +119,7 @@ Transformable::IsIdentity() const bool Transformable::IsTranslationOnly() const { - double m[6]; + double m[matrix_size]; store_to(m); if (m[0] == 1.0 && m[1] == 0.0 && @@ -133,7 +133,7 @@ Transformable::IsTranslationOnly() const bool Transformable::IsNotDistorted() const { - double m[6]; + double m[matrix_size]; store_to(m); return (m[0] == m[3]); } @@ -142,7 +142,7 @@ Transformable::IsNotDistorted() const bool Transformable::IsValid() const { - double m[6]; + double m[matrix_size]; store_to(m); return ((m[0] * m[3] - m[1] * m[2]) != 0.0); } @@ -151,9 +151,9 @@ Transformable::IsValid() const bool Transformable::operator==(const Transformable& other) const { - double m1[6]; + double m1[matrix_size]; other.store_to(m1); - double m2[6]; + double m2[matrix_size]; store_to(m2); if (m1[0] == m2[0] && m1[1] == m2[1] && diff --git a/src/apps/icon-o-matic/transformable/Transformable.h b/src/apps/icon-o-matic/transformable/Transformable.h index 2924e689f2..7468a9622c 100644 --- a/src/apps/icon-o-matic/transformable/Transformable.h +++ b/src/apps/icon-o-matic/transformable/Transformable.h @@ -17,12 +17,16 @@ class Transformable : public agg::trans_affine { public: + enum { + matrix_size = 6, + }; + Transformable(); Transformable(const Transformable& other); virtual ~Transformable(); - void StoreTo(double matrix[6]) const; - void LoadFrom(double matrix[6]); + void StoreTo(double matrix[matrix_size]) const; + void LoadFrom(double matrix[matrix_size]); // set to or combine with other matrix void SetTransform(const Transformable& other); diff --git a/src/apps/icon-o-matic/transformer/AffineTransformer.cpp b/src/apps/icon-o-matic/transformer/AffineTransformer.cpp index d27df4351f..956804fa66 100644 --- a/src/apps/icon-o-matic/transformer/AffineTransformer.cpp +++ b/src/apps/icon-o-matic/transformer/AffineTransformer.cpp @@ -8,10 +8,14 @@ #include "AffineTransformer.h" +#include + #include "CommonPropertyIDs.h" #include "Property.h" #include "PropertyObject.h" +using std::nothrow; + // constructor AffineTransformer::AffineTransformer(VertexSource& source) : Transformer(source, "Transformation"), @@ -24,6 +28,16 @@ AffineTransformer::~AffineTransformer() { } +// Clone +Transformer* +AffineTransformer::Clone(VertexSource& source) const +{ + AffineTransformer* clone = new (nothrow) AffineTransformer(source); + if (clone) + clone->multiply(*this); + return clone; +} + // rewind void AffineTransformer::rewind(unsigned path_id) diff --git a/src/apps/icon-o-matic/transformer/AffineTransformer.h b/src/apps/icon-o-matic/transformer/AffineTransformer.h index 79d082c4cd..be77a351fa 100644 --- a/src/apps/icon-o-matic/transformer/AffineTransformer.h +++ b/src/apps/icon-o-matic/transformer/AffineTransformer.h @@ -25,7 +25,9 @@ class AffineTransformer : public Transformer, VertexSource& source); virtual ~AffineTransformer(); - virtual void rewind(unsigned path_id); + virtual Transformer* Clone(VertexSource& source) const; + + virtual void rewind(unsigned path_id); virtual unsigned vertex(double* x, double* y); virtual void SetSource(VertexSource& source); diff --git a/src/apps/icon-o-matic/transformer/ContourTransformer.cpp b/src/apps/icon-o-matic/transformer/ContourTransformer.cpp index 3764c0feb3..7bdc5e18de 100644 --- a/src/apps/icon-o-matic/transformer/ContourTransformer.cpp +++ b/src/apps/icon-o-matic/transformer/ContourTransformer.cpp @@ -8,11 +8,15 @@ #include "ContourTransformer.h" +#include + #include "CommonPropertyIDs.h" #include "OptionProperty.h" #include "Property.h" #include "PropertyObject.h" +using std::nothrow; + // constructor ContourTransformer::ContourTransformer(VertexSource& source) : Transformer(source, "Contour"), @@ -26,6 +30,22 @@ ContourTransformer::~ContourTransformer() { } +// Clone +Transformer* +ContourTransformer::Clone(VertexSource& source) const +{ + ContourTransformer* clone = new (nothrow) ContourTransformer(source); + if (clone) { + clone->line_join(line_join()); + clone->inner_join(inner_join()); + clone->width(width()); + clone->miter_limit(miter_limit()); + clone->inner_miter_limit(inner_miter_limit()); + clone->auto_detect_orientation(auto_detect_orientation()); + } + return clone; +} + // rewind void ContourTransformer::rewind(unsigned path_id) diff --git a/src/apps/icon-o-matic/transformer/ContourTransformer.h b/src/apps/icon-o-matic/transformer/ContourTransformer.h index 4b6bfd515c..6d385799c1 100644 --- a/src/apps/icon-o-matic/transformer/ContourTransformer.h +++ b/src/apps/icon-o-matic/transformer/ContourTransformer.h @@ -22,7 +22,9 @@ class ContourTransformer : public Transformer, VertexSource& source); virtual ~ContourTransformer(); - virtual void rewind(unsigned path_id); + virtual Transformer* Clone(VertexSource& source) const; + + virtual void rewind(unsigned path_id); virtual unsigned vertex(double* x, double* y); virtual void SetSource(VertexSource& source); diff --git a/src/apps/icon-o-matic/transformer/PerspectiveTransformer.cpp b/src/apps/icon-o-matic/transformer/PerspectiveTransformer.cpp index 535b10f38b..79a8dd3aca 100644 --- a/src/apps/icon-o-matic/transformer/PerspectiveTransformer.cpp +++ b/src/apps/icon-o-matic/transformer/PerspectiveTransformer.cpp @@ -8,6 +8,10 @@ #include "PerspectiveTransformer.h" +#include + +using std::nothrow; + // constructor PerspectiveTransformer::PerspectiveTransformer(VertexSource& source) : Transformer(source, "Perspective"), @@ -20,6 +24,19 @@ PerspectiveTransformer::~PerspectiveTransformer() { } +// Clone +Transformer* +PerspectiveTransformer::Clone(VertexSource& source) const +{ + PerspectiveTransformer* clone + = new (nothrow) PerspectiveTransformer(source); + if (clone) { +// TODO: upgrade AGG +// clone->multiply(*this); + } + return clone; +} + // rewind void PerspectiveTransformer::rewind(unsigned path_id) diff --git a/src/apps/icon-o-matic/transformer/PerspectiveTransformer.h b/src/apps/icon-o-matic/transformer/PerspectiveTransformer.h index e5a25895c9..6f74cb9566 100644 --- a/src/apps/icon-o-matic/transformer/PerspectiveTransformer.h +++ b/src/apps/icon-o-matic/transformer/PerspectiveTransformer.h @@ -25,8 +25,10 @@ class PerspectiveTransformer : public Transformer, VertexSource& source); virtual ~PerspectiveTransformer(); - virtual void rewind(unsigned path_id); - virtual unsigned vertex(double* x, double* y); + virtual Transformer* Clone(VertexSource& source) const; + + virtual void rewind(unsigned path_id); + virtual unsigned vertex(double* x, double* y); virtual void SetSource(VertexSource& source); diff --git a/src/apps/icon-o-matic/transformer/StrokeTransformer.cpp b/src/apps/icon-o-matic/transformer/StrokeTransformer.cpp index 7adc140516..345db11877 100644 --- a/src/apps/icon-o-matic/transformer/StrokeTransformer.cpp +++ b/src/apps/icon-o-matic/transformer/StrokeTransformer.cpp @@ -8,11 +8,15 @@ #include "StrokeTransformer.h" +#include + #include "CommonPropertyIDs.h" #include "OptionProperty.h" #include "Property.h" #include "PropertyObject.h" +using std::nothrow; + // constructor StrokeTransformer::StrokeTransformer(VertexSource& source) : Transformer(source, "Stroke"), @@ -25,6 +29,23 @@ StrokeTransformer::~StrokeTransformer() { } +// Clone +Transformer* +StrokeTransformer::Clone(VertexSource& source) const +{ + StrokeTransformer* clone = new (nothrow) StrokeTransformer(source); + if (clone) { + clone->line_cap(line_cap()); + clone->line_join(line_join()); + clone->inner_join(inner_join()); + clone->width(width()); + clone->miter_limit(miter_limit()); + clone->inner_miter_limit(inner_miter_limit()); + clone->shorten(shorten()); + } + return clone; +} + // rewind void StrokeTransformer::rewind(unsigned path_id) @@ -98,6 +119,10 @@ StrokeTransformer::MakePropertyObject() const miter_limit())); } + // shorten + object->AddProperty(new FloatProperty(PROPERTY_STROKE_SHORTEN, + shorten())); + return object; } @@ -137,6 +162,13 @@ StrokeTransformer::SetToPropertyObject(const PropertyObject* object) Notify(); } + // shorten + float s = object->Value(PROPERTY_STROKE_SHORTEN, (float)shorten()); + if (s != shorten()) { + shorten(s); + Notify(); + } + return HasPendingNotifications(); } diff --git a/src/apps/icon-o-matic/transformer/StrokeTransformer.h b/src/apps/icon-o-matic/transformer/StrokeTransformer.h index dc949e0919..f46a85526f 100644 --- a/src/apps/icon-o-matic/transformer/StrokeTransformer.h +++ b/src/apps/icon-o-matic/transformer/StrokeTransformer.h @@ -22,8 +22,10 @@ class StrokeTransformer : public Transformer, VertexSource& source); virtual ~StrokeTransformer(); - virtual void rewind(unsigned path_id); - virtual unsigned vertex(double* x, double* y); + virtual Transformer* Clone(VertexSource& source) const; + + virtual void rewind(unsigned path_id); + virtual unsigned vertex(double* x, double* y); virtual void SetSource(VertexSource& source); diff --git a/src/apps/icon-o-matic/transformer/Transformer.h b/src/apps/icon-o-matic/transformer/Transformer.h index 6631e8b562..26c1fbb65a 100644 --- a/src/apps/icon-o-matic/transformer/Transformer.h +++ b/src/apps/icon-o-matic/transformer/Transformer.h @@ -31,7 +31,9 @@ class Transformer : public VertexSource, const char* name); virtual ~Transformer(); - virtual void rewind(unsigned path_id); + virtual Transformer* Clone(VertexSource& source) const = 0; + + virtual void rewind(unsigned path_id); virtual unsigned vertex(double* x, double* y); virtual void SetSource(VertexSource& source);