root/src/tests/servers/app/playground/States.cpp
// States.cpp

#include <View.h>

#include "States.h"

// constructor
State::State()
        : fValid(false),
          fEditing(true),
          fTracking(TRACKING_NONE),
          fStartPoint(-1.0, -1.0),
          fEndPoint(-1.0, -1.0),
          fColor((rgb_color){ 0, 0, 0, 255 }),
          fDrawingMode(B_OP_COPY),
          fFill(true),
          fPenSize(1.0)
{
}

// destructor
State::~State()
{
}

// Init
void
State::Init(rgb_color color, drawing_mode mode, bool fill, float penSize)
{
        fColor = color;
        fDrawingMode = mode;
        fFill = fill;
        fPenSize = penSize;
}

// MouseDown
void
State::MouseDown(BPoint where)
{
        where.x = floorf(where.x + 0.5);
        where.y = floorf(where.y + 0.5);

        if (_HitTest(where, fStartPoint)) {
                fTracking = TRACKING_START;
                fClickOffset = fStartPoint - where;
        } else if (_HitTest(where, fEndPoint)) {
                fTracking = TRACKING_END;
                fClickOffset = fEndPoint - where;
        } else if (!fValid) {
                fTracking = TRACKING_END;
                fStartPoint = fEndPoint = where;
                fClickOffset.Set(0.0, 0.0);
        }
}

// MouseUp
void
State::MouseUp()
{
        fTracking = TRACKING_NONE;
}

// MouseMoved
void
State::MouseMoved(BPoint where)
{
        where.x = floorf(where.x + 0.5);
        where.y = floorf(where.y + 0.5);

        if (fTracking == TRACKING_START) {
                fStartPoint = where + fClickOffset;
                fValid = true;
        } else if (fTracking == TRACKING_END) {
                fEndPoint = where + fClickOffset;
                fValid = true;
        }
}

// SetColor
void
State::SetColor(rgb_color color)
{
        fColor = color;
}

// SetDrawingMode
void
State::SetDrawingMode(drawing_mode mode)
{
        fDrawingMode = mode;
}

// SetFill
void
State::SetFill(bool fill)
{
        fFill = fill;
}

// SetPenSize
void
State::SetPenSize(float penSize)
{
        fPenSize = penSize;
}

// SetEditing
void
State::SetEditing(bool editing)
{
        fEditing = editing;
}

// Bounds
BRect
State::Bounds() const
{
        if (fValid) {
                BRect r = _ValidRect();
                float inset = -2.0; // for the dots
                if (!SupportsFill() || !fFill) {
                        inset = min_c(inset, -ceilf(fPenSize / 2.0));
                }
                r.InsetBy(inset, inset);
                return r;
        }
        return BRect(0.0, 0.0, -1.0, -1.0);
}

// Draw
void
State::Draw(BView* view) const
{
        if (fValid && fEditing) {
                _RenderDot(view, fStartPoint);
                _RenderDot(view, fEndPoint);
        }
}

// _ValidRect
BRect
State::_ValidRect() const
{
        return BRect(min_c(fStartPoint.x, fEndPoint.x),
                                 min_c(fStartPoint.y, fEndPoint.y),
                                 max_c(fStartPoint.x, fEndPoint.x),
                                 max_c(fStartPoint.y, fEndPoint.y));
}

// _RenderDot
void
State::_RenderDot(BView* view, BPoint where) const
{
        view->SetHighColor(0, 0, 0, 255);
        view->SetPenSize(1.0);
        view->SetDrawingMode(B_OP_COPY);
        BRect r(where, where);
        r.InsetBy(-2.0, -2.0);
        view->StrokeRect(r);
        view->SetHighColor(255, 255, 255, 255);
        r.InsetBy(1.0, 1.0);
        view->FillRect(r);
}

// _AdjustViewState
void
State::_AdjustViewState(BView* view) const
{
        view->SetDrawingMode(fDrawingMode);
        view->SetHighColor(fColor);

        if (!SupportsFill() || !fFill)
                view->SetPenSize(fPenSize);
}

// _HitTest
bool
State::_HitTest(BPoint where, BPoint point) const
{
        BRect r(point, point);
        r.InsetBy(-8.0, -8.0);
        return r.Contains(where);
}

// LineState
class LineState : public State {
 public:
                                        LineState()
                                                : State() {}

        virtual void    Draw(BView* view) const
                                        {
                                                if (fValid) {
                                                        _AdjustViewState(view);
                                                        view->StrokeLine(fStartPoint, fEndPoint);
                                                }
                                                State::Draw(view);
                                        }
        virtual bool    SupportsFill() const
                                        {
                                                return false;
                                        }
};

// RectState
class RectState : public State {
 public:
                                        RectState()
                                                : State() {}

        virtual void    Draw(BView* view) const
                                        {
                                                if (fValid) {
                                                        _AdjustViewState(view);
                                                        if (fFill)
                                                                view->FillRect(_ValidRect());
                                                        else
                                                                view->StrokeRect(_ValidRect());
                                                }
                                                State::Draw(view);
                                        }
};

// RoundRectState
class RoundRectState : public State {
 public:
                                        RoundRectState()
                                                : State() {}

        virtual void    Draw(BView* view) const
                                        {
                                                if (fValid) {
                                                        _AdjustViewState(view);
                                                        BRect r = _ValidRect();
                                                        float radius = min_c(r.Width() / 3.0, r.Height() / 3.0);
                                                        if (fFill)
                                                                view->FillRoundRect(r, radius, radius);
                                                        else
                                                                view->StrokeRoundRect(r, radius, radius);
                                                }
                                                State::Draw(view);
                                        }
};

// EllipseState
class EllipseState : public State {
 public:
                                        EllipseState()
                                                : State() {}

        virtual void    Draw(BView* view) const
                                        {
                                                if (fValid) {
                                                        _AdjustViewState(view);
                                                        if (fFill)
                                                                view->FillEllipse(_ValidRect());
                                                        else
                                                                view->StrokeEllipse(_ValidRect());
                                                }
                                                State::Draw(view);
                                        }
};

// StateFor
State*
State::StateFor(int32 objectType, rgb_color color, drawing_mode mode,
                                bool fill, float penSize)
{
        State* state = NULL;
        switch (objectType) {
                case OBJECT_LINE:
                        state = new LineState();
                        break;
                case OBJECT_RECT:
                        state = new RectState();
                        break;
                case OBJECT_ROUND_RECT:
                        state = new RoundRectState();
                        break;
                case OBJECT_ELLIPSE:
                        state = new EllipseState();
                        break;
                default:
                        break;
        }
        if (state)
                state->Init(color, mode, fill, penSize);
        return state;
}