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