* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "TransformShapesBox.h"
#include <new>
#include <stdio.h>
#include <string.h>
#include "Shape.h"
#include "StateView.h"
#include "TransformObjectsCommand.h"
using std::nothrow;
TransformShapesBox::TransformShapesBox(CanvasView* view,
const Shape** shapes,
int32 count)
: CanvasTransformBox(view),
fShapes(shapes && count > 0 ? new Shape*[count] : NULL),
fCount(count),
fOriginals(NULL),
fParentTransform()
{
if (fShapes != NULL) {
fOriginals = new double[fCount * Transformable::matrix_size];
memcpy(fShapes, shapes, fCount * sizeof(Shape*));
for (int32 i = 0; i < fCount; i++) {
if (fShapes[i]) {
fShapes[i]->AcquireReference();
fShapes[i]->AddObserver(this);
}
}
ObjectChanged(fShapes[0]);
} else {
SetBox(BRect(0, 0, -1, -1));
}
}
TransformShapesBox::~TransformShapesBox()
{
if (fShapes) {
for (int32 i = 0; i < fCount; i++) {
if (fShapes[i]) {
fShapes[i]->RemoveObserver(this);
fShapes[i]->ReleaseReference();
}
}
delete[] fShapes;
}
delete[] fOriginals;
}
void
TransformShapesBox::Update(bool deep)
{
BRect r = Bounds();
TransformBox::Update(deep);
BRect dirty(r | Bounds());
dirty.InsetBy(-8, -8);
fView->Invalidate(dirty);
if (!deep || !fShapes)
return;
for (int32 i = 0; i < fCount; i++) {
if (!fShapes[i])
continue;
fShapes[i]->RemoveObserver(this);
fShapes[i]->SuspendNotifications(true);
fShapes[i]->LoadFrom(&fOriginals[i * Transformable::matrix_size]);
fShapes[i]->Multiply(*this);
fShapes[i]->SuspendNotifications(false);
fShapes[i]->AddObserver(this);
}
}
void
TransformShapesBox::ObjectChanged(const Observable* object)
{
if (!fView->LockLooper())
return;
fParentTransform.Reset();
BRect box(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN);
for (int32 i = 0; i < fCount; i++) {
if (!fShapes[i])
continue;
box = box | fShapes[i]->Bounds();
fShapes[i]->StoreTo(&fOriginals[i * Transformable::matrix_size]);
}
_NotifyDeleted();
Reset();
SetBox(box);
fView->UnlockLooper();
}
TransformCommand*
TransformShapesBox::MakeCommand(const char* commandName)
{
Transformable* objects[fCount];
for (int32 i = 0; i < fCount; i++)
objects[i] = fShapes[i];
return new TransformObjectsCommand(this, objects, fOriginals, fCount,
Pivot(),
Translation(),
LocalRotation(),
LocalXScale(),
LocalYScale(),
commandName);
}