[RAPPS] Bulk install!
[reactos.git] / reactos / base / applications / mspaint / mouse.cpp
1 /*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/mspaint/mouse.cpp
5 * PURPOSE: Things which should not be in the mouse event handler itself
6 * PROGRAMMERS: Benedikt Freisen
7 */
8
9 /* INCLUDES *********************************************************/
10
11 #include "precomp.h"
12
13 /* FUNCTIONS ********************************************************/
14
15 void
16 placeSelWin()
17 {
18 selectionWindow.MoveWindow(selectionModel.GetDestRectLeft() * toolsModel.GetZoom() / 1000, selectionModel.GetDestRectTop() * toolsModel.GetZoom() / 1000,
19 selectionModel.GetDestRectWidth() * toolsModel.GetZoom() / 1000 + 6, selectionModel.GetDestRectHeight() * toolsModel.GetZoom() / 1000 + 6, TRUE);
20 selectionWindow.BringWindowToTop();
21 imageArea.InvalidateRect(NULL, FALSE);
22 }
23
24 void
25 regularize(LONG x0, LONG y0, LONG& x1, LONG& y1)
26 {
27 if (abs(x1 - x0) >= abs(y1 - y0))
28 y1 = y0 + (y1 > y0 ? abs(x1 - x0) : -abs(x1 - x0));
29 else
30 x1 = x0 + (x1 > x0 ? abs(y1 - y0) : -abs(y1 - y0));
31 }
32
33 void
34 roundTo8Directions(LONG x0, LONG y0, LONG& x1, LONG& y1)
35 {
36 if (abs(x1 - x0) >= abs(y1 - y0))
37 {
38 if (abs(y1 - y0) * 5 < abs(x1 - x0) * 2)
39 y1 = y0;
40 else
41 y1 = y0 + (y1 > y0 ? abs(x1 - x0) : -abs(x1 - x0));
42 }
43 else
44 {
45 if (abs(x1 - x0) * 5 < abs(y1 - y0) * 2)
46 x1 = x0;
47 else
48 x1 = x0 + (x1 > x0 ? abs(y1 - y0) : -abs(y1 - y0));
49 }
50 }
51
52 POINT pointStack[256];
53 short pointSP;
54
55 void
56 startPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
57 {
58 start.x = x;
59 start.y = y;
60 last.x = x;
61 last.y = y;
62 switch (toolsModel.GetActiveTool())
63 {
64 case TOOL_FREESEL:
65 selectionWindow.ShowWindow(SW_HIDE);
66 selectionModel.ResetPtStack();
67 selectionModel.PushToPtStack(x, y);
68 break;
69 case TOOL_LINE:
70 case TOOL_RECT:
71 case TOOL_ELLIPSE:
72 case TOOL_RRECT:
73 imageModel.CopyPrevious();
74 break;
75 case TOOL_RECTSEL:
76 case TOOL_TEXT:
77 imageModel.CopyPrevious();
78 selectionWindow.ShowWindow(SW_HIDE);
79 selectionModel.SetSrcRectSizeToZero();
80 break;
81 case TOOL_RUBBER:
82 imageModel.CopyPrevious();
83 Erase(hdc, x, y, x, y, bg, toolsModel.GetRubberRadius());
84 break;
85 case TOOL_FILL:
86 imageModel.CopyPrevious();
87 Fill(hdc, x, y, fg);
88 break;
89 case TOOL_PEN:
90 imageModel.CopyPrevious();
91 SetPixel(hdc, x, y, fg);
92 break;
93 case TOOL_BRUSH:
94 imageModel.CopyPrevious();
95 Brush(hdc, x, y, x, y, fg, toolsModel.GetBrushStyle());
96 break;
97 case TOOL_AIRBRUSH:
98 imageModel.CopyPrevious();
99 Airbrush(hdc, x, y, fg, toolsModel.GetAirBrushWidth());
100 break;
101 case TOOL_BEZIER:
102 pointStack[pointSP].x = x;
103 pointStack[pointSP].y = y;
104 if (pointSP == 0)
105 {
106 imageModel.CopyPrevious();
107 pointSP++;
108 }
109 break;
110 case TOOL_SHAPE:
111 pointStack[pointSP].x = x;
112 pointStack[pointSP].y = y;
113 if (pointSP + 1 >= 2)
114 Poly(hdc, pointStack, pointSP + 1, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
115 if (pointSP == 0)
116 {
117 imageModel.CopyPrevious();
118 pointSP++;
119 }
120 break;
121 }
122 }
123
124 void
125 whilePaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
126 {
127 switch (toolsModel.GetActiveTool())
128 {
129 case TOOL_FREESEL:
130 if (selectionModel.PtStackSize() == 1)
131 imageModel.CopyPrevious();
132 selectionModel.PushToPtStack(max(0, min(x, imageModel.GetWidth())), max(0, min(y, imageModel.GetHeight())));
133 imageModel.ResetToPrevious();
134 selectionModel.DrawFramePoly(hdc);
135 break;
136 case TOOL_RECTSEL:
137 case TOOL_TEXT:
138 {
139 POINT temp;
140 imageModel.ResetToPrevious();
141 temp.x = max(0, min(x, imageModel.GetWidth()));
142 temp.y = max(0, min(y, imageModel.GetHeight()));
143 selectionModel.SetSrcAndDestRectFromPoints(start, temp);
144 RectSel(hdc, start.x, start.y, temp.x, temp.y);
145 break;
146 }
147 case TOOL_RUBBER:
148 Erase(hdc, last.x, last.y, x, y, bg, toolsModel.GetRubberRadius());
149 break;
150 case TOOL_PEN:
151 Line(hdc, last.x, last.y, x, y, fg, 1);
152 break;
153 case TOOL_BRUSH:
154 Brush(hdc, last.x, last.y, x, y, fg, toolsModel.GetBrushStyle());
155 break;
156 case TOOL_AIRBRUSH:
157 Airbrush(hdc, x, y, fg, toolsModel.GetAirBrushWidth());
158 break;
159 case TOOL_LINE:
160 imageModel.ResetToPrevious();
161 if (GetAsyncKeyState(VK_SHIFT) < 0)
162 roundTo8Directions(start.x, start.y, x, y);
163 Line(hdc, start.x, start.y, x, y, fg, toolsModel.GetLineWidth());
164 break;
165 case TOOL_BEZIER:
166 imageModel.ResetToPrevious();
167 pointStack[pointSP].x = x;
168 pointStack[pointSP].y = y;
169 switch (pointSP)
170 {
171 case 1:
172 Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, fg,
173 toolsModel.GetLineWidth());
174 break;
175 case 2:
176 Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], fg, toolsModel.GetLineWidth());
177 break;
178 case 3:
179 Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], fg, toolsModel.GetLineWidth());
180 break;
181 }
182 break;
183 case TOOL_RECT:
184 imageModel.ResetToPrevious();
185 if (GetAsyncKeyState(VK_SHIFT) < 0)
186 regularize(start.x, start.y, x, y);
187 Rect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
188 break;
189 case TOOL_SHAPE:
190 imageModel.ResetToPrevious();
191 pointStack[pointSP].x = x;
192 pointStack[pointSP].y = y;
193 if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
194 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y,
195 pointStack[pointSP].x, pointStack[pointSP].y);
196 if (pointSP + 1 >= 2)
197 Poly(hdc, pointStack, pointSP + 1, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
198 break;
199 case TOOL_ELLIPSE:
200 imageModel.ResetToPrevious();
201 if (GetAsyncKeyState(VK_SHIFT) < 0)
202 regularize(start.x, start.y, x, y);
203 Ellp(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
204 break;
205 case TOOL_RRECT:
206 imageModel.ResetToPrevious();
207 if (GetAsyncKeyState(VK_SHIFT) < 0)
208 regularize(start.x, start.y, x, y);
209 RRect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
210 break;
211 }
212
213 last.x = x;
214 last.y = y;
215 }
216
217 void
218 endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
219 {
220 switch (toolsModel.GetActiveTool())
221 {
222 case TOOL_FREESEL:
223 {
224 selectionModel.CalculateBoundingBoxAndContents(hdc);
225 if (selectionModel.PtStackSize() > 1)
226 {
227 selectionModel.DrawBackgroundPoly(hdc, bg);
228 imageModel.CopyPrevious();
229
230 selectionModel.DrawSelection(hdc);
231
232 placeSelWin();
233 selectionWindow.ShowWindow(SW_SHOW);
234 ForceRefreshSelectionContents();
235 }
236 selectionModel.ResetPtStack();
237 break;
238 }
239 case TOOL_RECTSEL:
240 imageModel.ResetToPrevious();
241 if (selectionModel.IsSrcRectSizeNonzero())
242 {
243 selectionModel.CalculateContents(hdc);
244 selectionModel.DrawBackgroundRect(hdc, bg);
245 imageModel.CopyPrevious();
246
247 selectionModel.DrawSelection(hdc);
248
249 placeSelWin();
250 selectionWindow.ShowWindow(SW_SHOW);
251 ForceRefreshSelectionContents();
252 }
253 break;
254 case TOOL_TEXT:
255 imageModel.ResetToPrevious();
256 if (selectionModel.IsSrcRectSizeNonzero())
257 {
258 imageModel.CopyPrevious();
259
260 placeSelWin();
261 selectionWindow.ShowWindow(SW_SHOW);
262 ForceRefreshSelectionContents();
263 }
264 break;
265 case TOOL_RUBBER:
266 Erase(hdc, last.x, last.y, x, y, bg, toolsModel.GetRubberRadius());
267 break;
268 case TOOL_PEN:
269 Line(hdc, last.x, last.y, x, y, fg, 1);
270 SetPixel(hdc, x, y, fg);
271 break;
272 case TOOL_LINE:
273 imageModel.ResetToPrevious();
274 if (GetAsyncKeyState(VK_SHIFT) < 0)
275 roundTo8Directions(start.x, start.y, x, y);
276 Line(hdc, start.x, start.y, x, y, fg, toolsModel.GetLineWidth());
277 break;
278 case TOOL_BEZIER:
279 pointSP++;
280 if (pointSP == 4)
281 pointSP = 0;
282 break;
283 case TOOL_RECT:
284 imageModel.ResetToPrevious();
285 if (GetAsyncKeyState(VK_SHIFT) < 0)
286 regularize(start.x, start.y, x, y);
287 Rect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
288 break;
289 case TOOL_SHAPE:
290 imageModel.ResetToPrevious();
291 pointStack[pointSP].x = x;
292 pointStack[pointSP].y = y;
293 if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
294 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y,
295 pointStack[pointSP].x, pointStack[pointSP].y);
296 pointSP++;
297 if (pointSP >= 2)
298 {
299 if ((pointStack[0].x - x) * (pointStack[0].x - x) +
300 (pointStack[0].y - y) * (pointStack[0].y - y) <= toolsModel.GetLineWidth() * toolsModel.GetLineWidth() + 1)
301 {
302 Poly(hdc, pointStack, pointSP, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), TRUE, FALSE);
303 pointSP = 0;
304 }
305 else
306 {
307 Poly(hdc, pointStack, pointSP, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
308 }
309 }
310 if (pointSP == 255)
311 pointSP--;
312 break;
313 case TOOL_ELLIPSE:
314 imageModel.ResetToPrevious();
315 if (GetAsyncKeyState(VK_SHIFT) < 0)
316 regularize(start.x, start.y, x, y);
317 Ellp(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
318 break;
319 case TOOL_RRECT:
320 imageModel.ResetToPrevious();
321 if (GetAsyncKeyState(VK_SHIFT) < 0)
322 regularize(start.x, start.y, x, y);
323 RRect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
324 break;
325 }
326 }
327
328 void
329 startPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
330 {
331 start.x = x;
332 start.y = y;
333 last.x = x;
334 last.y = y;
335 switch (toolsModel.GetActiveTool())
336 {
337 case TOOL_FREESEL:
338 case TOOL_TEXT:
339 case TOOL_LINE:
340 case TOOL_RECT:
341 case TOOL_ELLIPSE:
342 case TOOL_RRECT:
343 imageModel.CopyPrevious();
344 break;
345 case TOOL_RUBBER:
346 imageModel.CopyPrevious();
347 Replace(hdc, x, y, x, y, fg, bg, toolsModel.GetRubberRadius());
348 break;
349 case TOOL_FILL:
350 imageModel.CopyPrevious();
351 Fill(hdc, x, y, bg);
352 break;
353 case TOOL_PEN:
354 imageModel.CopyPrevious();
355 SetPixel(hdc, x, y, bg);
356 break;
357 case TOOL_BRUSH:
358 imageModel.CopyPrevious();
359 Brush(hdc, x, y, x, y, bg, toolsModel.GetBrushStyle());
360 break;
361 case TOOL_AIRBRUSH:
362 imageModel.CopyPrevious();
363 Airbrush(hdc, x, y, bg, toolsModel.GetAirBrushWidth());
364 break;
365 case TOOL_BEZIER:
366 pointStack[pointSP].x = x;
367 pointStack[pointSP].y = y;
368 if (pointSP == 0)
369 {
370 imageModel.CopyPrevious();
371 pointSP++;
372 }
373 break;
374 case TOOL_SHAPE:
375 pointStack[pointSP].x = x;
376 pointStack[pointSP].y = y;
377 if (pointSP + 1 >= 2)
378 Poly(hdc, pointStack, pointSP + 1, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
379 if (pointSP == 0)
380 {
381 imageModel.CopyPrevious();
382 pointSP++;
383 }
384 break;
385 }
386 }
387
388 void
389 whilePaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
390 {
391 switch (toolsModel.GetActiveTool())
392 {
393 case TOOL_RUBBER:
394 Replace(hdc, last.x, last.y, x, y, fg, bg, toolsModel.GetRubberRadius());
395 break;
396 case TOOL_PEN:
397 Line(hdc, last.x, last.y, x, y, bg, 1);
398 break;
399 case TOOL_BRUSH:
400 Brush(hdc, last.x, last.y, x, y, bg, toolsModel.GetBrushStyle());
401 break;
402 case TOOL_AIRBRUSH:
403 Airbrush(hdc, x, y, bg, toolsModel.GetAirBrushWidth());
404 break;
405 case TOOL_LINE:
406 imageModel.ResetToPrevious();
407 if (GetAsyncKeyState(VK_SHIFT) < 0)
408 roundTo8Directions(start.x, start.y, x, y);
409 Line(hdc, start.x, start.y, x, y, bg, toolsModel.GetLineWidth());
410 break;
411 case TOOL_BEZIER:
412 imageModel.ResetToPrevious();
413 pointStack[pointSP].x = x;
414 pointStack[pointSP].y = y;
415 switch (pointSP)
416 {
417 case 1:
418 Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, bg,
419 toolsModel.GetLineWidth());
420 break;
421 case 2:
422 Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], bg, toolsModel.GetLineWidth());
423 break;
424 case 3:
425 Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], bg, toolsModel.GetLineWidth());
426 break;
427 }
428 break;
429 case TOOL_RECT:
430 imageModel.ResetToPrevious();
431 if (GetAsyncKeyState(VK_SHIFT) < 0)
432 regularize(start.x, start.y, x, y);
433 Rect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
434 break;
435 case TOOL_SHAPE:
436 imageModel.ResetToPrevious();
437 pointStack[pointSP].x = x;
438 pointStack[pointSP].y = y;
439 if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
440 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y,
441 pointStack[pointSP].x, pointStack[pointSP].y);
442 if (pointSP + 1 >= 2)
443 Poly(hdc, pointStack, pointSP + 1, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
444 break;
445 case TOOL_ELLIPSE:
446 imageModel.ResetToPrevious();
447 if (GetAsyncKeyState(VK_SHIFT) < 0)
448 regularize(start.x, start.y, x, y);
449 Ellp(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
450 break;
451 case TOOL_RRECT:
452 imageModel.ResetToPrevious();
453 if (GetAsyncKeyState(VK_SHIFT) < 0)
454 regularize(start.x, start.y, x, y);
455 RRect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
456 break;
457 }
458
459 last.x = x;
460 last.y = y;
461 }
462
463 void
464 endPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
465 {
466 switch (toolsModel.GetActiveTool())
467 {
468 case TOOL_RUBBER:
469 Replace(hdc, last.x, last.y, x, y, fg, bg, toolsModel.GetRubberRadius());
470 break;
471 case TOOL_PEN:
472 Line(hdc, last.x, last.y, x, y, bg, 1);
473 SetPixel(hdc, x, y, bg);
474 break;
475 case TOOL_LINE:
476 imageModel.ResetToPrevious();
477 if (GetAsyncKeyState(VK_SHIFT) < 0)
478 roundTo8Directions(start.x, start.y, x, y);
479 Line(hdc, start.x, start.y, x, y, bg, toolsModel.GetLineWidth());
480 break;
481 case TOOL_BEZIER:
482 pointSP++;
483 if (pointSP == 4)
484 pointSP = 0;
485 break;
486 case TOOL_RECT:
487 imageModel.ResetToPrevious();
488 if (GetAsyncKeyState(VK_SHIFT) < 0)
489 regularize(start.x, start.y, x, y);
490 Rect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
491 break;
492 case TOOL_SHAPE:
493 imageModel.ResetToPrevious();
494 pointStack[pointSP].x = x;
495 pointStack[pointSP].y = y;
496 if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
497 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y,
498 pointStack[pointSP].x, pointStack[pointSP].y);
499 pointSP++;
500 if (pointSP >= 2)
501 {
502 if ((pointStack[0].x - x) * (pointStack[0].x - x) +
503 (pointStack[0].y - y) * (pointStack[0].y - y) <= toolsModel.GetLineWidth() * toolsModel.GetLineWidth() + 1)
504 {
505 Poly(hdc, pointStack, pointSP, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), TRUE, FALSE);
506 pointSP = 0;
507 }
508 else
509 {
510 Poly(hdc, pointStack, pointSP, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
511 }
512 }
513 if (pointSP == 255)
514 pointSP--;
515 break;
516 case TOOL_ELLIPSE:
517 imageModel.ResetToPrevious();
518 if (GetAsyncKeyState(VK_SHIFT) < 0)
519 regularize(start.x, start.y, x, y);
520 Ellp(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
521 break;
522 case TOOL_RRECT:
523 imageModel.ResetToPrevious();
524 if (GetAsyncKeyState(VK_SHIFT) < 0)
525 regularize(start.x, start.y, x, y);
526 RRect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
527 break;
528 }
529 }