* added MoveShapesCommand and RemoveShapesCommand

* ShapeContainerListener also gets the index at which a Shape was added
* ShapeListView allows to drag-sort the shapes
* ShapeListView allows to remove shapes (untested)

* IconRenderer is independent of StyleManager now, the
  order of shapes is now correct
* disabled clipping for now, since clear() ignores it (clearing will
  be changed for a checker background anyways)
* added copy constructor to Shape (needs to clone the Transformers yet)

* Selectable optionally knows the global Selection, so that one
  could use Selectable::SetSelected() and it would add itself to
  the selection (not yet used)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17995 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2006-07-01 12:42:52 +00:00
parent 610fdb756f
commit 2ce8d31d09
21 changed files with 587 additions and 93 deletions
+2
View File
@@ -87,8 +87,10 @@ Application Icon-O-Matic :
AddPointCommand.cpp
ChangePointCommand.cpp
InsertPointCommand.cpp
MoveShapesCommand.cpp
PathCommand.cpp
RemovePointsCommand.cpp
RemoveShapesCommand.cpp
# style
Style.cpp
StyleManager.cpp
+3 -3
View File
@@ -93,11 +93,11 @@ MainWindow::_Init()
fPathListView->SetPathContainer(fDocument->Icon()->Paths());
// fPathListView->SetCommandStack(fDocument->CommandStack());
// fPathListView->SetSelection(fDocument->Selection());
fPathListView->SetSelection(fDocument->Selection());
fShapeListView->SetShapeContainer(fDocument->Icon()->Shapes());
// fShapeListView->SetCommandStack(fDocument->CommandStack());
// fShapeListView->SetSelection(fDocument->Selection());
fShapeListView->SetCommandStack(fDocument->CommandStack());
fShapeListView->SetSelection(fDocument->Selection());
fIconPreview16->SetIcon(fDocument->Icon());
fIconPreview32->SetIcon(fDocument->Icon());
+1 -1
View File
@@ -50,7 +50,7 @@ Icon::~Icon()
// ShapeAdded
void
Icon::ShapeAdded(Shape* shape)
Icon::ShapeAdded(Shape* shape, int32 index)
{
shape->AddObserver(this);
_NotifyAreaInvalidated(shape->Bounds(true));
+1 -1
View File
@@ -32,7 +32,7 @@ class Icon : public ShapeContainerListener,
virtual ~Icon();
// ShapeContainerListener interface
virtual void ShapeAdded(Shape* shape);
virtual void ShapeAdded(Shape* shape, int32 index);
virtual void ShapeRemoved(Shape* shape);
// Observer interface
+31 -19
View File
@@ -12,6 +12,7 @@
#include <stdio.h>
#include <Bitmap.h>
#include <List.h>
#include "agg_span_gradient.h"
#include "agg_span_interpolator_linear.h"
@@ -21,16 +22,14 @@
#include "Shape.h"
#include "ShapeContainer.h"
#include "Style.h"
#include "StyleManager.h"
#include "VectorPath.h"
using std::nothrow;
class StyleHandler {
public:
StyleHandler(const StyleManager* styles,
GammaTable& gammaTable)
: fStyles(styles),
StyleHandler(GammaTable& gammaTable)
: fStyles(20),
fGammaTable(gammaTable),
fTransparent(0, 0, 0, 0),
fColor(0, 0, 0, 0)
@@ -38,7 +37,7 @@ class StyleHandler {
bool is_solid(unsigned styleIndex) const
{
Style* style = fStyles->StyleAt(styleIndex);
Style* style = (Style*)fStyles.ItemAt(styleIndex);
if (!style)
return true;
@@ -50,6 +49,11 @@ class StyleHandler {
void generate_span(agg::rgba8* span, int x, int y,
unsigned len, unsigned styleIndex);
bool AddStyle(Style* style)
{
return fStyles.AddItem((void*)style);
}
private:
template<class GradientFunction>
void _GenerateGradient(agg::rgba8* span, int x, int y, unsigned len,
@@ -57,7 +61,7 @@ private:
const agg::rgba8* gradientColors,
agg::trans_affine& gradientTransform);
const StyleManager* fStyles;
BList fStyles;
GammaTable& fGammaTable;
agg::rgba8 fTransparent;
agg::rgba8 fColor;
@@ -67,7 +71,7 @@ private:
const agg::rgba8&
StyleHandler::color(unsigned styleIndex)
{
Style* style = fStyles->StyleAt(styleIndex);
Style* style = (Style*)fStyles.ItemAt(styleIndex);
if (!style) {
printf("no style at index: %d!\n", styleIndex);
return fTransparent;
@@ -87,7 +91,7 @@ void
StyleHandler::generate_span(agg::rgba8* span, int x, int y,
unsigned len, unsigned styleIndex)
{
Style* style = fStyles->StyleAt(styleIndex);
Style* style = (Style*)fStyles.ItemAt(styleIndex);
if (!style || !style->Gradient()) {
printf("no style/gradient at index: %d!\n", styleIndex);
// TODO: memset() span?
@@ -178,7 +182,6 @@ StyleHandler::_GenerateGradient(agg::rgba8* span, int x, int y, unsigned len,
IconRenderer::IconRenderer(BBitmap* bitmap)
: fBitmap(bitmap),
fIcon(NULL),
fStyles(StyleManager::Default()),
fGammaTable(2.2),
@@ -201,6 +204,11 @@ IconRenderer::IconRenderer(BBitmap* bitmap)
bitmap->Bounds().IntegerWidth() + 1,
bitmap->Bounds().IntegerHeight() + 1,
bitmap->BytesPerRow());
fBaseRendererPre.clip_box(0,
0,
fBitmap->Bounds().IntegerWidth(),
fBitmap->Bounds().IntegerHeight());
}
// destructor
@@ -247,15 +255,18 @@ IconRenderer::SetScale(double scale)
void
IconRenderer::_Render(const BRect& r)
{
fBaseRendererPre.clear(agg::rgba8(0, 0, 0, 0));
if (!fIcon)
return;
fBaseRendererPre.clip_box((int)floorf(r.left),
(int)floorf(r.top),
(int)ceilf(r.right),
(int)ceilf(r.bottom));
// TODO: fix clip box for "clear" and "apply_gamma_inv"
// fBaseRendererPre.clip_box((int)floorf(r.left),
// (int)floorf(r.top),
// (int)ceilf(r.right),
// (int)ceilf(r.bottom));
fBaseRendererPre.clear(agg::rgba8(0, 0, 0, 0));
StyleHandler styleHandler(fGammaTable);
fRasterizer.reset();
// iterate over the shapes in the icon,
@@ -265,8 +276,11 @@ IconRenderer::_Render(const BRect& r)
for (int32 i = 0; i < shapeCount; i++) {
Shape* shape = fIcon->Shapes()->ShapeAtFast(i);
int32 styleIndex = fStyles->IndexOf(shape->Style());
fRasterizer.styles(styleIndex, -1);
if (!styleHandler.AddStyle(shape->Style())) {
printf("IconRenderer::_Render() - out of memory\n");
break;
}
fRasterizer.styles(i, -1);
if (fGlobalTransform.is_identity()) {
fRasterizer.add_path(shape->VertexSource());
@@ -277,8 +291,6 @@ IconRenderer::_Render(const BRect& r)
}
}
StyleHandler styleHandler(fStyles, fGammaTable);
agg::render_scanlines_compound(fRasterizer,
fScanline,
fBinaryScanline,
@@ -22,7 +22,6 @@
class BBitmap;
class BRect;
class Icon;
class StyleManager;
typedef agg::gamma_lut
<agg::int8u, agg::int8u> GammaTable;
@@ -58,7 +57,6 @@ class IconRenderer {
BBitmap* fBitmap;
Icon* fIcon;
StyleManager* fStyles;
GammaTable fGammaTable;
@@ -43,7 +43,7 @@ CommandStack::Perform(Command* command)
ret = command->Perform();
if (ret == B_OK)
ret = AddCommand(command);
ret = _AddCommand(command);
if (ret != B_OK) {
// no one else feels responsible...
@@ -54,45 +54,6 @@ CommandStack::Perform(Command* command)
return ret;
}
// AddCommand
status_t
CommandStack::AddCommand(Command* command)
{
status_t status = B_ERROR;
if (Lock()) {
if (command && (status = command->InitCheck()) == B_OK) {
// try to collapse commands to a single command
bool add = true;
if (!fUndoHistory.empty()) {
if (Command* top = fUndoHistory.top()) {
if (top->CombineWithNext(command)) {
add = false;
delete command;
} else if (command->CombineWithPrevious(top)) {
fUndoHistory.pop();
delete top;
}
}
}
if (add)
fUndoHistory.push(command);
// the redo stack needs to be empty
// as soon as an command was added (also in case of collapsing)
while (!fRedoHistory.empty()) {
delete fRedoHistory.top();
fRedoHistory.pop();
}
}
Unlock();
}
Notify();
return status;
}
// Undo
status_t
CommandStack::Undo()
@@ -219,5 +180,41 @@ CommandStack::IsSaved()
return saved;
}
// #pragma mark -
// _AddCommand
status_t
CommandStack::_AddCommand(Command* command)
{
status_t status = B_OK;
// try to collapse commands to a single command
bool add = true;
if (!fUndoHistory.empty()) {
if (Command* top = fUndoHistory.top()) {
if (top->CombineWithNext(command)) {
add = false;
delete command;
} else if (command->CombineWithPrevious(top)) {
fUndoHistory.pop();
delete top;
}
}
}
if (add) {
// TODO: check return value and set status
fUndoHistory.push(command);
}
// the redo stack needs to be empty
// as soon as a command was added (also in case of collapsing)
while (!fRedoHistory.empty()) {
delete fRedoHistory.top();
fRedoHistory.pop();
}
Notify();
return status;
}
@@ -25,7 +25,6 @@ class CommandStack : public BLocker,
virtual ~CommandStack();
status_t Perform(Command* command);
status_t AddCommand(Command* command);
status_t Undo();
status_t Redo();
@@ -38,6 +37,7 @@ class CommandStack : public BLocker,
bool IsSaved();
private:
status_t _AddCommand(Command* command);
typedef stack<Command*> command_stack;
@@ -8,9 +8,14 @@
#include "Selectable.h"
#include <debugger.h>
#include "Selection.h"
// constructor
Selectable::Selectable()
: fSelected(false)
: fSelected(false),
fSelection(NULL)
{
}
@@ -21,8 +26,37 @@ Selectable::~Selectable()
// SetSelected
void
Selectable::SetSelected(bool selected)
Selectable::SetSelected(bool selected, bool exclusive)
{
// NOTE: "exclusive" is only useful when selecting,
// it is ignored when deselecting...
if (selected == fSelected)
return;
if (fSelection) {
if (selected)
fSelection->Select(this, !exclusive);
else
fSelection->Deselect(this);
} else {
debugger("Selectable needs to know Selection\n");
}
}
// SetSelection
void
Selectable::SetSelection(Selection* selection)
{
fSelection = selection;
}
// #pragma mark -
// SetSelected
void
Selectable::_SetSelected(bool selected)
{
// NOTE: for private use by the Selection object!
if (fSelected != selected) {
fSelected = selected;
SelectedChanged();
@@ -11,6 +11,8 @@
#include <SupportDefs.h>
class Selection;
class Selectable {
public:
Selectable();
@@ -21,11 +23,17 @@ class Selectable {
virtual void SelectedChanged() = 0;
// this works only if the Selection is known
void SetSelected(bool selected,
bool exclusive = true);
void SetSelection(Selection* selection);
private:
friend class Selection;
void SetSelected(bool selected);
void _SetSelected(bool selected);
bool fSelected;
Selection* fSelection;
};
#endif // SELECTABLE_H
@@ -47,7 +47,7 @@ Selection::Select(Selectable* object, bool extend)
#endif
if (fSelected.AddItem((void*)object)) {
object->SetSelected(true);
object->_SetSelected(true);
success = true;
Notify();
@@ -77,7 +77,7 @@ Selection::Deselect(Selectable* object)
if (!fSelected.RemoveItem((void*)object))
debugger("Selection::Deselect() - "
"selected object not within list!");
object->SetSelected(false);
object->_SetSelected(false);
Notify();
}
@@ -126,7 +126,7 @@ Selection::_DeselectAllExcept(Selectable* except)
for (int32 i = 0; i < count; i++) {
Selectable* object = (Selectable*)fSelected.ItemAtFast(i);
if (object != except) {
object->SetSelected(false);
object->_SetSelected(false);
notify = true;
} else {
containedExcept = true;
+57 -12
View File
@@ -8,6 +8,7 @@
#include "ShapeListView.h"
#include <new>
#include <stdio.h>
#include <Application.h>
@@ -16,10 +17,15 @@
#include <Mime.h>
#include <Window.h>
#include "CommandStack.h"
#include "MoveShapesCommand.h"
#include "RemoveShapesCommand.h"
#include "Shape.h"
#include "Observer.h"
#include "Selection.h"
using std::nothrow;
class ShapeListItem : public SimpleItem,
public Observer {
public:
@@ -90,7 +96,8 @@ ShapeListView::ShapeListView(BRect frame,
NULL, B_MULTIPLE_SELECTION_LIST),
fMessage(message),
fShapeContainer(NULL),
fSelection(NULL)
fSelection(NULL),
fCommandStack(NULL)
{
SetDragCommand(MSG_DRAG_SHAPE);
SetTarget(target);
@@ -178,11 +185,35 @@ ShapeListView::SetDropTargetRect(const BMessage* message, BPoint where)
SimpleListView::SetDropTargetRect(message, where);
}
// #pragma mark -
// MoveItems
void
ShapeListView::MoveItems(BList& items, int32 toIndex)
{
SimpleListView::MoveItems(items, toIndex);
if (!fCommandStack || !fShapeContainer)
return;
int32 count = items.CountItems();
Shape** shapes = new (nothrow) Shape*[count];
if (!shapes)
return;
for (int32 i = 0; i < count; i++) {
ShapeListItem* item
= dynamic_cast<ShapeListItem*>((BListItem*)items.ItemAtFast(i));
shapes[i] = item ? item->shape : NULL;
}
MoveShapesCommand* command
= new (nothrow) MoveShapesCommand(fShapeContainer,
shapes, count, toIndex);
if (!command) {
delete[] shapes;
return;
}
fCommandStack->Perform(command);
}
// CopyItems
@@ -190,16 +221,23 @@ void
ShapeListView::CopyItems(BList& items, int32 toIndex)
{
MoveItems(items, toIndex);
// copy operation not allowed -> ?!?
// TODO: what about clips that reference the same file but
// with different "in/out points"
// TODO: allow copying items
}
// RemoveItemList
void
ShapeListView::RemoveItemList(BList& indices)
ShapeListView::RemoveItemList(BList& indexList)
{
// TODO: allow removing items
if (!fCommandStack || !fShapeContainer)
return;
int32 count = indexList.CountItems();
const int32* indices = (int32*)indexList.Items();
RemoveShapesCommand* command
= new (nothrow) RemoveShapesCommand(fShapeContainer,
indices, count);
fCommandStack->Perform(command);
}
// CloneItem
@@ -217,7 +255,7 @@ ShapeListView::CloneItem(int32 index) const
// ShapeAdded
void
ShapeListView::ShapeAdded(Shape* shape)
ShapeListView::ShapeAdded(Shape* shape, int32 index)
{
// NOTE: we are in the thread that messed with the
// ShapeContainer, so no need to lock the
@@ -228,7 +266,7 @@ ShapeListView::ShapeAdded(Shape* shape)
// NOTE: shapes are always added at the end
// of the list, so the sorting is synced...
_AddShape(shape);
_AddShape(shape, index);
UnlockLooper();
}
@@ -278,7 +316,7 @@ ShapeListView::SetShapeContainer(ShapeContainer* container)
int32 count = fShapeContainer->CountShapes();
for (int32 i = 0; i < count; i++)
_AddShape(fShapeContainer->ShapeAtFast(i));
_AddShape(fShapeContainer->ShapeAtFast(i), i);
// fShapeContainer->ReadUnlock();
}
@@ -290,14 +328,21 @@ ShapeListView::SetSelection(Selection* selection)
fSelection = selection;
}
// SetCommandStack
void
ShapeListView::SetCommandStack(CommandStack* stack)
{
fCommandStack = stack;
}
// #pragma mark -
// _AddShape
bool
ShapeListView::_AddShape(Shape* shape)
ShapeListView::_AddShape(Shape* shape, int32 index)
{
if (shape)
return AddItem(new ShapeListItem(shape, this));
return AddItem(new ShapeListItem(shape, this), index);
return false;
}
+5 -2
View File
@@ -12,6 +12,7 @@
#include "ListViews.h"
#include "ShapeContainer.h"
class CommandStack;
class Shape;
class ShapeListItem;
class Selection;
@@ -43,15 +44,16 @@ class ShapeListView : public SimpleListView,
virtual BListItem* CloneItem(int32 atIndex) const;
// ShapeContainerListener interface
virtual void ShapeAdded(Shape* shape);
virtual void ShapeAdded(Shape* shape, int32 index);
virtual void ShapeRemoved(Shape* shape);
// ShapeListView
void SetShapeContainer(ShapeContainer* container);
void SetSelection(Selection* selection);
void SetCommandStack(CommandStack* stack);
private:
bool _AddShape(Shape* shape);
bool _AddShape(Shape* shape, int32 index);
bool _RemoveShape(Shape* shape);
ShapeListItem* _ItemForShape(Shape* shape) const;
@@ -61,6 +63,7 @@ class ShapeListView : public SimpleListView,
ShapeContainer* fShapeContainer;
Selection* fSelection;
CommandStack* fCommandStack;
};
#endif // SHAPE_LIST_VIEW_H
+34
View File
@@ -34,6 +34,40 @@ Shape::Shape(::Style* style)
fStyle->Acquire();
}
// constructor
Shape::Shape(const Shape& other)
: Observable(),
Referenceable(),
PathContainerListener(),
fPaths(new (nothrow) PathContainer(false)),
fStyle(other.fStyle),
fPathSource(fPaths),
fTransformers(4),
fLastBounds(0, 0, -1, -1),
fName(other.fName)
{
if (fPaths) {
fPaths->AddListener(this);
// copy the path references from
// the other shape
if (other.fPaths) {
int32 count = other.fPaths->CountPaths();
for (int32 i = 0; i < count; i++) {
if (!fPaths->AddPath(other.fPaths->PathAtFast(i)))
break;
}
}
}
// TODO: clone vertex transformers
if (fStyle)
fStyle->Acquire();
}
// destructor
Shape::~Shape()
{
+1
View File
@@ -21,6 +21,7 @@ class Shape : public Observable,
public PathContainerListener {
public:
Shape(::Style* style);
Shape(const Shape& other);
virtual ~Shape();
// PathContainerListener interface
+18 -4
View File
@@ -50,6 +50,13 @@ ShapeContainer::~ShapeContainer()
// AddShape
bool
ShapeContainer::AddShape(Shape* shape)
{
return AddShape(shape, CountShapes());
}
// AddShape
bool
ShapeContainer::AddShape(Shape* shape, int32 index)
{
if (!shape)
return false;
@@ -58,8 +65,8 @@ ShapeContainer::AddShape(Shape* shape)
if (HasShape(shape))
return false;
if (fShapes.AddItem((void*)shape)) {
_NotifyShapeAdded(shape);
if (fShapes.AddItem((void*)shape, index)) {
_NotifyShapeAdded(shape, index);
return true;
}
@@ -114,6 +121,13 @@ ShapeContainer::HasShape(Shape* shape) const
return fShapes.HasItem((void*)shape);
}
// IndexOf
int32
ShapeContainer::IndexOf(Shape* shape) const
{
return fShapes.IndexOf((void*)shape);
}
// ShapeAt
Shape*
ShapeContainer::ShapeAt(int32 index) const
@@ -165,14 +179,14 @@ ShapeContainer::_MakeEmpty()
// _NotifyShapeAdded
void
ShapeContainer::_NotifyShapeAdded(Shape* shape) const
ShapeContainer::_NotifyShapeAdded(Shape* shape, int32 index) const
{
BList listeners(fListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
ShapeContainerListener* listener
= (ShapeContainerListener*)listeners.ItemAtFast(i);
listener->ShapeAdded(shape);
listener->ShapeAdded(shape, index);
}
}
+5 -2
View File
@@ -18,7 +18,7 @@ class ShapeContainerListener {
ShapeContainerListener();
virtual ~ShapeContainerListener();
virtual void ShapeAdded(Shape* shape) = 0;
virtual void ShapeAdded(Shape* shape, int32 index) = 0;
virtual void ShapeRemoved(Shape* shape) = 0;
};
@@ -28,6 +28,7 @@ class ShapeContainer {
virtual ~ShapeContainer();
bool AddShape(Shape* shape);
bool AddShape(Shape* shape, int32 index);
bool RemoveShape(Shape* shape);
Shape* RemoveShape(int32 index);
@@ -35,6 +36,7 @@ class ShapeContainer {
int32 CountShapes() const;
bool HasShape(Shape* shape) const;
int32 IndexOf(Shape* shape) const;
Shape* ShapeAt(int32 index) const;
Shape* ShapeAtFast(int32 index) const;
@@ -46,7 +48,8 @@ class ShapeContainer {
private:
void _MakeEmpty();
void _NotifyShapeAdded(Shape* shape) const;
void _NotifyShapeAdded(Shape* shape,
int32 index) const;
void _NotifyShapeRemoved(Shape* shape) const;
BList fShapes;
@@ -0,0 +1,157 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "MoveShapesCommand.h"
#include <new>
#include <stdio.h>
#include "ShapeContainer.h"
#include "Shape.h"
using std::nothrow;
// constructor
MoveShapesCommand::MoveShapesCommand(ShapeContainer* container,
Shape** shapes,
int32 count,
int32 toIndex)
: Command(),
fContainer(container),
fShapes(shapes),
fIndices(count > 0 ? new (nothrow) int32[count] : NULL),
fToIndex(toIndex),
fCount(count)
{
if (!fContainer || !fShapes || !fIndices)
return;
// init original shape indices and
// adjust toIndex compensating for items that
// are removed before that index
int32 itemsBeforeIndex = 0;
for (int32 i = 0; i < fCount; i++) {
fIndices[i] = fContainer->IndexOf(fShapes[i]);
if (fIndices[i] >= 0 && fIndices[i] < fToIndex)
itemsBeforeIndex++;
}
fToIndex -= itemsBeforeIndex;
}
// destructor
MoveShapesCommand::~MoveShapesCommand()
{
delete[] fShapes;
delete[] fIndices;
}
// InitCheck
status_t
MoveShapesCommand::InitCheck()
{
if (!fContainer || !fShapes || !fIndices)
return B_NO_INIT;
// analyse the move, don't return B_OK in case
// the container state does not change...
int32 index = fIndices[0];
// NOTE: fIndices == NULL if fCount < 1
if (index != fToIndex) {
// a change is guaranteed
return B_OK;
}
// the insertion index is the same as the index of the first
// moved item, a change only occures if the indices of the
// moved items is not contiguous
bool isContiguous = true;
for (int32 i = 1; i < fCount; i++) {
if (fIndices[i] != index + 1) {
isContiguous = false;
break;
}
index = fIndices[i];
}
if (isContiguous) {
// the container state will not change because of the move
return B_ERROR;
}
return B_OK;
}
// Perform
status_t
MoveShapesCommand::Perform()
{
status_t ret = B_OK;
// remove shapes from container
for (int32 i = 0; i < fCount; i++) {
if (fShapes[i] && !fContainer->RemoveShape(fShapes[i])) {
ret = B_ERROR;
break;
}
}
if (ret < B_OK)
return ret;
// add shapes to container at the insertion index
int32 index = fToIndex;
for (int32 i = 0; i < fCount; i++) {
if (fShapes[i] && !fContainer->AddShape(fShapes[i], index++)) {
ret = B_ERROR;
break;
}
}
return ret;
}
// Undo
status_t
MoveShapesCommand::Undo()
{
status_t ret = B_OK;
// remove shapes from container
for (int32 i = 0; i < fCount; i++) {
if (fShapes[i] && !fContainer->RemoveShape(fShapes[i])) {
ret = B_ERROR;
break;
}
}
if (ret < B_OK)
return ret;
// add shapes to container at remembered indices
for (int32 i = 0; i < fCount; i++) {
if (fShapes[i] && !fContainer->AddShape(fShapes[i], fIndices[i])) {
ret = B_ERROR;
break;
}
}
return ret;
}
// GetName
void
MoveShapesCommand::GetName(BString& name)
{
// if (fCount > 1)
// name << _GetString(MOVE_MODIFIERS, "Move Shapes");
// else
// name << _GetString(MOVE_MODIFIER, "Move Shape");
if (fCount > 1)
name << "Move Shapes";
else
name << "Move Shape";
}
@@ -0,0 +1,41 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef MOVE_SHAPES_COMMAND_H
#define MOVE_SHAPES_COMMAND_H
#include "Command.h"
class Shape;
class ShapeContainer;
class MoveShapesCommand : public Command {
public:
MoveShapesCommand(
ShapeContainer* container,
Shape** shapes,
int32 count,
int32 toIndex);
virtual ~MoveShapesCommand();
virtual status_t InitCheck();
virtual status_t Perform();
virtual status_t Undo();
virtual void GetName(BString& name);
private:
ShapeContainer* fContainer;
Shape** fShapes;
int32* fIndices;
int32 fToIndex;
int32 fCount;
};
#endif // MOVE_SHAPES_COMMAND_H
@@ -0,0 +1,105 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "RemoveShapesCommand.h"
#include <new>
#include <stdio.h>
#include <string.h>
#include "ShapeContainer.h"
#include "Shape.h"
using std::nothrow;
// constructor
RemoveShapesCommand::RemoveShapesCommand(ShapeContainer* container,
const int32* indices,
int32 count)
: Command(),
fContainer(container),
fShapes(count > 0 ? new (nothrow) Shape*[count] : NULL),
fIndices(count > 0 ? new (nothrow) int32[count] : NULL),
fCount(count),
fShapesRemoved(false)
{
if (!fContainer || !fShapes || !fIndices)
return;
memcpy(fIndices, indices, sizeof(int32) * fCount);
for (int32 i = 0; i < fCount; i++)
fShapes[i] = fContainer->ShapeAt(fIndices[i]);
}
// destructor
RemoveShapesCommand::~RemoveShapesCommand()
{
if (fShapesRemoved && fShapes) {
for (int32 i = 0; i < fCount; i++)
delete fShapes[i];
}
delete[] fShapes;
delete[] fIndices;
}
// InitCheck
status_t
RemoveShapesCommand::InitCheck()
{
return fContainer && fShapes && fIndices ? B_OK : B_NO_INIT;
}
// Perform
status_t
RemoveShapesCommand::Perform()
{
status_t ret = B_OK;
// remove shapes from container
for (int32 i = 0; i < fCount; i++) {
if (fShapes[i] && !fContainer->RemoveShape(fShapes[i])) {
ret = B_ERROR;
break;
}
}
fShapesRemoved = true;
return ret;
}
// Undo
status_t
RemoveShapesCommand::Undo()
{
status_t ret = B_OK;
// add shapes to container at remembered indices
for (int32 i = 0; i < fCount; i++) {
if (fShapes[i] && !fContainer->AddShape(fShapes[i], fIndices[i])) {
ret = B_ERROR;
break;
}
}
fShapesRemoved = false;
return ret;
}
// GetName
void
RemoveShapesCommand::GetName(BString& name)
{
// if (fCount > 1)
// name << _GetString(MOVE_MODIFIERS, "Move Shapes");
// else
// name << _GetString(MOVE_MODIFIER, "Move Shape");
if (fCount > 1)
name << "Remove Shapes";
else
name << "Remove Shape";
}
@@ -0,0 +1,40 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef REMOVE_SHAPES_COMMAND_H
#define REMOVE_SHAPES_COMMAND_H
#include "Command.h"
class Shape;
class ShapeContainer;
class RemoveShapesCommand : public Command {
public:
RemoveShapesCommand(
ShapeContainer* container,
const int32* indices,
int32 count);
virtual ~RemoveShapesCommand();
virtual status_t InitCheck();
virtual status_t Perform();
virtual status_t Undo();
virtual void GetName(BString& name);
private:
ShapeContainer* fContainer;
Shape** fShapes;
int32* fIndices;
int32 fCount;
bool fShapesRemoved;
};
#endif // REMOVE_SHAPES_COMMAND_H