1 // States.cpp
2
3 #include <View.h>
4
5 #include "States.h"
6
7 // constructor
State()8 State::State()
9 : fValid(false),
10 fEditing(true),
11 fTracking(TRACKING_NONE),
12 fStartPoint(-1.0, -1.0),
13 fEndPoint(-1.0, -1.0),
14 fColor((rgb_color){ 0, 0, 0, 255 }),
15 fDrawingMode(B_OP_COPY),
16 fFill(true),
17 fPenSize(1.0)
18 {
19 }
20
21 // destructor
~State()22 State::~State()
23 {
24 }
25
26 // Init
27 void
Init(rgb_color color,drawing_mode mode,bool fill,float penSize)28 State::Init(rgb_color color, drawing_mode mode, bool fill, float penSize)
29 {
30 fColor = color;
31 fDrawingMode = mode;
32 fFill = fill;
33 fPenSize = penSize;
34 }
35
36 // MouseDown
37 void
MouseDown(BPoint where)38 State::MouseDown(BPoint where)
39 {
40 where.x = floorf(where.x + 0.5);
41 where.y = floorf(where.y + 0.5);
42
43 if (_HitTest(where, fStartPoint)) {
44 fTracking = TRACKING_START;
45 fClickOffset = fStartPoint - where;
46 } else if (_HitTest(where, fEndPoint)) {
47 fTracking = TRACKING_END;
48 fClickOffset = fEndPoint - where;
49 } else if (!fValid) {
50 fTracking = TRACKING_END;
51 fStartPoint = fEndPoint = where;
52 fClickOffset.Set(0.0, 0.0);
53 }
54 }
55
56 // MouseUp
57 void
MouseUp()58 State::MouseUp()
59 {
60 fTracking = TRACKING_NONE;
61 }
62
63 // MouseMoved
64 void
MouseMoved(BPoint where)65 State::MouseMoved(BPoint where)
66 {
67 where.x = floorf(where.x + 0.5);
68 where.y = floorf(where.y + 0.5);
69
70 if (fTracking == TRACKING_START) {
71 fStartPoint = where + fClickOffset;
72 fValid = true;
73 } else if (fTracking == TRACKING_END) {
74 fEndPoint = where + fClickOffset;
75 fValid = true;
76 }
77 }
78
79 // SetColor
80 void
SetColor(rgb_color color)81 State::SetColor(rgb_color color)
82 {
83 fColor = color;
84 }
85
86 // SetDrawingMode
87 void
SetDrawingMode(drawing_mode mode)88 State::SetDrawingMode(drawing_mode mode)
89 {
90 fDrawingMode = mode;
91 }
92
93 // SetFill
94 void
SetFill(bool fill)95 State::SetFill(bool fill)
96 {
97 fFill = fill;
98 }
99
100 // SetPenSize
101 void
SetPenSize(float penSize)102 State::SetPenSize(float penSize)
103 {
104 fPenSize = penSize;
105 }
106
107 // SetEditing
108 void
SetEditing(bool editing)109 State::SetEditing(bool editing)
110 {
111 fEditing = editing;
112 }
113
114 // Bounds
115 BRect
Bounds() const116 State::Bounds() const
117 {
118 if (fValid) {
119 BRect r = _ValidRect();
120 float inset = -2.0; // for the dots
121 if (!SupportsFill() || !fFill) {
122 inset = min_c(inset, -ceilf(fPenSize / 2.0));
123 }
124 r.InsetBy(inset, inset);
125 return r;
126 }
127 return BRect(0.0, 0.0, -1.0, -1.0);
128 }
129
130 // Draw
131 void
Draw(BView * view) const132 State::Draw(BView* view) const
133 {
134 if (fValid && fEditing) {
135 _RenderDot(view, fStartPoint);
136 _RenderDot(view, fEndPoint);
137 }
138 }
139
140 // _ValidRect
141 BRect
_ValidRect() const142 State::_ValidRect() const
143 {
144 return BRect(min_c(fStartPoint.x, fEndPoint.x),
145 min_c(fStartPoint.y, fEndPoint.y),
146 max_c(fStartPoint.x, fEndPoint.x),
147 max_c(fStartPoint.y, fEndPoint.y));
148 }
149
150 // _RenderDot
151 void
_RenderDot(BView * view,BPoint where) const152 State::_RenderDot(BView* view, BPoint where) const
153 {
154 view->SetHighColor(0, 0, 0, 255);
155 view->SetPenSize(1.0);
156 view->SetDrawingMode(B_OP_COPY);
157 BRect r(where, where);
158 r.InsetBy(-2.0, -2.0);
159 view->StrokeRect(r);
160 view->SetHighColor(255, 255, 255, 255);
161 r.InsetBy(1.0, 1.0);
162 view->FillRect(r);
163 }
164
165 // _AdjustViewState
166 void
_AdjustViewState(BView * view) const167 State::_AdjustViewState(BView* view) const
168 {
169 view->SetDrawingMode(fDrawingMode);
170 view->SetHighColor(fColor);
171
172 if (!SupportsFill() || !fFill)
173 view->SetPenSize(fPenSize);
174 }
175
176 // _HitTest
177 bool
_HitTest(BPoint where,BPoint point) const178 State::_HitTest(BPoint where, BPoint point) const
179 {
180 BRect r(point, point);
181 r.InsetBy(-8.0, -8.0);
182 return r.Contains(where);
183 }
184
185 // LineState
186 class LineState : public State {
187 public:
LineState()188 LineState()
189 : State() {}
190
Draw(BView * view) const191 virtual void Draw(BView* view) const
192 {
193 if (fValid) {
194 _AdjustViewState(view);
195 view->StrokeLine(fStartPoint, fEndPoint);
196 }
197 State::Draw(view);
198 }
SupportsFill() const199 virtual bool SupportsFill() const
200 {
201 return false;
202 }
203 };
204
205 // RectState
206 class RectState : public State {
207 public:
RectState()208 RectState()
209 : State() {}
210
Draw(BView * view) const211 virtual void Draw(BView* view) const
212 {
213 if (fValid) {
214 _AdjustViewState(view);
215 if (fFill)
216 view->FillRect(_ValidRect());
217 else
218 view->StrokeRect(_ValidRect());
219 }
220 State::Draw(view);
221 }
222 };
223
224 // RoundRectState
225 class RoundRectState : public State {
226 public:
RoundRectState()227 RoundRectState()
228 : State() {}
229
Draw(BView * view) const230 virtual void Draw(BView* view) const
231 {
232 if (fValid) {
233 _AdjustViewState(view);
234 BRect r = _ValidRect();
235 float radius = min_c(r.Width() / 3.0, r.Height() / 3.0);
236 if (fFill)
237 view->FillRoundRect(r, radius, radius);
238 else
239 view->StrokeRoundRect(r, radius, radius);
240 }
241 State::Draw(view);
242 }
243 };
244
245 // EllipseState
246 class EllipseState : public State {
247 public:
EllipseState()248 EllipseState()
249 : State() {}
250
Draw(BView * view) const251 virtual void Draw(BView* view) const
252 {
253 if (fValid) {
254 _AdjustViewState(view);
255 if (fFill)
256 view->FillEllipse(_ValidRect());
257 else
258 view->StrokeEllipse(_ValidRect());
259 }
260 State::Draw(view);
261 }
262 };
263
264 // StateFor
265 State*
StateFor(int32 objectType,rgb_color color,drawing_mode mode,bool fill,float penSize)266 State::StateFor(int32 objectType, rgb_color color, drawing_mode mode,
267 bool fill, float penSize)
268 {
269 State* state = NULL;
270 switch (objectType) {
271 case OBJECT_LINE:
272 state = new LineState();
273 break;
274 case OBJECT_RECT:
275 state = new RectState();
276 break;
277 case OBJECT_ROUND_RECT:
278 state = new RoundRectState();
279 break;
280 case OBJECT_ELLIPSE:
281 state = new EllipseState();
282 break;
283 default:
284 break;
285 }
286 if (state)
287 state->Init(color, mode, fill, penSize);
288 return state;
289 }
290
291