* Copyright 2006-2009, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "TransformGradientBox.h"
#include <new>
#include <stdio.h>
#include <string.h>
#include "CanvasView.h"
#include "GradientTransformable.h"
#include "Shape.h"
#include "StateView.h"
#include "TransformGradientCommand.h"
using std::nothrow;
TransformGradientBox::TransformGradientBox(CanvasView* view, Gradient* gradient,
Shape* parentShape)
:
TransformBox(view, BRect(0.0, 0.0, 1.0, 1.0)),
fCanvasView(view),
fShape(parentShape),
fGradient(gradient)
{
if (fShape) {
fShape->AcquireReference();
fShape->AddObserver(this);
}
if (fGradient.IsSet()) {
ObjectChanged(fGradient);
} else {
SetBox(BRect(0, 0, -1, -1));
}
}
TransformGradientBox::~TransformGradientBox()
{
if (fShape) {
fShape->RemoveObserver(this);
fShape->ReleaseReference();
}
if (fGradient.IsSet()) {
fGradient->RemoveObserver(this);
}
}
void
TransformGradientBox::Update(bool deep)
{
BRect r = Bounds();
TransformBox::Update(deep);
BRect dirty(r | Bounds());
dirty.InsetBy(-8, -8);
fView->Invalidate(dirty);
if (!deep || !fGradient.IsSet())
return;
fGradient->RemoveObserver(this);
fGradient->SuspendNotifications(true);
fGradient->Reset();
fGradient->Multiply(*this);
fGradient->SuspendNotifications(false);
fGradient->AddObserver(this);
}
void
TransformGradientBox::ObjectChanged(const Observable* object)
{
if (!fGradient.IsSet() || !fView->LockLooper())
return;
if (object == fShape) {
fView->Invalidate(Bounds());
fView->UnlockLooper();
return;
}
_NotifyDeleted();
fGradient->StoreTo(fOriginals);
SetTransformation(*fGradient);
SetBox(fGradient->GradientArea());
fView->UnlockLooper();
}
Command*
TransformGradientBox::Perform()
{
return NULL;
}
Command*
TransformGradientBox::Cancel()
{
SetTransformation(B_ORIGIN, B_ORIGIN, 0.0, 1.0, 1.0);
return NULL;
}
void
TransformGradientBox::TransformFromCanvas(BPoint& point) const
{
if (fShape)
fShape->InverseTransform(&point);
fCanvasView->ConvertFromCanvas(&point);
}
void
TransformGradientBox::TransformToCanvas(BPoint& point) const
{
fCanvasView->ConvertToCanvas(&point);
if (fShape)
fShape->Transform(&point);
}
float
TransformGradientBox::ZoomLevel() const
{
return fCanvasView->ZoomLevel();
}
double
TransformGradientBox::ViewSpaceRotation() const
{
Transformable t(*this);
if (fShape)
t.Multiply(*fShape);
return t.rotation() * 180.0 / M_PI;
}
TransformCommand*
TransformGradientBox::MakeCommand(const char* commandName)
{
return new TransformGradientCommand(this, fGradient, Pivot(),
Translation(), LocalRotation(), LocalXScale(), LocalYScale(),
commandName);
}