* 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
|
||||
ChangePointCommand.cpp
|
||||
InsertPointCommand.cpp
|
||||
MoveShapesCommand.cpp
|
||||
PathCommand.cpp
|
||||
RemovePointsCommand.cpp
|
||||
RemoveShapesCommand.cpp
|
||||
# style
|
||||
Style.cpp
|
||||
StyleManager.cpp
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,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()
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@ class Shape : public Observable,
|
||||
public PathContainerListener {
|
||||
public:
|
||||
Shape(::Style* style);
|
||||
Shape(const Shape& other);
|
||||
virtual ~Shape();
|
||||
|
||||
// PathContainerListener interface
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user