// States.cpp #include #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; }