* 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:
@@ -87,8 +87,10 @@ Application Icon-O-Matic :
|
|||||||
AddPointCommand.cpp
|
AddPointCommand.cpp
|
||||||
ChangePointCommand.cpp
|
ChangePointCommand.cpp
|
||||||
InsertPointCommand.cpp
|
InsertPointCommand.cpp
|
||||||
|
MoveShapesCommand.cpp
|
||||||
PathCommand.cpp
|
PathCommand.cpp
|
||||||
RemovePointsCommand.cpp
|
RemovePointsCommand.cpp
|
||||||
|
RemoveShapesCommand.cpp
|
||||||
# style
|
# style
|
||||||
Style.cpp
|
Style.cpp
|
||||||
StyleManager.cpp
|
StyleManager.cpp
|
||||||
|
|||||||
@@ -93,11 +93,11 @@ MainWindow::_Init()
|
|||||||
|
|
||||||
fPathListView->SetPathContainer(fDocument->Icon()->Paths());
|
fPathListView->SetPathContainer(fDocument->Icon()->Paths());
|
||||||
// fPathListView->SetCommandStack(fDocument->CommandStack());
|
// fPathListView->SetCommandStack(fDocument->CommandStack());
|
||||||
// fPathListView->SetSelection(fDocument->Selection());
|
fPathListView->SetSelection(fDocument->Selection());
|
||||||
|
|
||||||
fShapeListView->SetShapeContainer(fDocument->Icon()->Shapes());
|
fShapeListView->SetShapeContainer(fDocument->Icon()->Shapes());
|
||||||
// fShapeListView->SetCommandStack(fDocument->CommandStack());
|
fShapeListView->SetCommandStack(fDocument->CommandStack());
|
||||||
// fShapeListView->SetSelection(fDocument->Selection());
|
fShapeListView->SetSelection(fDocument->Selection());
|
||||||
|
|
||||||
fIconPreview16->SetIcon(fDocument->Icon());
|
fIconPreview16->SetIcon(fDocument->Icon());
|
||||||
fIconPreview32->SetIcon(fDocument->Icon());
|
fIconPreview32->SetIcon(fDocument->Icon());
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ Icon::~Icon()
|
|||||||
|
|
||||||
// ShapeAdded
|
// ShapeAdded
|
||||||
void
|
void
|
||||||
Icon::ShapeAdded(Shape* shape)
|
Icon::ShapeAdded(Shape* shape, int32 index)
|
||||||
{
|
{
|
||||||
shape->AddObserver(this);
|
shape->AddObserver(this);
|
||||||
_NotifyAreaInvalidated(shape->Bounds(true));
|
_NotifyAreaInvalidated(shape->Bounds(true));
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class Icon : public ShapeContainerListener,
|
|||||||
virtual ~Icon();
|
virtual ~Icon();
|
||||||
|
|
||||||
// ShapeContainerListener interface
|
// ShapeContainerListener interface
|
||||||
virtual void ShapeAdded(Shape* shape);
|
virtual void ShapeAdded(Shape* shape, int32 index);
|
||||||
virtual void ShapeRemoved(Shape* shape);
|
virtual void ShapeRemoved(Shape* shape);
|
||||||
|
|
||||||
// Observer interface
|
// Observer interface
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <Bitmap.h>
|
#include <Bitmap.h>
|
||||||
|
#include <List.h>
|
||||||
|
|
||||||
#include "agg_span_gradient.h"
|
#include "agg_span_gradient.h"
|
||||||
#include "agg_span_interpolator_linear.h"
|
#include "agg_span_interpolator_linear.h"
|
||||||
@@ -21,16 +22,14 @@
|
|||||||
#include "Shape.h"
|
#include "Shape.h"
|
||||||
#include "ShapeContainer.h"
|
#include "ShapeContainer.h"
|
||||||
#include "Style.h"
|
#include "Style.h"
|
||||||
#include "StyleManager.h"
|
|
||||||
#include "VectorPath.h"
|
#include "VectorPath.h"
|
||||||
|
|
||||||
using std::nothrow;
|
using std::nothrow;
|
||||||
|
|
||||||
class StyleHandler {
|
class StyleHandler {
|
||||||
public:
|
public:
|
||||||
StyleHandler(const StyleManager* styles,
|
StyleHandler(GammaTable& gammaTable)
|
||||||
GammaTable& gammaTable)
|
: fStyles(20),
|
||||||
: fStyles(styles),
|
|
||||||
fGammaTable(gammaTable),
|
fGammaTable(gammaTable),
|
||||||
fTransparent(0, 0, 0, 0),
|
fTransparent(0, 0, 0, 0),
|
||||||
fColor(0, 0, 0, 0)
|
fColor(0, 0, 0, 0)
|
||||||
@@ -38,7 +37,7 @@ class StyleHandler {
|
|||||||
|
|
||||||
bool is_solid(unsigned styleIndex) const
|
bool is_solid(unsigned styleIndex) const
|
||||||
{
|
{
|
||||||
Style* style = fStyles->StyleAt(styleIndex);
|
Style* style = (Style*)fStyles.ItemAt(styleIndex);
|
||||||
if (!style)
|
if (!style)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -50,6 +49,11 @@ class StyleHandler {
|
|||||||
void generate_span(agg::rgba8* span, int x, int y,
|
void generate_span(agg::rgba8* span, int x, int y,
|
||||||
unsigned len, unsigned styleIndex);
|
unsigned len, unsigned styleIndex);
|
||||||
|
|
||||||
|
bool AddStyle(Style* style)
|
||||||
|
{
|
||||||
|
return fStyles.AddItem((void*)style);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<class GradientFunction>
|
template<class GradientFunction>
|
||||||
void _GenerateGradient(agg::rgba8* span, int x, int y, unsigned len,
|
void _GenerateGradient(agg::rgba8* span, int x, int y, unsigned len,
|
||||||
@@ -57,7 +61,7 @@ private:
|
|||||||
const agg::rgba8* gradientColors,
|
const agg::rgba8* gradientColors,
|
||||||
agg::trans_affine& gradientTransform);
|
agg::trans_affine& gradientTransform);
|
||||||
|
|
||||||
const StyleManager* fStyles;
|
BList fStyles;
|
||||||
GammaTable& fGammaTable;
|
GammaTable& fGammaTable;
|
||||||
agg::rgba8 fTransparent;
|
agg::rgba8 fTransparent;
|
||||||
agg::rgba8 fColor;
|
agg::rgba8 fColor;
|
||||||
@@ -67,7 +71,7 @@ private:
|
|||||||
const agg::rgba8&
|
const agg::rgba8&
|
||||||
StyleHandler::color(unsigned styleIndex)
|
StyleHandler::color(unsigned styleIndex)
|
||||||
{
|
{
|
||||||
Style* style = fStyles->StyleAt(styleIndex);
|
Style* style = (Style*)fStyles.ItemAt(styleIndex);
|
||||||
if (!style) {
|
if (!style) {
|
||||||
printf("no style at index: %d!\n", styleIndex);
|
printf("no style at index: %d!\n", styleIndex);
|
||||||
return fTransparent;
|
return fTransparent;
|
||||||
@@ -87,7 +91,7 @@ void
|
|||||||
StyleHandler::generate_span(agg::rgba8* span, int x, int y,
|
StyleHandler::generate_span(agg::rgba8* span, int x, int y,
|
||||||
unsigned len, unsigned styleIndex)
|
unsigned len, unsigned styleIndex)
|
||||||
{
|
{
|
||||||
Style* style = fStyles->StyleAt(styleIndex);
|
Style* style = (Style*)fStyles.ItemAt(styleIndex);
|
||||||
if (!style || !style->Gradient()) {
|
if (!style || !style->Gradient()) {
|
||||||
printf("no style/gradient at index: %d!\n", styleIndex);
|
printf("no style/gradient at index: %d!\n", styleIndex);
|
||||||
// TODO: memset() span?
|
// TODO: memset() span?
|
||||||
@@ -178,7 +182,6 @@ StyleHandler::_GenerateGradient(agg::rgba8* span, int x, int y, unsigned len,
|
|||||||
IconRenderer::IconRenderer(BBitmap* bitmap)
|
IconRenderer::IconRenderer(BBitmap* bitmap)
|
||||||
: fBitmap(bitmap),
|
: fBitmap(bitmap),
|
||||||
fIcon(NULL),
|
fIcon(NULL),
|
||||||
fStyles(StyleManager::Default()),
|
|
||||||
|
|
||||||
fGammaTable(2.2),
|
fGammaTable(2.2),
|
||||||
|
|
||||||
@@ -201,6 +204,11 @@ IconRenderer::IconRenderer(BBitmap* bitmap)
|
|||||||
bitmap->Bounds().IntegerWidth() + 1,
|
bitmap->Bounds().IntegerWidth() + 1,
|
||||||
bitmap->Bounds().IntegerHeight() + 1,
|
bitmap->Bounds().IntegerHeight() + 1,
|
||||||
bitmap->BytesPerRow());
|
bitmap->BytesPerRow());
|
||||||
|
|
||||||
|
fBaseRendererPre.clip_box(0,
|
||||||
|
0,
|
||||||
|
fBitmap->Bounds().IntegerWidth(),
|
||||||
|
fBitmap->Bounds().IntegerHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
@@ -247,15 +255,18 @@ IconRenderer::SetScale(double scale)
|
|||||||
void
|
void
|
||||||
IconRenderer::_Render(const BRect& r)
|
IconRenderer::_Render(const BRect& r)
|
||||||
{
|
{
|
||||||
fBaseRendererPre.clear(agg::rgba8(0, 0, 0, 0));
|
|
||||||
|
|
||||||
if (!fIcon)
|
if (!fIcon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fBaseRendererPre.clip_box((int)floorf(r.left),
|
// TODO: fix clip box for "clear" and "apply_gamma_inv"
|
||||||
(int)floorf(r.top),
|
// fBaseRendererPre.clip_box((int)floorf(r.left),
|
||||||
(int)ceilf(r.right),
|
// (int)floorf(r.top),
|
||||||
(int)ceilf(r.bottom));
|
// (int)ceilf(r.right),
|
||||||
|
// (int)ceilf(r.bottom));
|
||||||
|
|
||||||
|
fBaseRendererPre.clear(agg::rgba8(0, 0, 0, 0));
|
||||||
|
|
||||||
|
StyleHandler styleHandler(fGammaTable);
|
||||||
|
|
||||||
fRasterizer.reset();
|
fRasterizer.reset();
|
||||||
// iterate over the shapes in the icon,
|
// iterate over the shapes in the icon,
|
||||||
@@ -265,8 +276,11 @@ IconRenderer::_Render(const BRect& r)
|
|||||||
for (int32 i = 0; i < shapeCount; i++) {
|
for (int32 i = 0; i < shapeCount; i++) {
|
||||||
Shape* shape = fIcon->Shapes()->ShapeAtFast(i);
|
Shape* shape = fIcon->Shapes()->ShapeAtFast(i);
|
||||||
|
|
||||||
int32 styleIndex = fStyles->IndexOf(shape->Style());
|
if (!styleHandler.AddStyle(shape->Style())) {
|
||||||
fRasterizer.styles(styleIndex, -1);
|
printf("IconRenderer::_Render() - out of memory\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fRasterizer.styles(i, -1);
|
||||||
|
|
||||||
if (fGlobalTransform.is_identity()) {
|
if (fGlobalTransform.is_identity()) {
|
||||||
fRasterizer.add_path(shape->VertexSource());
|
fRasterizer.add_path(shape->VertexSource());
|
||||||
@@ -277,8 +291,6 @@ IconRenderer::_Render(const BRect& r)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyleHandler styleHandler(fStyles, fGammaTable);
|
|
||||||
|
|
||||||
agg::render_scanlines_compound(fRasterizer,
|
agg::render_scanlines_compound(fRasterizer,
|
||||||
fScanline,
|
fScanline,
|
||||||
fBinaryScanline,
|
fBinaryScanline,
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
class BBitmap;
|
class BBitmap;
|
||||||
class BRect;
|
class BRect;
|
||||||
class Icon;
|
class Icon;
|
||||||
class StyleManager;
|
|
||||||
|
|
||||||
typedef agg::gamma_lut
|
typedef agg::gamma_lut
|
||||||
<agg::int8u, agg::int8u> GammaTable;
|
<agg::int8u, agg::int8u> GammaTable;
|
||||||
@@ -58,7 +57,6 @@ class IconRenderer {
|
|||||||
|
|
||||||
BBitmap* fBitmap;
|
BBitmap* fBitmap;
|
||||||
Icon* fIcon;
|
Icon* fIcon;
|
||||||
StyleManager* fStyles;
|
|
||||||
|
|
||||||
GammaTable fGammaTable;
|
GammaTable fGammaTable;
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ CommandStack::Perform(Command* command)
|
|||||||
ret = command->Perform();
|
ret = command->Perform();
|
||||||
|
|
||||||
if (ret == B_OK)
|
if (ret == B_OK)
|
||||||
ret = AddCommand(command);
|
ret = _AddCommand(command);
|
||||||
|
|
||||||
if (ret != B_OK) {
|
if (ret != B_OK) {
|
||||||
// no one else feels responsible...
|
// no one else feels responsible...
|
||||||
@@ -54,45 +54,6 @@ CommandStack::Perform(Command* command)
|
|||||||
return ret;
|
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
|
// Undo
|
||||||
status_t
|
status_t
|
||||||
CommandStack::Undo()
|
CommandStack::Undo()
|
||||||
@@ -219,5 +180,41 @@ CommandStack::IsSaved()
|
|||||||
return saved;
|
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();
|
virtual ~CommandStack();
|
||||||
|
|
||||||
status_t Perform(Command* command);
|
status_t Perform(Command* command);
|
||||||
status_t AddCommand(Command* command);
|
|
||||||
|
|
||||||
status_t Undo();
|
status_t Undo();
|
||||||
status_t Redo();
|
status_t Redo();
|
||||||
@@ -38,6 +37,7 @@ class CommandStack : public BLocker,
|
|||||||
bool IsSaved();
|
bool IsSaved();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
status_t _AddCommand(Command* command);
|
||||||
|
|
||||||
typedef stack<Command*> command_stack;
|
typedef stack<Command*> command_stack;
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,14 @@
|
|||||||
|
|
||||||
#include "Selectable.h"
|
#include "Selectable.h"
|
||||||
|
|
||||||
|
#include <debugger.h>
|
||||||
|
|
||||||
|
#include "Selection.h"
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
Selectable::Selectable()
|
Selectable::Selectable()
|
||||||
: fSelected(false)
|
: fSelected(false),
|
||||||
|
fSelection(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,8 +26,37 @@ Selectable::~Selectable()
|
|||||||
|
|
||||||
// SetSelected
|
// SetSelected
|
||||||
void
|
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) {
|
if (fSelected != selected) {
|
||||||
fSelected = selected;
|
fSelected = selected;
|
||||||
SelectedChanged();
|
SelectedChanged();
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
class Selection;
|
||||||
|
|
||||||
class Selectable {
|
class Selectable {
|
||||||
public:
|
public:
|
||||||
Selectable();
|
Selectable();
|
||||||
@@ -21,11 +23,17 @@ class Selectable {
|
|||||||
|
|
||||||
virtual void SelectedChanged() = 0;
|
virtual void SelectedChanged() = 0;
|
||||||
|
|
||||||
|
// this works only if the Selection is known
|
||||||
|
void SetSelected(bool selected,
|
||||||
|
bool exclusive = true);
|
||||||
|
void SetSelection(Selection* selection);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Selection;
|
friend class Selection;
|
||||||
void SetSelected(bool selected);
|
void _SetSelected(bool selected);
|
||||||
|
|
||||||
bool fSelected;
|
bool fSelected;
|
||||||
|
Selection* fSelection;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SELECTABLE_H
|
#endif // SELECTABLE_H
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ Selection::Select(Selectable* object, bool extend)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (fSelected.AddItem((void*)object)) {
|
if (fSelected.AddItem((void*)object)) {
|
||||||
object->SetSelected(true);
|
object->_SetSelected(true);
|
||||||
success = true;
|
success = true;
|
||||||
|
|
||||||
Notify();
|
Notify();
|
||||||
@@ -77,7 +77,7 @@ Selection::Deselect(Selectable* object)
|
|||||||
if (!fSelected.RemoveItem((void*)object))
|
if (!fSelected.RemoveItem((void*)object))
|
||||||
debugger("Selection::Deselect() - "
|
debugger("Selection::Deselect() - "
|
||||||
"selected object not within list!");
|
"selected object not within list!");
|
||||||
object->SetSelected(false);
|
object->_SetSelected(false);
|
||||||
|
|
||||||
Notify();
|
Notify();
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,7 @@ Selection::_DeselectAllExcept(Selectable* except)
|
|||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
Selectable* object = (Selectable*)fSelected.ItemAtFast(i);
|
Selectable* object = (Selectable*)fSelected.ItemAtFast(i);
|
||||||
if (object != except) {
|
if (object != except) {
|
||||||
object->SetSelected(false);
|
object->_SetSelected(false);
|
||||||
notify = true;
|
notify = true;
|
||||||
} else {
|
} else {
|
||||||
containedExcept = true;
|
containedExcept = true;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "ShapeListView.h"
|
#include "ShapeListView.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
@@ -16,10 +17,15 @@
|
|||||||
#include <Mime.h>
|
#include <Mime.h>
|
||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
|
#include "CommandStack.h"
|
||||||
|
#include "MoveShapesCommand.h"
|
||||||
|
#include "RemoveShapesCommand.h"
|
||||||
#include "Shape.h"
|
#include "Shape.h"
|
||||||
#include "Observer.h"
|
#include "Observer.h"
|
||||||
#include "Selection.h"
|
#include "Selection.h"
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
class ShapeListItem : public SimpleItem,
|
class ShapeListItem : public SimpleItem,
|
||||||
public Observer {
|
public Observer {
|
||||||
public:
|
public:
|
||||||
@@ -90,7 +96,8 @@ ShapeListView::ShapeListView(BRect frame,
|
|||||||
NULL, B_MULTIPLE_SELECTION_LIST),
|
NULL, B_MULTIPLE_SELECTION_LIST),
|
||||||
fMessage(message),
|
fMessage(message),
|
||||||
fShapeContainer(NULL),
|
fShapeContainer(NULL),
|
||||||
fSelection(NULL)
|
fSelection(NULL),
|
||||||
|
fCommandStack(NULL)
|
||||||
{
|
{
|
||||||
SetDragCommand(MSG_DRAG_SHAPE);
|
SetDragCommand(MSG_DRAG_SHAPE);
|
||||||
SetTarget(target);
|
SetTarget(target);
|
||||||
@@ -178,11 +185,35 @@ ShapeListView::SetDropTargetRect(const BMessage* message, BPoint where)
|
|||||||
SimpleListView::SetDropTargetRect(message, where);
|
SimpleListView::SetDropTargetRect(message, where);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
// MoveItems
|
// MoveItems
|
||||||
void
|
void
|
||||||
ShapeListView::MoveItems(BList& items, int32 toIndex)
|
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
|
// CopyItems
|
||||||
@@ -190,16 +221,23 @@ void
|
|||||||
ShapeListView::CopyItems(BList& items, int32 toIndex)
|
ShapeListView::CopyItems(BList& items, int32 toIndex)
|
||||||
{
|
{
|
||||||
MoveItems(items, toIndex);
|
MoveItems(items, toIndex);
|
||||||
// copy operation not allowed -> ?!?
|
// TODO: allow copying items
|
||||||
// TODO: what about clips that reference the same file but
|
|
||||||
// with different "in/out points"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveItemList
|
// RemoveItemList
|
||||||
void
|
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
|
// CloneItem
|
||||||
@@ -217,7 +255,7 @@ ShapeListView::CloneItem(int32 index) const
|
|||||||
|
|
||||||
// ShapeAdded
|
// ShapeAdded
|
||||||
void
|
void
|
||||||
ShapeListView::ShapeAdded(Shape* shape)
|
ShapeListView::ShapeAdded(Shape* shape, int32 index)
|
||||||
{
|
{
|
||||||
// NOTE: we are in the thread that messed with the
|
// NOTE: we are in the thread that messed with the
|
||||||
// ShapeContainer, so no need to lock the
|
// ShapeContainer, so no need to lock the
|
||||||
@@ -228,7 +266,7 @@ ShapeListView::ShapeAdded(Shape* shape)
|
|||||||
|
|
||||||
// NOTE: shapes are always added at the end
|
// NOTE: shapes are always added at the end
|
||||||
// of the list, so the sorting is synced...
|
// of the list, so the sorting is synced...
|
||||||
_AddShape(shape);
|
_AddShape(shape, index);
|
||||||
|
|
||||||
UnlockLooper();
|
UnlockLooper();
|
||||||
}
|
}
|
||||||
@@ -278,7 +316,7 @@ ShapeListView::SetShapeContainer(ShapeContainer* container)
|
|||||||
|
|
||||||
int32 count = fShapeContainer->CountShapes();
|
int32 count = fShapeContainer->CountShapes();
|
||||||
for (int32 i = 0; i < count; i++)
|
for (int32 i = 0; i < count; i++)
|
||||||
_AddShape(fShapeContainer->ShapeAtFast(i));
|
_AddShape(fShapeContainer->ShapeAtFast(i), i);
|
||||||
|
|
||||||
// fShapeContainer->ReadUnlock();
|
// fShapeContainer->ReadUnlock();
|
||||||
}
|
}
|
||||||
@@ -290,14 +328,21 @@ ShapeListView::SetSelection(Selection* selection)
|
|||||||
fSelection = selection;
|
fSelection = selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetCommandStack
|
||||||
|
void
|
||||||
|
ShapeListView::SetCommandStack(CommandStack* stack)
|
||||||
|
{
|
||||||
|
fCommandStack = stack;
|
||||||
|
}
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// _AddShape
|
// _AddShape
|
||||||
bool
|
bool
|
||||||
ShapeListView::_AddShape(Shape* shape)
|
ShapeListView::_AddShape(Shape* shape, int32 index)
|
||||||
{
|
{
|
||||||
if (shape)
|
if (shape)
|
||||||
return AddItem(new ShapeListItem(shape, this));
|
return AddItem(new ShapeListItem(shape, this), index);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "ListViews.h"
|
#include "ListViews.h"
|
||||||
#include "ShapeContainer.h"
|
#include "ShapeContainer.h"
|
||||||
|
|
||||||
|
class CommandStack;
|
||||||
class Shape;
|
class Shape;
|
||||||
class ShapeListItem;
|
class ShapeListItem;
|
||||||
class Selection;
|
class Selection;
|
||||||
@@ -43,15 +44,16 @@ class ShapeListView : public SimpleListView,
|
|||||||
virtual BListItem* CloneItem(int32 atIndex) const;
|
virtual BListItem* CloneItem(int32 atIndex) const;
|
||||||
|
|
||||||
// ShapeContainerListener interface
|
// ShapeContainerListener interface
|
||||||
virtual void ShapeAdded(Shape* shape);
|
virtual void ShapeAdded(Shape* shape, int32 index);
|
||||||
virtual void ShapeRemoved(Shape* shape);
|
virtual void ShapeRemoved(Shape* shape);
|
||||||
|
|
||||||
// ShapeListView
|
// ShapeListView
|
||||||
void SetShapeContainer(ShapeContainer* container);
|
void SetShapeContainer(ShapeContainer* container);
|
||||||
void SetSelection(Selection* selection);
|
void SetSelection(Selection* selection);
|
||||||
|
void SetCommandStack(CommandStack* stack);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _AddShape(Shape* shape);
|
bool _AddShape(Shape* shape, int32 index);
|
||||||
bool _RemoveShape(Shape* shape);
|
bool _RemoveShape(Shape* shape);
|
||||||
|
|
||||||
ShapeListItem* _ItemForShape(Shape* shape) const;
|
ShapeListItem* _ItemForShape(Shape* shape) const;
|
||||||
@@ -61,6 +63,7 @@ class ShapeListView : public SimpleListView,
|
|||||||
|
|
||||||
ShapeContainer* fShapeContainer;
|
ShapeContainer* fShapeContainer;
|
||||||
Selection* fSelection;
|
Selection* fSelection;
|
||||||
|
CommandStack* fCommandStack;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHAPE_LIST_VIEW_H
|
#endif // SHAPE_LIST_VIEW_H
|
||||||
|
|||||||
@@ -34,6 +34,40 @@ Shape::Shape(::Style* style)
|
|||||||
fStyle->Acquire();
|
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
|
// destructor
|
||||||
Shape::~Shape()
|
Shape::~Shape()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class Shape : public Observable,
|
|||||||
public PathContainerListener {
|
public PathContainerListener {
|
||||||
public:
|
public:
|
||||||
Shape(::Style* style);
|
Shape(::Style* style);
|
||||||
|
Shape(const Shape& other);
|
||||||
virtual ~Shape();
|
virtual ~Shape();
|
||||||
|
|
||||||
// PathContainerListener interface
|
// PathContainerListener interface
|
||||||
|
|||||||
@@ -50,6 +50,13 @@ ShapeContainer::~ShapeContainer()
|
|||||||
// AddShape
|
// AddShape
|
||||||
bool
|
bool
|
||||||
ShapeContainer::AddShape(Shape* shape)
|
ShapeContainer::AddShape(Shape* shape)
|
||||||
|
{
|
||||||
|
return AddShape(shape, CountShapes());
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddShape
|
||||||
|
bool
|
||||||
|
ShapeContainer::AddShape(Shape* shape, int32 index)
|
||||||
{
|
{
|
||||||
if (!shape)
|
if (!shape)
|
||||||
return false;
|
return false;
|
||||||
@@ -58,8 +65,8 @@ ShapeContainer::AddShape(Shape* shape)
|
|||||||
if (HasShape(shape))
|
if (HasShape(shape))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (fShapes.AddItem((void*)shape)) {
|
if (fShapes.AddItem((void*)shape, index)) {
|
||||||
_NotifyShapeAdded(shape);
|
_NotifyShapeAdded(shape, index);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,6 +121,13 @@ ShapeContainer::HasShape(Shape* shape) const
|
|||||||
return fShapes.HasItem((void*)shape);
|
return fShapes.HasItem((void*)shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IndexOf
|
||||||
|
int32
|
||||||
|
ShapeContainer::IndexOf(Shape* shape) const
|
||||||
|
{
|
||||||
|
return fShapes.IndexOf((void*)shape);
|
||||||
|
}
|
||||||
|
|
||||||
// ShapeAt
|
// ShapeAt
|
||||||
Shape*
|
Shape*
|
||||||
ShapeContainer::ShapeAt(int32 index) const
|
ShapeContainer::ShapeAt(int32 index) const
|
||||||
@@ -165,14 +179,14 @@ ShapeContainer::_MakeEmpty()
|
|||||||
|
|
||||||
// _NotifyShapeAdded
|
// _NotifyShapeAdded
|
||||||
void
|
void
|
||||||
ShapeContainer::_NotifyShapeAdded(Shape* shape) const
|
ShapeContainer::_NotifyShapeAdded(Shape* shape, int32 index) const
|
||||||
{
|
{
|
||||||
BList listeners(fListeners);
|
BList listeners(fListeners);
|
||||||
int32 count = listeners.CountItems();
|
int32 count = listeners.CountItems();
|
||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
ShapeContainerListener* listener
|
ShapeContainerListener* listener
|
||||||
= (ShapeContainerListener*)listeners.ItemAtFast(i);
|
= (ShapeContainerListener*)listeners.ItemAtFast(i);
|
||||||
listener->ShapeAdded(shape);
|
listener->ShapeAdded(shape, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class ShapeContainerListener {
|
|||||||
ShapeContainerListener();
|
ShapeContainerListener();
|
||||||
virtual ~ShapeContainerListener();
|
virtual ~ShapeContainerListener();
|
||||||
|
|
||||||
virtual void ShapeAdded(Shape* shape) = 0;
|
virtual void ShapeAdded(Shape* shape, int32 index) = 0;
|
||||||
virtual void ShapeRemoved(Shape* shape) = 0;
|
virtual void ShapeRemoved(Shape* shape) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -28,6 +28,7 @@ class ShapeContainer {
|
|||||||
virtual ~ShapeContainer();
|
virtual ~ShapeContainer();
|
||||||
|
|
||||||
bool AddShape(Shape* shape);
|
bool AddShape(Shape* shape);
|
||||||
|
bool AddShape(Shape* shape, int32 index);
|
||||||
bool RemoveShape(Shape* shape);
|
bool RemoveShape(Shape* shape);
|
||||||
Shape* RemoveShape(int32 index);
|
Shape* RemoveShape(int32 index);
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ class ShapeContainer {
|
|||||||
|
|
||||||
int32 CountShapes() const;
|
int32 CountShapes() const;
|
||||||
bool HasShape(Shape* shape) const;
|
bool HasShape(Shape* shape) const;
|
||||||
|
int32 IndexOf(Shape* shape) const;
|
||||||
|
|
||||||
Shape* ShapeAt(int32 index) const;
|
Shape* ShapeAt(int32 index) const;
|
||||||
Shape* ShapeAtFast(int32 index) const;
|
Shape* ShapeAtFast(int32 index) const;
|
||||||
@@ -46,7 +48,8 @@ class ShapeContainer {
|
|||||||
private:
|
private:
|
||||||
void _MakeEmpty();
|
void _MakeEmpty();
|
||||||
|
|
||||||
void _NotifyShapeAdded(Shape* shape) const;
|
void _NotifyShapeAdded(Shape* shape,
|
||||||
|
int32 index) const;
|
||||||
void _NotifyShapeRemoved(Shape* shape) const;
|
void _NotifyShapeRemoved(Shape* shape) const;
|
||||||
|
|
||||||
BList fShapes;
|
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
|
||||||
Reference in New Issue
Block a user