xref: /reactos/base/applications/mspaint/mouse.cpp (revision 3799d37a)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:    PAINT for ReactOS
38f1f1c7aSStanislav Motylkov  * LICENSE:    LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4c2c66affSColin Finck  * PURPOSE:    Things which should not be in the mouse event handler itself
5f5200e6cSStanislav Motylkov  * COPYRIGHT:  Copyright 2015 Benedikt Freisen <b.freisen@gmx.net>
6fa4b38d9SKatayama Hirofumi MZ  *             Copyright 2021-2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
7c2c66affSColin Finck  */
8c2c66affSColin Finck 
9c2c66affSColin Finck #include "precomp.h"
10e5792200SKatayama Hirofumi MZ #include <atlalloc.h>
11c2c66affSColin Finck 
12*3799d37aSKatayama Hirofumi MZ static SIZE_T s_cPoints = 0;
13*3799d37aSKatayama Hirofumi MZ static CHeapPtr<POINT, CLocalAllocator> s_dynamicPoints;
14*3799d37aSKatayama Hirofumi MZ static POINT s_staticPoints[512]; // 512 is enough
15*3799d37aSKatayama Hirofumi MZ static SIZE_T s_maxPoints = _countof(s_staticPoints);
16*3799d37aSKatayama Hirofumi MZ static LPPOINT s_pPoints = s_staticPoints;
17fa4b38d9SKatayama Hirofumi MZ static POINT g_ptStart, g_ptEnd;
18ee132a05SKatayama Hirofumi MZ 
19c2c66affSColin Finck /* FUNCTIONS ********************************************************/
20c2c66affSColin Finck 
21c2c66affSColin Finck void
regularize(LONG x0,LONG y0,LONG & x1,LONG & y1)22c2c66affSColin Finck regularize(LONG x0, LONG y0, LONG& x1, LONG& y1)
23c2c66affSColin Finck {
24389d0465SKatayama Hirofumi MZ     if (labs(x1 - x0) >= labs(y1 - y0))
25389d0465SKatayama Hirofumi MZ         y1 = y0 + (y1 > y0 ? labs(x1 - x0) : -labs(x1 - x0));
26c2c66affSColin Finck     else
27389d0465SKatayama Hirofumi MZ         x1 = x0 + (x1 > x0 ? labs(y1 - y0) : -labs(y1 - y0));
28c2c66affSColin Finck }
29c2c66affSColin Finck 
30c2c66affSColin Finck void
roundTo8Directions(LONG x0,LONG y0,LONG & x1,LONG & y1)31c2c66affSColin Finck roundTo8Directions(LONG x0, LONG y0, LONG& x1, LONG& y1)
32c2c66affSColin Finck {
33389d0465SKatayama Hirofumi MZ     if (labs(x1 - x0) >= labs(y1 - y0))
34c2c66affSColin Finck     {
35389d0465SKatayama Hirofumi MZ         if (labs(y1 - y0) * 5 < labs(x1 - x0) * 2)
36c2c66affSColin Finck             y1 = y0;
37c2c66affSColin Finck         else
38389d0465SKatayama Hirofumi MZ             y1 = y0 + (y1 > y0 ? labs(x1 - x0) : -labs(x1 - x0));
39c2c66affSColin Finck     }
40c2c66affSColin Finck     else
41c2c66affSColin Finck     {
42389d0465SKatayama Hirofumi MZ         if (labs(x1 - x0) * 5 < labs(y1 - y0) * 2)
43c2c66affSColin Finck             x1 = x0;
44c2c66affSColin Finck         else
45389d0465SKatayama Hirofumi MZ             x1 = x0 + (x1 > x0 ? labs(y1 - y0) : -labs(y1 - y0));
46c2c66affSColin Finck     }
47c2c66affSColin Finck }
48c2c66affSColin Finck 
nearlyEqualPoints(INT x0,INT y0,INT x1,INT y1)49ce54a8a5SKatayama Hirofumi MZ BOOL nearlyEqualPoints(INT x0, INT y0, INT x1, INT y1)
50ce54a8a5SKatayama Hirofumi MZ {
51ce54a8a5SKatayama Hirofumi MZ     INT cxThreshold = toolsModel.GetLineWidth() + UnZoomed(GetSystemMetrics(SM_CXDRAG));
52ce54a8a5SKatayama Hirofumi MZ     INT cyThreshold = toolsModel.GetLineWidth() + UnZoomed(GetSystemMetrics(SM_CYDRAG));
53ce54a8a5SKatayama Hirofumi MZ     return (abs(x1 - x0) <= cxThreshold) && (abs(y1 - y0) <= cyThreshold);
54ce54a8a5SKatayama Hirofumi MZ }
55ce54a8a5SKatayama Hirofumi MZ 
getBoundaryOfPoints(RECT & rcBoundary,SIZE_T cPoints,const POINT * pPoints)56*3799d37aSKatayama Hirofumi MZ void getBoundaryOfPoints(RECT& rcBoundary, SIZE_T cPoints, const POINT *pPoints)
57e5792200SKatayama Hirofumi MZ {
58e5792200SKatayama Hirofumi MZ     POINT ptMin = { MAXLONG, MAXLONG }, ptMax = { (LONG)MINLONG, (LONG)MINLONG };
59e5792200SKatayama Hirofumi MZ     while (cPoints-- > 0)
60e5792200SKatayama Hirofumi MZ     {
61e5792200SKatayama Hirofumi MZ         LONG x = pPoints->x, y = pPoints->y;
62e5792200SKatayama Hirofumi MZ         ptMin = { min(x, ptMin.x), min(y, ptMin.y) };
63e5792200SKatayama Hirofumi MZ         ptMax = { max(x, ptMax.x), max(y, ptMax.y) };
64e5792200SKatayama Hirofumi MZ         ++pPoints;
65e5792200SKatayama Hirofumi MZ     }
66e5792200SKatayama Hirofumi MZ 
67e5792200SKatayama Hirofumi MZ     ptMax.x += 1;
68e5792200SKatayama Hirofumi MZ     ptMax.y += 1;
69e5792200SKatayama Hirofumi MZ 
70e5792200SKatayama Hirofumi MZ     CRect rc(ptMin, ptMax);
71e5792200SKatayama Hirofumi MZ     rcBoundary = rc;
72e5792200SKatayama Hirofumi MZ }
73e5792200SKatayama Hirofumi MZ 
ShiftPoints(INT dx,INT dy)74*3799d37aSKatayama Hirofumi MZ void ShiftPoints(INT dx, INT dy)
75b8598e09SKatayama Hirofumi MZ {
76*3799d37aSKatayama Hirofumi MZ     for (SIZE_T i = 0; i < s_cPoints; ++i)
77b8598e09SKatayama Hirofumi MZ     {
78*3799d37aSKatayama Hirofumi MZ         POINT& pt = s_pPoints[i];
79b8598e09SKatayama Hirofumi MZ         pt.x += dx;
80b8598e09SKatayama Hirofumi MZ         pt.y += dy;
81b8598e09SKatayama Hirofumi MZ     }
82b8598e09SKatayama Hirofumi MZ }
83b8598e09SKatayama Hirofumi MZ 
BuildMaskFromPoints()84*3799d37aSKatayama Hirofumi MZ void BuildMaskFromPoints()
85b8598e09SKatayama Hirofumi MZ {
86b8598e09SKatayama Hirofumi MZ     CRect rc;
87*3799d37aSKatayama Hirofumi MZ     getBoundaryOfPoints(rc, s_cPoints, s_pPoints);
88b8598e09SKatayama Hirofumi MZ 
89*3799d37aSKatayama Hirofumi MZ     ShiftPoints(-rc.left, -rc.top);
90b8598e09SKatayama Hirofumi MZ 
91b8598e09SKatayama Hirofumi MZ     HDC hdcMem = ::CreateCompatibleDC(NULL);
92b8598e09SKatayama Hirofumi MZ     HBITMAP hbmMask = ::CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL);
93b8598e09SKatayama Hirofumi MZ     HGDIOBJ hbmOld = ::SelectObject(hdcMem, hbmMask);
94b8598e09SKatayama Hirofumi MZ     ::FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH));
95b8598e09SKatayama Hirofumi MZ     HGDIOBJ hPenOld = ::SelectObject(hdcMem, GetStockObject(NULL_PEN));
96b8598e09SKatayama Hirofumi MZ     HGDIOBJ hbrOld = ::SelectObject(hdcMem, GetStockObject(WHITE_BRUSH));
97*3799d37aSKatayama Hirofumi MZ     ::Polygon(hdcMem, s_pPoints, (INT)s_cPoints);
98b8598e09SKatayama Hirofumi MZ     ::SelectObject(hdcMem, hbrOld);
99b8598e09SKatayama Hirofumi MZ     ::SelectObject(hdcMem, hPenOld);
100b8598e09SKatayama Hirofumi MZ     ::SelectObject(hdcMem, hbmOld);
101b8598e09SKatayama Hirofumi MZ     ::DeleteDC(hdcMem);
102b8598e09SKatayama Hirofumi MZ 
103b8598e09SKatayama Hirofumi MZ     selectionModel.setMask(rc, hbmMask);
104b8598e09SKatayama Hirofumi MZ }
105b8598e09SKatayama Hirofumi MZ 
reset()106ee132a05SKatayama Hirofumi MZ void ToolBase::reset()
107c2c66affSColin Finck {
108*3799d37aSKatayama Hirofumi MZ     if (s_pPoints != s_staticPoints)
109b8598e09SKatayama Hirofumi MZ     {
110*3799d37aSKatayama Hirofumi MZ         s_dynamicPoints.Free();
111*3799d37aSKatayama Hirofumi MZ         s_pPoints = s_staticPoints;
112*3799d37aSKatayama Hirofumi MZ         s_maxPoints = _countof(s_staticPoints);
113b8598e09SKatayama Hirofumi MZ     }
114b8598e09SKatayama Hirofumi MZ 
115*3799d37aSKatayama Hirofumi MZ     s_cPoints = 0;
116e5792200SKatayama Hirofumi MZ     g_ptEnd = g_ptStart = { -1, -1 };
117e5792200SKatayama Hirofumi MZ 
118aac89519SKatayama Hirofumi MZ     if (selectionModel.m_bShow)
119aac89519SKatayama Hirofumi MZ     {
120aac89519SKatayama Hirofumi MZ         selectionModel.Landing();
121e8c7e300SKatayama Hirofumi MZ         selectionModel.HideSelection();
122aac89519SKatayama Hirofumi MZ     }
123ee132a05SKatayama Hirofumi MZ }
124ee132a05SKatayama Hirofumi MZ 
OnEndDraw(BOOL bCancel)12537f56d24SKatayama Hirofumi MZ void ToolBase::OnEndDraw(BOOL bCancel)
12608397115SKatayama Hirofumi MZ {
12708397115SKatayama Hirofumi MZ     reset();
128bfd42c67SKatayama Hirofumi MZ     imageModel.NotifyImageChanged();
12908397115SKatayama Hirofumi MZ }
13008397115SKatayama Hirofumi MZ 
beginEvent()131ee132a05SKatayama Hirofumi MZ void ToolBase::beginEvent()
132ee132a05SKatayama Hirofumi MZ {
133ee132a05SKatayama Hirofumi MZ     m_hdc = imageModel.GetDC();
134ee132a05SKatayama Hirofumi MZ     m_fg = paletteModel.GetFgColor();
135ee132a05SKatayama Hirofumi MZ     m_bg = paletteModel.GetBgColor();
136ee132a05SKatayama Hirofumi MZ }
137ee132a05SKatayama Hirofumi MZ 
endEvent()138ee132a05SKatayama Hirofumi MZ void ToolBase::endEvent()
139ee132a05SKatayama Hirofumi MZ {
140ee132a05SKatayama Hirofumi MZ     m_hdc = NULL;
141ee132a05SKatayama Hirofumi MZ }
142ee132a05SKatayama Hirofumi MZ 
pushToPoints(LONG x,LONG y)143*3799d37aSKatayama Hirofumi MZ static void pushToPoints(LONG x, LONG y)
144e5792200SKatayama Hirofumi MZ {
145*3799d37aSKatayama Hirofumi MZ     if (s_cPoints + 1 >= s_maxPoints)
146e5792200SKatayama Hirofumi MZ     {
147*3799d37aSKatayama Hirofumi MZ         SIZE_T newMax = s_maxPoints + 512;
148e5792200SKatayama Hirofumi MZ         SIZE_T cbNew = newMax * sizeof(POINT);
149*3799d37aSKatayama Hirofumi MZ         if (!s_dynamicPoints.ReallocateBytes(cbNew))
150e5792200SKatayama Hirofumi MZ         {
151*3799d37aSKatayama Hirofumi MZ             ATLTRACE("%d, %d, %d\n", (INT)s_cPoints, (INT)s_maxPoints, (INT)cbNew);
152e5792200SKatayama Hirofumi MZ             return;
153e5792200SKatayama Hirofumi MZ         }
154e5792200SKatayama Hirofumi MZ 
155*3799d37aSKatayama Hirofumi MZ         if (s_pPoints == s_staticPoints)
156*3799d37aSKatayama Hirofumi MZ             CopyMemory(s_dynamicPoints, s_staticPoints, s_cPoints * sizeof(POINT));
157b8598e09SKatayama Hirofumi MZ 
158*3799d37aSKatayama Hirofumi MZ         s_pPoints = s_dynamicPoints;
159*3799d37aSKatayama Hirofumi MZ         s_maxPoints = newMax;
160e5792200SKatayama Hirofumi MZ     }
161e5792200SKatayama Hirofumi MZ 
162*3799d37aSKatayama Hirofumi MZ     s_pPoints[s_cPoints++] = { x, y };
163e5792200SKatayama Hirofumi MZ }
164e5792200SKatayama Hirofumi MZ 
165ee132a05SKatayama Hirofumi MZ /* TOOLS ********************************************************/
166ee132a05SKatayama Hirofumi MZ 
167e8c7e300SKatayama Hirofumi MZ struct TwoPointDrawTool : ToolBase
168ee132a05SKatayama Hirofumi MZ {
169e8c7e300SKatayama Hirofumi MZ     BOOL m_bLeftButton = FALSE;
170e8c7e300SKatayama Hirofumi MZ     BOOL m_bDrawing = FALSE;
171e8c7e300SKatayama Hirofumi MZ 
OnButtonDownTwoPointDrawTool172e8c7e300SKatayama Hirofumi MZ     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
173e8c7e300SKatayama Hirofumi MZ     {
174e8c7e300SKatayama Hirofumi MZ         m_bLeftButton = bLeftButton;
175e8c7e300SKatayama Hirofumi MZ         m_bDrawing = TRUE;
176e8c7e300SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
177e8c7e300SKatayama Hirofumi MZ     }
178e8c7e300SKatayama Hirofumi MZ 
OnMouseMoveTwoPointDrawTool179389d0465SKatayama Hirofumi MZ     BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
180e8c7e300SKatayama Hirofumi MZ     {
181e8c7e300SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
182389d0465SKatayama Hirofumi MZ         return TRUE;
183e8c7e300SKatayama Hirofumi MZ     }
184e8c7e300SKatayama Hirofumi MZ 
OnButtonUpTwoPointDrawTool185389d0465SKatayama Hirofumi MZ     BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
186e8c7e300SKatayama Hirofumi MZ     {
18772081168SKatayama Hirofumi MZ         CRect rcPartial(g_ptStart, g_ptEnd);
18872081168SKatayama Hirofumi MZ         rcPartial.NormalizeRect();
18972081168SKatayama Hirofumi MZ         SIZE size = toolsModel.GetToolSize();
19072081168SKatayama Hirofumi MZ         rcPartial.InflateRect((size.cx + 1) / 2, (size.cy + 1) / 2);
19172081168SKatayama Hirofumi MZ         imageModel.PushImageForUndo(rcPartial);
19272081168SKatayama Hirofumi MZ 
193e8c7e300SKatayama Hirofumi MZ         OnDrawOverlayOnImage(m_hdc);
194e8c7e300SKatayama Hirofumi MZ         m_bDrawing = FALSE;
195e8c7e300SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
196389d0465SKatayama Hirofumi MZ         return TRUE;
197e8c7e300SKatayama Hirofumi MZ     }
198e8c7e300SKatayama Hirofumi MZ 
OnEndDrawTwoPointDrawTool19937f56d24SKatayama Hirofumi MZ     void OnEndDraw(BOOL bCancel) override
200e8c7e300SKatayama Hirofumi MZ     {
201e8c7e300SKatayama Hirofumi MZ         m_bDrawing = FALSE;
20237f56d24SKatayama Hirofumi MZ         ToolBase::OnEndDraw(bCancel);
203e8c7e300SKatayama Hirofumi MZ     }
204f2a01224SKatayama Hirofumi MZ 
OnSpecialTweakTwoPointDrawTool205f2a01224SKatayama Hirofumi MZ     void OnSpecialTweak(BOOL bMinus) override
206f2a01224SKatayama Hirofumi MZ     {
207f2a01224SKatayama Hirofumi MZ         toolsModel.MakeLineThickerOrThinner(bMinus);
208f2a01224SKatayama Hirofumi MZ     }
209e8c7e300SKatayama Hirofumi MZ };
210e8c7e300SKatayama Hirofumi MZ 
211389d0465SKatayama Hirofumi MZ typedef enum DIRECTION
212389d0465SKatayama Hirofumi MZ {
213389d0465SKatayama Hirofumi MZ     NO_DIRECTION = -1,
214389d0465SKatayama Hirofumi MZ     DIRECTION_HORIZONTAL,
215389d0465SKatayama Hirofumi MZ     DIRECTION_VERTICAL,
216389d0465SKatayama Hirofumi MZ     DIRECTION_DIAGONAL_RIGHT_DOWN,
217389d0465SKatayama Hirofumi MZ     DIRECTION_DIAGONAL_RIGHT_UP,
218389d0465SKatayama Hirofumi MZ } DIRECTION;
219389d0465SKatayama Hirofumi MZ 
220389d0465SKatayama Hirofumi MZ #define THRESHOULD_DEG 15
221389d0465SKatayama Hirofumi MZ 
222389d0465SKatayama Hirofumi MZ static DIRECTION
GetDirection(LONG x0,LONG y0,LONG x1,LONG y1)223389d0465SKatayama Hirofumi MZ GetDirection(LONG x0, LONG y0, LONG x1, LONG y1)
224389d0465SKatayama Hirofumi MZ {
225389d0465SKatayama Hirofumi MZ     LONG dx = x1 - x0, dy = y1 - y0;
226389d0465SKatayama Hirofumi MZ 
227389d0465SKatayama Hirofumi MZ     if (labs(dx) <= 8 && labs(dy) <= 8)
228389d0465SKatayama Hirofumi MZ         return NO_DIRECTION;
229389d0465SKatayama Hirofumi MZ 
230389d0465SKatayama Hirofumi MZ     double radian = atan2((double)dy, (double)dx);
231389d0465SKatayama Hirofumi MZ     if (radian < DEG2RAD(-180 + THRESHOULD_DEG))
232389d0465SKatayama Hirofumi MZ     {
233389d0465SKatayama Hirofumi MZ         ATLTRACE("DIRECTION_HORIZONTAL: %ld\n", RAD2DEG(radian));
234389d0465SKatayama Hirofumi MZ         return DIRECTION_HORIZONTAL;
235389d0465SKatayama Hirofumi MZ     }
236389d0465SKatayama Hirofumi MZ     if (radian < DEG2RAD(-90 - THRESHOULD_DEG))
237389d0465SKatayama Hirofumi MZ     {
238389d0465SKatayama Hirofumi MZ         ATLTRACE("DIRECTION_DIAGONAL_RIGHT_DOWN: %ld\n", RAD2DEG(radian));
239389d0465SKatayama Hirofumi MZ         return DIRECTION_DIAGONAL_RIGHT_DOWN;
240389d0465SKatayama Hirofumi MZ     }
241389d0465SKatayama Hirofumi MZ     if (radian < DEG2RAD(-90 + THRESHOULD_DEG))
242389d0465SKatayama Hirofumi MZ     {
243389d0465SKatayama Hirofumi MZ         ATLTRACE("DIRECTION_VERTICAL: %ld\n", RAD2DEG(radian));
244389d0465SKatayama Hirofumi MZ         return DIRECTION_VERTICAL;
245389d0465SKatayama Hirofumi MZ     }
246389d0465SKatayama Hirofumi MZ     if (radian < DEG2RAD(-THRESHOULD_DEG))
247389d0465SKatayama Hirofumi MZ     {
248389d0465SKatayama Hirofumi MZ         ATLTRACE("DIRECTION_DIAGONAL_RIGHT_UP: %ld\n", RAD2DEG(radian));
249389d0465SKatayama Hirofumi MZ         return DIRECTION_DIAGONAL_RIGHT_UP;
250389d0465SKatayama Hirofumi MZ     }
251389d0465SKatayama Hirofumi MZ     if (radian < DEG2RAD(+THRESHOULD_DEG))
252389d0465SKatayama Hirofumi MZ     {
253389d0465SKatayama Hirofumi MZ         ATLTRACE("DIRECTION_HORIZONTAL: %ld\n", RAD2DEG(radian));
254389d0465SKatayama Hirofumi MZ         return DIRECTION_HORIZONTAL;
255389d0465SKatayama Hirofumi MZ     }
256389d0465SKatayama Hirofumi MZ     if (radian < DEG2RAD(+90 - THRESHOULD_DEG))
257389d0465SKatayama Hirofumi MZ     {
258389d0465SKatayama Hirofumi MZ         ATLTRACE("DIRECTION_DIAGONAL_RIGHT_DOWN: %ld\n", RAD2DEG(radian));
259389d0465SKatayama Hirofumi MZ         return DIRECTION_DIAGONAL_RIGHT_DOWN;
260389d0465SKatayama Hirofumi MZ     }
261389d0465SKatayama Hirofumi MZ     if (radian < DEG2RAD(+90 + THRESHOULD_DEG))
262389d0465SKatayama Hirofumi MZ     {
263389d0465SKatayama Hirofumi MZ         ATLTRACE("DIRECTION_VERTICAL: %ld\n", RAD2DEG(radian));
264389d0465SKatayama Hirofumi MZ         return DIRECTION_VERTICAL;
265389d0465SKatayama Hirofumi MZ     }
266389d0465SKatayama Hirofumi MZ     if (radian < DEG2RAD(+180 - THRESHOULD_DEG))
267389d0465SKatayama Hirofumi MZ     {
268389d0465SKatayama Hirofumi MZ         ATLTRACE("DIRECTION_DIAGONAL_RIGHT_UP: %ld\n", RAD2DEG(radian));
269389d0465SKatayama Hirofumi MZ         return DIRECTION_DIAGONAL_RIGHT_UP;
270389d0465SKatayama Hirofumi MZ     }
271389d0465SKatayama Hirofumi MZ     ATLTRACE("DIRECTION_HORIZONTAL: %ld\n", RAD2DEG(radian));
272389d0465SKatayama Hirofumi MZ     return DIRECTION_HORIZONTAL;
273389d0465SKatayama Hirofumi MZ }
274389d0465SKatayama Hirofumi MZ 
275389d0465SKatayama Hirofumi MZ static void
RestrictDrawDirection(DIRECTION dir,LONG x0,LONG y0,LONG & x1,LONG & y1)276389d0465SKatayama Hirofumi MZ RestrictDrawDirection(DIRECTION dir, LONG x0, LONG y0, LONG& x1, LONG& y1)
277389d0465SKatayama Hirofumi MZ {
278389d0465SKatayama Hirofumi MZ     switch (dir)
279389d0465SKatayama Hirofumi MZ     {
280389d0465SKatayama Hirofumi MZ         case NO_DIRECTION:
281389d0465SKatayama Hirofumi MZ         default:
282389d0465SKatayama Hirofumi MZ             return;
283389d0465SKatayama Hirofumi MZ 
284389d0465SKatayama Hirofumi MZ         case DIRECTION_HORIZONTAL:
285389d0465SKatayama Hirofumi MZ             y1 = y0;
286389d0465SKatayama Hirofumi MZ             break;
287389d0465SKatayama Hirofumi MZ 
288389d0465SKatayama Hirofumi MZ         case DIRECTION_VERTICAL:
289389d0465SKatayama Hirofumi MZ             x1 = x0;
290389d0465SKatayama Hirofumi MZ             break;
291389d0465SKatayama Hirofumi MZ 
292389d0465SKatayama Hirofumi MZ         case DIRECTION_DIAGONAL_RIGHT_DOWN:
293389d0465SKatayama Hirofumi MZ             y1 = y0 + (x1 - x0);
294389d0465SKatayama Hirofumi MZ             break;
295389d0465SKatayama Hirofumi MZ 
296389d0465SKatayama Hirofumi MZ         case DIRECTION_DIAGONAL_RIGHT_UP:
297389d0465SKatayama Hirofumi MZ             x1 = x0 - (y1 - y0);
298389d0465SKatayama Hirofumi MZ             break;
299389d0465SKatayama Hirofumi MZ     }
300389d0465SKatayama Hirofumi MZ }
301389d0465SKatayama Hirofumi MZ 
302e8c7e300SKatayama Hirofumi MZ struct SmoothDrawTool : ToolBase
303e8c7e300SKatayama Hirofumi MZ {
304389d0465SKatayama Hirofumi MZ     DIRECTION m_direction = NO_DIRECTION;
305fd1e1584SKatayama Hirofumi MZ     BOOL m_bShiftDown = FALSE;
306e5792200SKatayama Hirofumi MZ     BOOL m_bLeftButton = FALSE;
307389d0465SKatayama Hirofumi MZ 
308e5792200SKatayama Hirofumi MZ     virtual void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) = 0;
309ee132a05SKatayama Hirofumi MZ 
OnButtonDownSmoothDrawTool3106d9b7f77SKatayama Hirofumi MZ     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
311ee132a05SKatayama Hirofumi MZ     {
312389d0465SKatayama Hirofumi MZ         m_direction = NO_DIRECTION;
313fd1e1584SKatayama Hirofumi MZ         m_bShiftDown = (::GetKeyState(VK_SHIFT) & 0x8000); // Is Shift key pressed?
314e5792200SKatayama Hirofumi MZ         m_bLeftButton = bLeftButton;
315*3799d37aSKatayama Hirofumi MZ         s_cPoints = 0;
316*3799d37aSKatayama Hirofumi MZ         pushToPoints(x, y);
317*3799d37aSKatayama Hirofumi MZ         pushToPoints(x, y); // We have to draw the first point
318e5792200SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
319389d0465SKatayama Hirofumi MZ     }
320389d0465SKatayama Hirofumi MZ 
OnMouseMoveSmoothDrawTool321389d0465SKatayama Hirofumi MZ     BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
322389d0465SKatayama Hirofumi MZ     {
323e5792200SKatayama Hirofumi MZ         if (!m_bShiftDown)
324389d0465SKatayama Hirofumi MZ         {
325*3799d37aSKatayama Hirofumi MZ             pushToPoints(x, y);
326e5792200SKatayama Hirofumi MZ             imageModel.NotifyImageChanged();
327e5792200SKatayama Hirofumi MZ             return TRUE;
328e5792200SKatayama Hirofumi MZ         }
329e5792200SKatayama Hirofumi MZ 
330389d0465SKatayama Hirofumi MZ         if (m_direction == NO_DIRECTION)
331389d0465SKatayama Hirofumi MZ         {
332389d0465SKatayama Hirofumi MZ             m_direction = GetDirection(g_ptStart.x, g_ptStart.y, x, y);
333389d0465SKatayama Hirofumi MZ             if (m_direction == NO_DIRECTION)
334389d0465SKatayama Hirofumi MZ                 return FALSE;
335389d0465SKatayama Hirofumi MZ         }
336389d0465SKatayama Hirofumi MZ 
337389d0465SKatayama Hirofumi MZ         RestrictDrawDirection(m_direction, g_ptStart.x, g_ptStart.y, x, y);
338*3799d37aSKatayama Hirofumi MZ         pushToPoints(x, y);
339bfd42c67SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
340389d0465SKatayama Hirofumi MZ         return TRUE;
341ee132a05SKatayama Hirofumi MZ     }
342ee132a05SKatayama Hirofumi MZ 
OnButtonUpSmoothDrawTool343389d0465SKatayama Hirofumi MZ     BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
344ee132a05SKatayama Hirofumi MZ     {
345fd1e1584SKatayama Hirofumi MZ         if (m_bShiftDown && m_direction != NO_DIRECTION)
346389d0465SKatayama Hirofumi MZ             RestrictDrawDirection(m_direction, g_ptStart.x, g_ptStart.y, x, y);
347389d0465SKatayama Hirofumi MZ 
348*3799d37aSKatayama Hirofumi MZ         pushToPoints(x, y);
349e5792200SKatayama Hirofumi MZ 
350e5792200SKatayama Hirofumi MZ         CRect rcPartial;
351*3799d37aSKatayama Hirofumi MZ         getBoundaryOfPoints(rcPartial, s_cPoints, s_pPoints);
352e5792200SKatayama Hirofumi MZ 
353e5792200SKatayama Hirofumi MZ         SIZE size = toolsModel.GetToolSize();
354e5792200SKatayama Hirofumi MZ         rcPartial.InflateRect((size.cx + 1) / 2, (size.cy + 1) / 2);
355e5792200SKatayama Hirofumi MZ 
356e5792200SKatayama Hirofumi MZ         imageModel.PushImageForUndo(rcPartial);
357e5792200SKatayama Hirofumi MZ 
358e5792200SKatayama Hirofumi MZ         OnDrawOverlayOnImage(m_hdc);
359e5792200SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
36037f56d24SKatayama Hirofumi MZ         OnEndDraw(FALSE);
361389d0465SKatayama Hirofumi MZ         return TRUE;
362e8c7e300SKatayama Hirofumi MZ     }
363e8c7e300SKatayama Hirofumi MZ 
OnDrawOverlayOnImageSmoothDrawTool364e5792200SKatayama Hirofumi MZ     void OnDrawOverlayOnImage(HDC hdc) override
365e8c7e300SKatayama Hirofumi MZ     {
366*3799d37aSKatayama Hirofumi MZ         for (SIZE_T i = 1; i < s_cPoints; ++i)
367ee132a05SKatayama Hirofumi MZ         {
368*3799d37aSKatayama Hirofumi MZ             OnDraw(hdc, m_bLeftButton, s_pPoints[i - 1], s_pPoints[i]);
36937f56d24SKatayama Hirofumi MZ         }
370ee132a05SKatayama Hirofumi MZ     }
371ee132a05SKatayama Hirofumi MZ };
372ee132a05SKatayama Hirofumi MZ 
373b8598e09SKatayama Hirofumi MZ struct SelectionBaseTool : ToolBase
374f710e5a2SKatayama Hirofumi MZ {
375f710e5a2SKatayama Hirofumi MZ     BOOL m_bLeftButton = FALSE;
376f710e5a2SKatayama Hirofumi MZ     BOOL m_bCtrlKey = FALSE;
377f710e5a2SKatayama Hirofumi MZ     BOOL m_bShiftKey = FALSE;
378f710e5a2SKatayama Hirofumi MZ     BOOL m_bDrawing = FALSE;
379b8598e09SKatayama Hirofumi MZ     BOOL m_bNoDrawBack = FALSE;
380f710e5a2SKatayama Hirofumi MZ     HITTEST m_hitSelection = HIT_NONE;
381f710e5a2SKatayama Hirofumi MZ 
isRectSelectSelectionBaseTool382f710e5a2SKatayama Hirofumi MZ     BOOL isRectSelect() const
383f710e5a2SKatayama Hirofumi MZ     {
384f710e5a2SKatayama Hirofumi MZ         return (toolsModel.GetActiveTool() == TOOL_RECTSEL);
385f710e5a2SKatayama Hirofumi MZ     }
386f710e5a2SKatayama Hirofumi MZ 
OnDrawOverlayOnImageSelectionBaseTool387f710e5a2SKatayama Hirofumi MZ     void OnDrawOverlayOnImage(HDC hdc) override
388f710e5a2SKatayama Hirofumi MZ     {
389b8598e09SKatayama Hirofumi MZ         if (selectionModel.IsLanded() || !selectionModel.m_bShow)
390b8598e09SKatayama Hirofumi MZ             return;
391b8598e09SKatayama Hirofumi MZ 
392b8598e09SKatayama Hirofumi MZ         if (!m_bNoDrawBack)
393b8598e09SKatayama Hirofumi MZ             selectionModel.DrawBackground(hdc, selectionModel.m_rgbBack);
394b8598e09SKatayama Hirofumi MZ 
395f710e5a2SKatayama Hirofumi MZ         selectionModel.DrawSelection(hdc, paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
396f710e5a2SKatayama Hirofumi MZ     }
397f710e5a2SKatayama Hirofumi MZ 
OnDrawOverlayOnCanvasSelectionBaseTool398f710e5a2SKatayama Hirofumi MZ     void OnDrawOverlayOnCanvas(HDC hdc) override
399f710e5a2SKatayama Hirofumi MZ     {
400b8598e09SKatayama Hirofumi MZ         if (m_bDrawing || selectionModel.m_bShow)
401f710e5a2SKatayama Hirofumi MZ             selectionModel.drawFrameOnCanvas(hdc);
402f710e5a2SKatayama Hirofumi MZ     }
403f710e5a2SKatayama Hirofumi MZ 
OnButtonDownSelectionBaseTool404f710e5a2SKatayama Hirofumi MZ     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
405f710e5a2SKatayama Hirofumi MZ     {
406f710e5a2SKatayama Hirofumi MZ         m_bLeftButton = bLeftButton;
407f710e5a2SKatayama Hirofumi MZ         m_bCtrlKey = (::GetKeyState(VK_CONTROL) < 0);
408f710e5a2SKatayama Hirofumi MZ         m_bShiftKey = (::GetKeyState(VK_SHIFT) < 0);
409f710e5a2SKatayama Hirofumi MZ         m_bDrawing = FALSE;
410f710e5a2SKatayama Hirofumi MZ         m_hitSelection = HIT_NONE;
411f710e5a2SKatayama Hirofumi MZ 
412f710e5a2SKatayama Hirofumi MZ         POINT pt = { x, y };
413f710e5a2SKatayama Hirofumi MZ         if (!m_bLeftButton) // Show context menu on Right-click
414f710e5a2SKatayama Hirofumi MZ         {
415f710e5a2SKatayama Hirofumi MZ             canvasWindow.ImageToCanvas(pt);
416f710e5a2SKatayama Hirofumi MZ             canvasWindow.ClientToScreen(&pt);
417f710e5a2SKatayama Hirofumi MZ             mainWindow.TrackPopupMenu(pt, 0);
418f710e5a2SKatayama Hirofumi MZ             return;
419f710e5a2SKatayama Hirofumi MZ         }
420f710e5a2SKatayama Hirofumi MZ 
421f710e5a2SKatayama Hirofumi MZ         POINT ptCanvas = pt;
422f710e5a2SKatayama Hirofumi MZ         canvasWindow.ImageToCanvas(ptCanvas);
423f710e5a2SKatayama Hirofumi MZ         HITTEST hit = selectionModel.hitTest(ptCanvas);
424f710e5a2SKatayama Hirofumi MZ         if (hit != HIT_NONE) // Dragging of selection started?
425f710e5a2SKatayama Hirofumi MZ         {
426f710e5a2SKatayama Hirofumi MZ             if (m_bCtrlKey || m_bShiftKey)
427b8598e09SKatayama Hirofumi MZ             {
428b8598e09SKatayama Hirofumi MZ                 imageModel.PushImageForUndo();
429b8598e09SKatayama Hirofumi MZ                 toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
430b8598e09SKatayama Hirofumi MZ             }
431f710e5a2SKatayama Hirofumi MZ             m_hitSelection = hit;
432f710e5a2SKatayama Hirofumi MZ             selectionModel.m_ptHit = pt;
433f710e5a2SKatayama Hirofumi MZ             selectionModel.TakeOff();
434b8598e09SKatayama Hirofumi MZ             m_bNoDrawBack |= (m_bCtrlKey || m_bShiftKey);
435f710e5a2SKatayama Hirofumi MZ             imageModel.NotifyImageChanged();
436f710e5a2SKatayama Hirofumi MZ             return;
437f710e5a2SKatayama Hirofumi MZ         }
438f710e5a2SKatayama Hirofumi MZ 
439f710e5a2SKatayama Hirofumi MZ         selectionModel.Landing();
440f710e5a2SKatayama Hirofumi MZ         m_bDrawing = TRUE;
441f710e5a2SKatayama Hirofumi MZ 
442f710e5a2SKatayama Hirofumi MZ         imageModel.Clamp(pt);
443f710e5a2SKatayama Hirofumi MZ         if (isRectSelect())
444f710e5a2SKatayama Hirofumi MZ         {
445f710e5a2SKatayama Hirofumi MZ             selectionModel.SetRectFromPoints(g_ptStart, pt);
446f710e5a2SKatayama Hirofumi MZ         }
447f710e5a2SKatayama Hirofumi MZ         else
448f710e5a2SKatayama Hirofumi MZ         {
449*3799d37aSKatayama Hirofumi MZ             s_cPoints = 0;
450*3799d37aSKatayama Hirofumi MZ             pushToPoints(pt.x, pt.y);
451f710e5a2SKatayama Hirofumi MZ         }
452f710e5a2SKatayama Hirofumi MZ 
453f710e5a2SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
454f710e5a2SKatayama Hirofumi MZ     }
455f710e5a2SKatayama Hirofumi MZ 
OnMouseMoveSelectionBaseTool456f710e5a2SKatayama Hirofumi MZ     BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
457f710e5a2SKatayama Hirofumi MZ     {
458f710e5a2SKatayama Hirofumi MZ         POINT pt = { x, y };
459f710e5a2SKatayama Hirofumi MZ 
460f710e5a2SKatayama Hirofumi MZ         if (!m_bLeftButton)
461f710e5a2SKatayama Hirofumi MZ             return TRUE;
462f710e5a2SKatayama Hirofumi MZ 
463f710e5a2SKatayama Hirofumi MZ         if (m_hitSelection != HIT_NONE) // Now dragging selection?
464f710e5a2SKatayama Hirofumi MZ         {
465f710e5a2SKatayama Hirofumi MZ             if (m_bShiftKey)
466b8598e09SKatayama Hirofumi MZ                 toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
467f710e5a2SKatayama Hirofumi MZ 
468f710e5a2SKatayama Hirofumi MZ             selectionModel.Dragging(m_hitSelection, pt);
469f710e5a2SKatayama Hirofumi MZ             imageModel.NotifyImageChanged();
470f710e5a2SKatayama Hirofumi MZ             return TRUE;
471f710e5a2SKatayama Hirofumi MZ         }
472f710e5a2SKatayama Hirofumi MZ 
473b8598e09SKatayama Hirofumi MZ         if (isRectSelect() && ::GetKeyState(VK_SHIFT) < 0)
474b8598e09SKatayama Hirofumi MZ             regularize(g_ptStart.x, g_ptStart.y, pt.x, pt.y);
475b8598e09SKatayama Hirofumi MZ 
476f710e5a2SKatayama Hirofumi MZ         imageModel.Clamp(pt);
477b8598e09SKatayama Hirofumi MZ 
478f710e5a2SKatayama Hirofumi MZ         if (isRectSelect())
479f710e5a2SKatayama Hirofumi MZ             selectionModel.SetRectFromPoints(g_ptStart, pt);
480f710e5a2SKatayama Hirofumi MZ         else
481*3799d37aSKatayama Hirofumi MZ             pushToPoints(pt.x, pt.y);
482f710e5a2SKatayama Hirofumi MZ 
483f710e5a2SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
484f710e5a2SKatayama Hirofumi MZ         return TRUE;
485f710e5a2SKatayama Hirofumi MZ     }
486f710e5a2SKatayama Hirofumi MZ 
OnButtonUpSelectionBaseTool487f710e5a2SKatayama Hirofumi MZ     BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
488f710e5a2SKatayama Hirofumi MZ     {
489f710e5a2SKatayama Hirofumi MZ         POINT pt = { x, y };
490f710e5a2SKatayama Hirofumi MZ         m_bDrawing = FALSE;
491f710e5a2SKatayama Hirofumi MZ 
492f710e5a2SKatayama Hirofumi MZ         if (!m_bLeftButton)
493f710e5a2SKatayama Hirofumi MZ             return TRUE;
494f710e5a2SKatayama Hirofumi MZ 
495f710e5a2SKatayama Hirofumi MZ         if (m_hitSelection != HIT_NONE) // Dragging of selection ended?
496f710e5a2SKatayama Hirofumi MZ         {
497b8598e09SKatayama Hirofumi MZ             if (m_bShiftKey)
498b8598e09SKatayama Hirofumi MZ                 toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
499b8598e09SKatayama Hirofumi MZ 
500f710e5a2SKatayama Hirofumi MZ             selectionModel.Dragging(m_hitSelection, pt);
501f710e5a2SKatayama Hirofumi MZ             m_hitSelection = HIT_NONE;
502f710e5a2SKatayama Hirofumi MZ             imageModel.NotifyImageChanged();
503f710e5a2SKatayama Hirofumi MZ             return TRUE;
504f710e5a2SKatayama Hirofumi MZ         }
505f710e5a2SKatayama Hirofumi MZ 
506b8598e09SKatayama Hirofumi MZ         if (isRectSelect() && ::GetKeyState(VK_SHIFT) < 0)
507b8598e09SKatayama Hirofumi MZ             regularize(g_ptStart.x, g_ptStart.y, pt.x, pt.y);
508b8598e09SKatayama Hirofumi MZ 
509f710e5a2SKatayama Hirofumi MZ         imageModel.Clamp(pt);
510b8598e09SKatayama Hirofumi MZ 
511f710e5a2SKatayama Hirofumi MZ         if (isRectSelect())
512f710e5a2SKatayama Hirofumi MZ         {
513f710e5a2SKatayama Hirofumi MZ             selectionModel.SetRectFromPoints(g_ptStart, pt);
514f710e5a2SKatayama Hirofumi MZ             selectionModel.m_bShow = !selectionModel.m_rc.IsRectEmpty();
515f710e5a2SKatayama Hirofumi MZ         }
516f710e5a2SKatayama Hirofumi MZ         else
517f710e5a2SKatayama Hirofumi MZ         {
518*3799d37aSKatayama Hirofumi MZ             if (s_cPoints > 2)
519f710e5a2SKatayama Hirofumi MZ             {
520*3799d37aSKatayama Hirofumi MZ                 BuildMaskFromPoints();
521f710e5a2SKatayama Hirofumi MZ                 selectionModel.m_bShow = TRUE;
522f710e5a2SKatayama Hirofumi MZ             }
523f710e5a2SKatayama Hirofumi MZ             else
524f710e5a2SKatayama Hirofumi MZ             {
525*3799d37aSKatayama Hirofumi MZ                 s_cPoints = 0;
526f710e5a2SKatayama Hirofumi MZ                 selectionModel.m_bShow = FALSE;
527f710e5a2SKatayama Hirofumi MZ             }
528f710e5a2SKatayama Hirofumi MZ         }
529f710e5a2SKatayama Hirofumi MZ 
530b8598e09SKatayama Hirofumi MZ         m_bNoDrawBack = FALSE;
531f710e5a2SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
532f710e5a2SKatayama Hirofumi MZ         return TRUE;
533f710e5a2SKatayama Hirofumi MZ     }
534f710e5a2SKatayama Hirofumi MZ 
OnEndDrawSelectionBaseTool535f710e5a2SKatayama Hirofumi MZ     void OnEndDraw(BOOL bCancel) override
536f710e5a2SKatayama Hirofumi MZ     {
537f710e5a2SKatayama Hirofumi MZ         if (bCancel)
538f710e5a2SKatayama Hirofumi MZ             selectionModel.HideSelection();
539f710e5a2SKatayama Hirofumi MZ         else
540f710e5a2SKatayama Hirofumi MZ             selectionModel.Landing();
541f710e5a2SKatayama Hirofumi MZ 
542b8598e09SKatayama Hirofumi MZ         m_bDrawing = FALSE;
543f710e5a2SKatayama Hirofumi MZ         m_hitSelection = HIT_NONE;
544f710e5a2SKatayama Hirofumi MZ         ToolBase::OnEndDraw(bCancel);
545f710e5a2SKatayama Hirofumi MZ     }
546f710e5a2SKatayama Hirofumi MZ 
OnSpecialTweakSelectionBaseTool547f710e5a2SKatayama Hirofumi MZ     void OnSpecialTweak(BOOL bMinus) override
548f710e5a2SKatayama Hirofumi MZ     {
549f710e5a2SKatayama Hirofumi MZ         selectionModel.StretchSelection(bMinus);
550f710e5a2SKatayama Hirofumi MZ     }
551f710e5a2SKatayama Hirofumi MZ };
552f710e5a2SKatayama Hirofumi MZ 
553f710e5a2SKatayama Hirofumi MZ // TOOL_FREESEL
554f710e5a2SKatayama Hirofumi MZ struct FreeSelTool : SelectionBaseTool
555f710e5a2SKatayama Hirofumi MZ {
OnDrawOverlayOnImageFreeSelTool556f710e5a2SKatayama Hirofumi MZ     void OnDrawOverlayOnImage(HDC hdc) override
557f710e5a2SKatayama Hirofumi MZ     {
558f710e5a2SKatayama Hirofumi MZ         SelectionBaseTool::OnDrawOverlayOnImage(hdc);
559f710e5a2SKatayama Hirofumi MZ 
560f710e5a2SKatayama Hirofumi MZ         if (!selectionModel.m_bShow && m_bDrawing)
561b8598e09SKatayama Hirofumi MZ         {
562b8598e09SKatayama Hirofumi MZ             /* Draw the freehand selection inverted/xored */
563*3799d37aSKatayama Hirofumi MZ             Poly(hdc, s_pPoints, (INT)s_cPoints, 0, 0, 2, 0, FALSE, TRUE);
564b8598e09SKatayama Hirofumi MZ         }
565f710e5a2SKatayama Hirofumi MZ     }
566f710e5a2SKatayama Hirofumi MZ };
567f710e5a2SKatayama Hirofumi MZ 
568f710e5a2SKatayama Hirofumi MZ // TOOL_RECTSEL
569f710e5a2SKatayama Hirofumi MZ struct RectSelTool : SelectionBaseTool
570f710e5a2SKatayama Hirofumi MZ {
OnDrawOverlayOnImageRectSelTool571f710e5a2SKatayama Hirofumi MZ     void OnDrawOverlayOnImage(HDC hdc) override
572f710e5a2SKatayama Hirofumi MZ     {
573f710e5a2SKatayama Hirofumi MZ         SelectionBaseTool::OnDrawOverlayOnImage(hdc);
574f710e5a2SKatayama Hirofumi MZ 
575f710e5a2SKatayama Hirofumi MZ         if (!selectionModel.m_bShow && m_bDrawing)
576f710e5a2SKatayama Hirofumi MZ         {
577f710e5a2SKatayama Hirofumi MZ             CRect& rc = selectionModel.m_rc;
578f710e5a2SKatayama Hirofumi MZ             if (!rc.IsRectEmpty())
579f710e5a2SKatayama Hirofumi MZ                 RectSel(hdc, rc.left, rc.top, rc.right, rc.bottom);
580f710e5a2SKatayama Hirofumi MZ         }
581f710e5a2SKatayama Hirofumi MZ     }
582f710e5a2SKatayama Hirofumi MZ };
583f710e5a2SKatayama Hirofumi MZ 
584ee132a05SKatayama Hirofumi MZ // TOOL_RUBBER
585e8c7e300SKatayama Hirofumi MZ struct RubberTool : SmoothDrawTool
586ee132a05SKatayama Hirofumi MZ {
OnDrawRubberTool587e5792200SKatayama Hirofumi MZ     void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) override
588ee132a05SKatayama Hirofumi MZ     {
589ee132a05SKatayama Hirofumi MZ         if (bLeftButton)
590e5792200SKatayama Hirofumi MZ             Erase(hdc, pt0.x, pt0.y, pt1.x, pt1.y, m_bg, toolsModel.GetRubberRadius());
591ee132a05SKatayama Hirofumi MZ         else
592e5792200SKatayama Hirofumi MZ             Replace(hdc, pt0.x, pt0.y, pt1.x, pt1.y, m_fg, m_bg, toolsModel.GetRubberRadius());
593ee132a05SKatayama Hirofumi MZ     }
594945ee4b2SKatayama Hirofumi MZ 
OnSpecialTweakRubberTool595945ee4b2SKatayama Hirofumi MZ     void OnSpecialTweak(BOOL bMinus) override
596945ee4b2SKatayama Hirofumi MZ     {
597945ee4b2SKatayama Hirofumi MZ         toolsModel.MakeRubberThickerOrThinner(bMinus);
598945ee4b2SKatayama Hirofumi MZ     }
599ee132a05SKatayama Hirofumi MZ };
600ee132a05SKatayama Hirofumi MZ 
601ee132a05SKatayama Hirofumi MZ // TOOL_FILL
602ee132a05SKatayama Hirofumi MZ struct FillTool : ToolBase
603ee132a05SKatayama Hirofumi MZ {
OnButtonDownFillTool6046d9b7f77SKatayama Hirofumi MZ     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
605ee132a05SKatayama Hirofumi MZ     {
6062b623c1dSKatayama Hirofumi MZ         imageModel.PushImageForUndo();
607ee132a05SKatayama Hirofumi MZ         Fill(m_hdc, x, y, bLeftButton ? m_fg : m_bg);
608ee132a05SKatayama Hirofumi MZ     }
609ee132a05SKatayama Hirofumi MZ };
610ee132a05SKatayama Hirofumi MZ 
611ee132a05SKatayama Hirofumi MZ // TOOL_COLOR
612ee132a05SKatayama Hirofumi MZ struct ColorTool : ToolBase
613ee132a05SKatayama Hirofumi MZ {
fetchColorColorTool61408397115SKatayama Hirofumi MZ     void fetchColor(BOOL bLeftButton, LONG x, LONG y)
615ee132a05SKatayama Hirofumi MZ     {
61608397115SKatayama Hirofumi MZ         COLORREF rgbColor;
617ee132a05SKatayama Hirofumi MZ 
618ee132a05SKatayama Hirofumi MZ         if (0 <= x && x < imageModel.GetWidth() && 0 <= y && y < imageModel.GetHeight())
61908397115SKatayama Hirofumi MZ             rgbColor = GetPixel(m_hdc, x, y);
620ee132a05SKatayama Hirofumi MZ         else
62108397115SKatayama Hirofumi MZ             rgbColor = RGB(255, 255, 255); // Outside is white
622ee132a05SKatayama Hirofumi MZ 
623ee132a05SKatayama Hirofumi MZ         if (bLeftButton)
62408397115SKatayama Hirofumi MZ             paletteModel.SetFgColor(rgbColor);
625ee132a05SKatayama Hirofumi MZ         else
62608397115SKatayama Hirofumi MZ             paletteModel.SetBgColor(rgbColor);
62708397115SKatayama Hirofumi MZ     }
628ee132a05SKatayama Hirofumi MZ 
OnMouseMoveColorTool629389d0465SKatayama Hirofumi MZ     BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
63008397115SKatayama Hirofumi MZ     {
63108397115SKatayama Hirofumi MZ         fetchColor(bLeftButton, x, y);
632389d0465SKatayama Hirofumi MZ         return TRUE;
63308397115SKatayama Hirofumi MZ     }
63408397115SKatayama Hirofumi MZ 
OnButtonUpColorTool635389d0465SKatayama Hirofumi MZ     BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
63608397115SKatayama Hirofumi MZ     {
63708397115SKatayama Hirofumi MZ         fetchColor(bLeftButton, x, y);
638ee132a05SKatayama Hirofumi MZ         toolsModel.SetActiveTool(toolsModel.GetOldActiveTool());
639389d0465SKatayama Hirofumi MZ         return TRUE;
640ee132a05SKatayama Hirofumi MZ     }
641ee132a05SKatayama Hirofumi MZ };
642ee132a05SKatayama Hirofumi MZ 
643ee132a05SKatayama Hirofumi MZ // TOOL_ZOOM
644ee132a05SKatayama Hirofumi MZ struct ZoomTool : ToolBase
645ee132a05SKatayama Hirofumi MZ {
6468f1eb03aSKatayama Hirofumi MZ     BOOL m_bZoomed = FALSE;
6478f1eb03aSKatayama Hirofumi MZ 
6488f1eb03aSKatayama Hirofumi MZ     BOOL getNewZoomRect(CRect& rcView, INT newZoom);
6498f1eb03aSKatayama Hirofumi MZ 
OnDrawOverlayOnCanvasZoomTool65062eeb158SKatayama Hirofumi MZ     void OnDrawOverlayOnCanvas(HDC hdc) override
65162eeb158SKatayama Hirofumi MZ     {
6528f1eb03aSKatayama Hirofumi MZ         CRect rcView;
6538f1eb03aSKatayama Hirofumi MZ         INT oldZoom = toolsModel.GetZoom();
6548f1eb03aSKatayama Hirofumi MZ         if (oldZoom < MAX_ZOOM && getNewZoomRect(rcView, oldZoom * 2))
6558f1eb03aSKatayama Hirofumi MZ             DrawXorRect(hdc, &rcView);
65662eeb158SKatayama Hirofumi MZ     }
65762eeb158SKatayama Hirofumi MZ 
OnButtonDownZoomTool6586d9b7f77SKatayama Hirofumi MZ     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
659ee132a05SKatayama Hirofumi MZ     {
6608f1eb03aSKatayama Hirofumi MZ         INT newZoom, oldZoom = toolsModel.GetZoom();
661ee132a05SKatayama Hirofumi MZ         if (bLeftButton)
6628f1eb03aSKatayama Hirofumi MZ             newZoom = (oldZoom < MAX_ZOOM) ? (oldZoom * 2) : MIN_ZOOM;
663ee132a05SKatayama Hirofumi MZ         else
6648f1eb03aSKatayama Hirofumi MZ             newZoom = (oldZoom > MIN_ZOOM) ? (oldZoom / 2) : MAX_ZOOM;
6658f1eb03aSKatayama Hirofumi MZ 
6668f1eb03aSKatayama Hirofumi MZ         m_bZoomed = FALSE;
6678f1eb03aSKatayama Hirofumi MZ 
6688f1eb03aSKatayama Hirofumi MZ         if (oldZoom != newZoom)
669ee132a05SKatayama Hirofumi MZ         {
6708f1eb03aSKatayama Hirofumi MZ             CRect rcView;
6718f1eb03aSKatayama Hirofumi MZ             if (getNewZoomRect(rcView, newZoom))
6728f1eb03aSKatayama Hirofumi MZ             {
6738f1eb03aSKatayama Hirofumi MZ                 canvasWindow.zoomTo(newZoom, rcView.left, rcView.top);
6748f1eb03aSKatayama Hirofumi MZ                 m_bZoomed = TRUE;
675ee132a05SKatayama Hirofumi MZ             }
676ee132a05SKatayama Hirofumi MZ         }
6778f1eb03aSKatayama Hirofumi MZ     }
6788f1eb03aSKatayama Hirofumi MZ 
OnButtonUpZoomTool6798f1eb03aSKatayama Hirofumi MZ     BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
6808f1eb03aSKatayama Hirofumi MZ     {
6818f1eb03aSKatayama Hirofumi MZ         if (m_bZoomed)
6828f1eb03aSKatayama Hirofumi MZ             toolsModel.SetActiveTool(toolsModel.GetOldActiveTool());
6838f1eb03aSKatayama Hirofumi MZ 
6848f1eb03aSKatayama Hirofumi MZ         return TRUE;
6858f1eb03aSKatayama Hirofumi MZ     }
686ee132a05SKatayama Hirofumi MZ };
687ee132a05SKatayama Hirofumi MZ 
getNewZoomRect(CRect & rcView,INT newZoom)6888f1eb03aSKatayama Hirofumi MZ BOOL ZoomTool::getNewZoomRect(CRect& rcView, INT newZoom)
6898f1eb03aSKatayama Hirofumi MZ {
6908f1eb03aSKatayama Hirofumi MZ     CPoint pt;
6918f1eb03aSKatayama Hirofumi MZ     ::GetCursorPos(&pt);
6928f1eb03aSKatayama Hirofumi MZ     canvasWindow.ScreenToClient(&pt);
6938f1eb03aSKatayama Hirofumi MZ 
6948f1eb03aSKatayama Hirofumi MZ     canvasWindow.getNewZoomRect(rcView, newZoom, pt);
6958f1eb03aSKatayama Hirofumi MZ 
6968f1eb03aSKatayama Hirofumi MZ     CRect rc;
6978f1eb03aSKatayama Hirofumi MZ     canvasWindow.GetImageRect(rc);
6988f1eb03aSKatayama Hirofumi MZ     canvasWindow.ImageToCanvas(rc);
6998f1eb03aSKatayama Hirofumi MZ 
7008f1eb03aSKatayama Hirofumi MZ     return rc.PtInRect(pt);
7018f1eb03aSKatayama Hirofumi MZ }
7028f1eb03aSKatayama Hirofumi MZ 
703ee132a05SKatayama Hirofumi MZ // TOOL_PEN
704e8c7e300SKatayama Hirofumi MZ struct PenTool : SmoothDrawTool
705ee132a05SKatayama Hirofumi MZ {
OnDrawPenTool706e5792200SKatayama Hirofumi MZ     void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) override
707ee132a05SKatayama Hirofumi MZ     {
708ee132a05SKatayama Hirofumi MZ         COLORREF rgb = bLeftButton ? m_fg : m_bg;
709e5792200SKatayama Hirofumi MZ         Line(hdc, pt0.x, pt0.y, pt1.x, pt1.y, rgb, toolsModel.GetPenWidth());
710f2a01224SKatayama Hirofumi MZ     }
711f2a01224SKatayama Hirofumi MZ 
OnSpecialTweakPenTool712f2a01224SKatayama Hirofumi MZ     void OnSpecialTweak(BOOL bMinus) override
713f2a01224SKatayama Hirofumi MZ     {
714f2a01224SKatayama Hirofumi MZ         toolsModel.MakePenThickerOrThinner(bMinus);
715ee132a05SKatayama Hirofumi MZ     }
716ee132a05SKatayama Hirofumi MZ };
717ee132a05SKatayama Hirofumi MZ 
718ee132a05SKatayama Hirofumi MZ // TOOL_BRUSH
719e8c7e300SKatayama Hirofumi MZ struct BrushTool : SmoothDrawTool
720ee132a05SKatayama Hirofumi MZ {
OnDrawBrushTool721e5792200SKatayama Hirofumi MZ     void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) override
722ee132a05SKatayama Hirofumi MZ     {
723ee132a05SKatayama Hirofumi MZ         COLORREF rgb = bLeftButton ? m_fg : m_bg;
724e5792200SKatayama Hirofumi MZ         Brush(hdc, pt0.x, pt0.y, pt1.x, pt1.y, rgb, toolsModel.GetBrushStyle(),
7258a4787b3SKatayama Hirofumi MZ               toolsModel.GetBrushWidth());
726f2a01224SKatayama Hirofumi MZ     }
727f2a01224SKatayama Hirofumi MZ 
OnSpecialTweakBrushTool728f2a01224SKatayama Hirofumi MZ     void OnSpecialTweak(BOOL bMinus) override
729f2a01224SKatayama Hirofumi MZ     {
7308a4787b3SKatayama Hirofumi MZ         toolsModel.MakeBrushThickerOrThinner(bMinus);
731ee132a05SKatayama Hirofumi MZ     }
732ee132a05SKatayama Hirofumi MZ };
733ee132a05SKatayama Hirofumi MZ 
734ee132a05SKatayama Hirofumi MZ // TOOL_AIRBRUSH
735e8c7e300SKatayama Hirofumi MZ struct AirBrushTool : SmoothDrawTool
736ee132a05SKatayama Hirofumi MZ {
737e5792200SKatayama Hirofumi MZ     DWORD m_dwTick = 0;
738e5792200SKatayama Hirofumi MZ 
OnButtonDownAirBrushTool739e5792200SKatayama Hirofumi MZ     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
740e5792200SKatayama Hirofumi MZ     {
741e5792200SKatayama Hirofumi MZ         m_dwTick = GetTickCount();
742e5792200SKatayama Hirofumi MZ         SmoothDrawTool::OnButtonDown(bLeftButton, x, y, bDoubleClick);
743e5792200SKatayama Hirofumi MZ     }
744e5792200SKatayama Hirofumi MZ 
OnDrawOverlayOnImageAirBrushTool745e5792200SKatayama Hirofumi MZ     void OnDrawOverlayOnImage(HDC hdc) override
746e5792200SKatayama Hirofumi MZ     {
747e5792200SKatayama Hirofumi MZ         srand(m_dwTick);
748e5792200SKatayama Hirofumi MZ         SmoothDrawTool::OnDrawOverlayOnImage(hdc);
749e5792200SKatayama Hirofumi MZ     }
750e5792200SKatayama Hirofumi MZ 
OnDrawAirBrushTool751e5792200SKatayama Hirofumi MZ     void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) override
752ee132a05SKatayama Hirofumi MZ     {
753ee132a05SKatayama Hirofumi MZ         COLORREF rgb = bLeftButton ? m_fg : m_bg;
754e5792200SKatayama Hirofumi MZ         Airbrush(hdc, pt1.x, pt1.y, rgb, toolsModel.GetAirBrushRadius());
755ee132a05SKatayama Hirofumi MZ     }
756945ee4b2SKatayama Hirofumi MZ 
OnSpecialTweakAirBrushTool757945ee4b2SKatayama Hirofumi MZ     void OnSpecialTweak(BOOL bMinus) override
758945ee4b2SKatayama Hirofumi MZ     {
759945ee4b2SKatayama Hirofumi MZ         toolsModel.MakeAirBrushThickerOrThinner(bMinus);
760945ee4b2SKatayama Hirofumi MZ     }
761ee132a05SKatayama Hirofumi MZ };
762ee132a05SKatayama Hirofumi MZ 
763ee132a05SKatayama Hirofumi MZ // TOOL_TEXT
764ee132a05SKatayama Hirofumi MZ struct TextTool : ToolBase
765ee132a05SKatayama Hirofumi MZ {
OnDrawOverlayOnImageTextTool766e8c7e300SKatayama Hirofumi MZ     void OnDrawOverlayOnImage(HDC hdc) override
767e8c7e300SKatayama Hirofumi MZ     {
768e8c7e300SKatayama Hirofumi MZ         if (canvasWindow.m_drawing)
769e8c7e300SKatayama Hirofumi MZ         {
7701aeebfdaSKatayama Hirofumi MZ             CRect& rc = selectionModel.m_rc;
7711aeebfdaSKatayama Hirofumi MZ             if (!rc.IsRectEmpty())
772e8c7e300SKatayama Hirofumi MZ                 RectSel(hdc, rc.left, rc.top, rc.right, rc.bottom);
773e8c7e300SKatayama Hirofumi MZ         }
774e8c7e300SKatayama Hirofumi MZ     }
775e8c7e300SKatayama Hirofumi MZ 
UpdatePointTextTool776361a2ce4SKatayama Hirofumi MZ     void UpdatePoint(LONG x, LONG y)
777c2c66affSColin Finck     {
77808397115SKatayama Hirofumi MZ         POINT pt = { x, y };
779d04e0492SKatayama Hirofumi MZ         imageModel.Clamp(pt);
780e8c7e300SKatayama Hirofumi MZ         selectionModel.SetRectFromPoints(g_ptStart, pt);
781e8c7e300SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
782c2c66affSColin Finck     }
783c2c66affSColin Finck 
OnButtonDownTextTool7846d9b7f77SKatayama Hirofumi MZ     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
785361a2ce4SKatayama Hirofumi MZ     {
786361a2ce4SKatayama Hirofumi MZ         if (!textEditWindow.IsWindow())
787efe7368cSKatayama Hirofumi MZ             textEditWindow.Create(canvasWindow);
788361a2ce4SKatayama Hirofumi MZ 
789361a2ce4SKatayama Hirofumi MZ         UpdatePoint(x, y);
790361a2ce4SKatayama Hirofumi MZ     }
791361a2ce4SKatayama Hirofumi MZ 
OnMouseMoveTextTool792389d0465SKatayama Hirofumi MZ     BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
793361a2ce4SKatayama Hirofumi MZ     {
794361a2ce4SKatayama Hirofumi MZ         UpdatePoint(x, y);
795389d0465SKatayama Hirofumi MZ         return TRUE;
796361a2ce4SKatayama Hirofumi MZ     }
797361a2ce4SKatayama Hirofumi MZ 
drawTextTool798e8c7e300SKatayama Hirofumi MZ     void draw(HDC hdc)
799361a2ce4SKatayama Hirofumi MZ     {
800640d67d1SKatayama Hirofumi MZ         CStringW szText;
801361a2ce4SKatayama Hirofumi MZ         textEditWindow.GetWindowText(szText);
802361a2ce4SKatayama Hirofumi MZ 
8031aeebfdaSKatayama Hirofumi MZ         CRect rc;
804361a2ce4SKatayama Hirofumi MZ         textEditWindow.InvalidateEditRect();
805361a2ce4SKatayama Hirofumi MZ         textEditWindow.GetEditRect(&rc);
8061aeebfdaSKatayama Hirofumi MZ         rc.InflateRect(-GRIP_SIZE / 2, -GRIP_SIZE / 2);
807361a2ce4SKatayama Hirofumi MZ 
808bddd8b05SKatayama Hirofumi MZ         // Draw the text
809361a2ce4SKatayama Hirofumi MZ         INT style = (toolsModel.IsBackgroundTransparent() ? 0 : 1);
810e8c7e300SKatayama Hirofumi MZ         Text(hdc, rc.left, rc.top, rc.right, rc.bottom, m_fg, m_bg, szText,
811361a2ce4SKatayama Hirofumi MZ              textEditWindow.GetFont(), style);
812e8c7e300SKatayama Hirofumi MZ     }
813e8c7e300SKatayama Hirofumi MZ 
quitTextTool814e8c7e300SKatayama Hirofumi MZ     void quit()
815e8c7e300SKatayama Hirofumi MZ     {
816e8c7e300SKatayama Hirofumi MZ         if (textEditWindow.IsWindow())
817e8c7e300SKatayama Hirofumi MZ             textEditWindow.ShowWindow(SW_HIDE);
818e8c7e300SKatayama Hirofumi MZ         selectionModel.HideSelection();
819e8c7e300SKatayama Hirofumi MZ     }
820e8c7e300SKatayama Hirofumi MZ 
OnButtonUpTextTool821389d0465SKatayama Hirofumi MZ     BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
822e8c7e300SKatayama Hirofumi MZ     {
823e8c7e300SKatayama Hirofumi MZ         POINT pt = { x, y };
824d04e0492SKatayama Hirofumi MZ         imageModel.Clamp(pt);
825e8c7e300SKatayama Hirofumi MZ         selectionModel.SetRectFromPoints(g_ptStart, pt);
826e8c7e300SKatayama Hirofumi MZ 
827e8c7e300SKatayama Hirofumi MZ         BOOL bTextBoxShown = ::IsWindowVisible(textEditWindow);
8287aadc1e1SKatayama Hirofumi MZ         if (bTextBoxShown)
8297aadc1e1SKatayama Hirofumi MZ         {
8307aadc1e1SKatayama Hirofumi MZ             if (textEditWindow.GetWindowTextLength() > 0)
831e8c7e300SKatayama Hirofumi MZ             {
8329f56e67bSKatayama Hirofumi MZ                 imageModel.PushImageForUndo();
833e8c7e300SKatayama Hirofumi MZ                 draw(m_hdc);
8347aadc1e1SKatayama Hirofumi MZ             }
8351aeebfdaSKatayama Hirofumi MZ             if (selectionModel.m_rc.IsRectEmpty())
836aac89519SKatayama Hirofumi MZ             {
8379f56e67bSKatayama Hirofumi MZ                 quit();
838389d0465SKatayama Hirofumi MZ                 return TRUE;
839aac89519SKatayama Hirofumi MZ             }
840361a2ce4SKatayama Hirofumi MZ         }
841361a2ce4SKatayama Hirofumi MZ 
842361a2ce4SKatayama Hirofumi MZ         if (registrySettings.ShowTextTool)
843361a2ce4SKatayama Hirofumi MZ         {
844361a2ce4SKatayama Hirofumi MZ             if (!fontsDialog.IsWindow())
845361a2ce4SKatayama Hirofumi MZ                 fontsDialog.Create(mainWindow);
846361a2ce4SKatayama Hirofumi MZ 
847361a2ce4SKatayama Hirofumi MZ             fontsDialog.ShowWindow(SW_SHOWNOACTIVATE);
848361a2ce4SKatayama Hirofumi MZ         }
849361a2ce4SKatayama Hirofumi MZ 
8501aeebfdaSKatayama Hirofumi MZ         CRect rc = selectionModel.m_rc;
851361a2ce4SKatayama Hirofumi MZ 
852361a2ce4SKatayama Hirofumi MZ         // Enlarge if tool small
853361a2ce4SKatayama Hirofumi MZ         INT cxMin = CX_MINTEXTEDIT, cyMin = CY_MINTEXTEDIT;
854aac89519SKatayama Hirofumi MZ         if (selectionModel.m_rc.IsRectEmpty())
855aac89519SKatayama Hirofumi MZ         {
8561aeebfdaSKatayama Hirofumi MZ             rc.SetRect(x, y, x + cxMin, y + cyMin);
857aac89519SKatayama Hirofumi MZ         }
858aac89519SKatayama Hirofumi MZ         else
859c2c66affSColin Finck         {
860361a2ce4SKatayama Hirofumi MZ             if (rc.right - rc.left < cxMin)
861361a2ce4SKatayama Hirofumi MZ                 rc.right = rc.left + cxMin;
862361a2ce4SKatayama Hirofumi MZ             if (rc.bottom - rc.top < cyMin)
863361a2ce4SKatayama Hirofumi MZ                 rc.bottom = rc.top + cyMin;
864361a2ce4SKatayama Hirofumi MZ         }
865c2c66affSColin Finck 
866361a2ce4SKatayama Hirofumi MZ         if (!textEditWindow.IsWindow())
867efe7368cSKatayama Hirofumi MZ             textEditWindow.Create(canvasWindow);
868361a2ce4SKatayama Hirofumi MZ 
869361a2ce4SKatayama Hirofumi MZ         textEditWindow.SetWindowText(NULL);
870361a2ce4SKatayama Hirofumi MZ         textEditWindow.ValidateEditRect(&rc);
871361a2ce4SKatayama Hirofumi MZ         textEditWindow.ShowWindow(SW_SHOWNOACTIVATE);
872361a2ce4SKatayama Hirofumi MZ         textEditWindow.SetFocus();
873389d0465SKatayama Hirofumi MZ         return TRUE;
874361a2ce4SKatayama Hirofumi MZ     }
875ee132a05SKatayama Hirofumi MZ 
OnEndDrawTextTool87637f56d24SKatayama Hirofumi MZ     void OnEndDraw(BOOL bCancel) override
87737f56d24SKatayama Hirofumi MZ     {
87837f56d24SKatayama Hirofumi MZ         if (!bCancel)
879ee132a05SKatayama Hirofumi MZ         {
8803579ea78SKatayama Hirofumi MZ             if (::IsWindowVisible(textEditWindow) &&
8813579ea78SKatayama Hirofumi MZ                 textEditWindow.GetWindowTextLength() > 0)
8827aadc1e1SKatayama Hirofumi MZ             {
8839f56e67bSKatayama Hirofumi MZ                 imageModel.PushImageForUndo();
884e8c7e300SKatayama Hirofumi MZ                 draw(m_hdc);
8857aadc1e1SKatayama Hirofumi MZ             }
886c2c66affSColin Finck         }
887e8c7e300SKatayama Hirofumi MZ         quit();
88837f56d24SKatayama Hirofumi MZ         ToolBase::OnEndDraw(bCancel);
889e8c7e300SKatayama Hirofumi MZ     }
890ee132a05SKatayama Hirofumi MZ };
891ee132a05SKatayama Hirofumi MZ 
892ee132a05SKatayama Hirofumi MZ // TOOL_LINE
893e8c7e300SKatayama Hirofumi MZ struct LineTool : TwoPointDrawTool
894c2c66affSColin Finck {
OnDrawOverlayOnImageLineTool895e8c7e300SKatayama Hirofumi MZ     void OnDrawOverlayOnImage(HDC hdc) override
896ee132a05SKatayama Hirofumi MZ     {
897e8c7e300SKatayama Hirofumi MZ         if (!m_bDrawing)
898e8c7e300SKatayama Hirofumi MZ             return;
899c2c66affSColin Finck         if (GetAsyncKeyState(VK_SHIFT) < 0)
900e8c7e300SKatayama Hirofumi MZ             roundTo8Directions(g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y);
901e8c7e300SKatayama Hirofumi MZ         COLORREF rgb = m_bLeftButton ? m_fg : m_bg;
902e8c7e300SKatayama Hirofumi MZ         Line(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, rgb, toolsModel.GetLineWidth());
903ee132a05SKatayama Hirofumi MZ     }
904ee132a05SKatayama Hirofumi MZ };
905ee132a05SKatayama Hirofumi MZ 
906ee132a05SKatayama Hirofumi MZ // TOOL_BEZIER
907ee132a05SKatayama Hirofumi MZ struct BezierTool : ToolBase
908c2c66affSColin Finck {
909e8c7e300SKatayama Hirofumi MZ     BOOL m_bLeftButton = FALSE;
91008397115SKatayama Hirofumi MZ 
OnDrawOverlayOnImageBezierTool911e8c7e300SKatayama Hirofumi MZ     void OnDrawOverlayOnImage(HDC hdc)
912c2c66affSColin Finck     {
913e8c7e300SKatayama Hirofumi MZ         COLORREF rgb = (m_bLeftButton ? m_fg : m_bg);
914*3799d37aSKatayama Hirofumi MZ         switch (s_cPoints)
915c2c66affSColin Finck         {
916e5792200SKatayama Hirofumi MZ             case 2:
917*3799d37aSKatayama Hirofumi MZ                 Line(hdc, s_pPoints[0].x, s_pPoints[0].y, s_pPoints[1].x, s_pPoints[1].y, rgb,
918c2c66affSColin Finck                      toolsModel.GetLineWidth());
919c2c66affSColin Finck                 break;
920e5792200SKatayama Hirofumi MZ             case 3:
921*3799d37aSKatayama Hirofumi MZ                 Bezier(hdc, s_pPoints[0], s_pPoints[2], s_pPoints[2], s_pPoints[1], rgb, toolsModel.GetLineWidth());
922c2c66affSColin Finck                 break;
923e5792200SKatayama Hirofumi MZ             case 4:
924*3799d37aSKatayama Hirofumi MZ                 Bezier(hdc, s_pPoints[0], s_pPoints[2], s_pPoints[3], s_pPoints[1], rgb, toolsModel.GetLineWidth());
925c2c66affSColin Finck                 break;
926c2c66affSColin Finck         }
927ee132a05SKatayama Hirofumi MZ     }
928ee132a05SKatayama Hirofumi MZ 
OnButtonDownBezierTool9296d9b7f77SKatayama Hirofumi MZ     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
930ee132a05SKatayama Hirofumi MZ     {
931e8c7e300SKatayama Hirofumi MZ         m_bLeftButton = bLeftButton;
932e8c7e300SKatayama Hirofumi MZ 
933*3799d37aSKatayama Hirofumi MZ         if (s_cPoints == 0)
934e8c7e300SKatayama Hirofumi MZ         {
935*3799d37aSKatayama Hirofumi MZ             pushToPoints(x, y);
936*3799d37aSKatayama Hirofumi MZ             pushToPoints(x, y);
937e8c7e300SKatayama Hirofumi MZ         }
938e8c7e300SKatayama Hirofumi MZ         else
939e8c7e300SKatayama Hirofumi MZ         {
940*3799d37aSKatayama Hirofumi MZ             s_pPoints[s_cPoints - 1] = { x, y };
941ee132a05SKatayama Hirofumi MZ         }
942e8c7e300SKatayama Hirofumi MZ 
943e8c7e300SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
944ee132a05SKatayama Hirofumi MZ     }
945ee132a05SKatayama Hirofumi MZ 
OnMouseMoveBezierTool946389d0465SKatayama Hirofumi MZ     BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
947ee132a05SKatayama Hirofumi MZ     {
948*3799d37aSKatayama Hirofumi MZ         if (s_cPoints > 0)
949*3799d37aSKatayama Hirofumi MZ             s_pPoints[s_cPoints - 1] = { x, y };
950e8c7e300SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
951389d0465SKatayama Hirofumi MZ         return TRUE;
952c2c66affSColin Finck     }
953c2c66affSColin Finck 
OnButtonUpBezierTool954389d0465SKatayama Hirofumi MZ     BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
955c2c66affSColin Finck     {
956*3799d37aSKatayama Hirofumi MZ         if (s_cPoints >= 4)
957e8c7e300SKatayama Hirofumi MZ         {
95837f56d24SKatayama Hirofumi MZ             OnEndDraw(FALSE);
959389d0465SKatayama Hirofumi MZ             return TRUE;
960e8c7e300SKatayama Hirofumi MZ         }
961*3799d37aSKatayama Hirofumi MZ         pushToPoints(x, y);
962bfd42c67SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
963389d0465SKatayama Hirofumi MZ         return TRUE;
964ee132a05SKatayama Hirofumi MZ     }
965ee132a05SKatayama Hirofumi MZ 
OnEndDrawBezierTool96637f56d24SKatayama Hirofumi MZ     void OnEndDraw(BOOL bCancel) override
967ee132a05SKatayama Hirofumi MZ     {
968*3799d37aSKatayama Hirofumi MZ         if (!bCancel && s_cPoints > 1)
96908397115SKatayama Hirofumi MZ         {
970e5792200SKatayama Hirofumi MZ             // FIXME: I couldn't calculate boundary rectangle from Bezier curve
971e8c7e300SKatayama Hirofumi MZ             imageModel.PushImageForUndo();
972e8c7e300SKatayama Hirofumi MZ             OnDrawOverlayOnImage(m_hdc);
97337f56d24SKatayama Hirofumi MZ         }
97437f56d24SKatayama Hirofumi MZ         ToolBase::OnEndDraw(bCancel);
97508397115SKatayama Hirofumi MZ     }
976f2a01224SKatayama Hirofumi MZ 
OnSpecialTweakBezierTool977f2a01224SKatayama Hirofumi MZ     void OnSpecialTweak(BOOL bMinus) override
978f2a01224SKatayama Hirofumi MZ     {
979f2a01224SKatayama Hirofumi MZ         toolsModel.MakeLineThickerOrThinner(bMinus);
980f2a01224SKatayama Hirofumi MZ     }
981ee132a05SKatayama Hirofumi MZ };
982ee132a05SKatayama Hirofumi MZ 
983ee132a05SKatayama Hirofumi MZ // TOOL_RECT
984e8c7e300SKatayama Hirofumi MZ struct RectTool : TwoPointDrawTool
985ee132a05SKatayama Hirofumi MZ {
OnDrawOverlayOnImageRectTool986e8c7e300SKatayama Hirofumi MZ     void OnDrawOverlayOnImage(HDC hdc) override
987ee132a05SKatayama Hirofumi MZ     {
988e8c7e300SKatayama Hirofumi MZ         if (!m_bDrawing)
989e8c7e300SKatayama Hirofumi MZ             return;
990c2c66affSColin Finck         if (GetAsyncKeyState(VK_SHIFT) < 0)
991e8c7e300SKatayama Hirofumi MZ             regularize(g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y);
992e8c7e300SKatayama Hirofumi MZ         if (m_bLeftButton)
993e8c7e300SKatayama Hirofumi MZ             Rect(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
994ee132a05SKatayama Hirofumi MZ         else
995e8c7e300SKatayama Hirofumi MZ             Rect(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
996ee132a05SKatayama Hirofumi MZ     }
997ee132a05SKatayama Hirofumi MZ };
998ee132a05SKatayama Hirofumi MZ 
999ee132a05SKatayama Hirofumi MZ // TOOL_SHAPE
1000ee132a05SKatayama Hirofumi MZ struct ShapeTool : ToolBase
1001ee132a05SKatayama Hirofumi MZ {
1002e8c7e300SKatayama Hirofumi MZ     BOOL m_bLeftButton = FALSE;
1003e8c7e300SKatayama Hirofumi MZ     BOOL m_bClosed = FALSE;
100408397115SKatayama Hirofumi MZ 
OnDrawOverlayOnImageShapeTool1005e8c7e300SKatayama Hirofumi MZ     void OnDrawOverlayOnImage(HDC hdc)
1006ee132a05SKatayama Hirofumi MZ     {
1007*3799d37aSKatayama Hirofumi MZ         if (s_cPoints <= 0)
1008e8c7e300SKatayama Hirofumi MZ             return;
1009e8c7e300SKatayama Hirofumi MZ 
1010e8c7e300SKatayama Hirofumi MZ         if (m_bLeftButton)
1011*3799d37aSKatayama Hirofumi MZ             Poly(hdc, s_pPoints, (INT)s_cPoints, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), m_bClosed, FALSE);
1012ee132a05SKatayama Hirofumi MZ         else
1013*3799d37aSKatayama Hirofumi MZ             Poly(hdc, s_pPoints, (INT)s_cPoints, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), m_bClosed, FALSE);
1014ee132a05SKatayama Hirofumi MZ     }
1015ee132a05SKatayama Hirofumi MZ 
OnButtonDownShapeTool10166d9b7f77SKatayama Hirofumi MZ     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
1017ee132a05SKatayama Hirofumi MZ     {
1018e8c7e300SKatayama Hirofumi MZ         m_bLeftButton = bLeftButton;
1019e8c7e300SKatayama Hirofumi MZ         m_bClosed = FALSE;
1020e8c7e300SKatayama Hirofumi MZ 
1021*3799d37aSKatayama Hirofumi MZ         if ((s_cPoints > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
1022*3799d37aSKatayama Hirofumi MZ             roundTo8Directions(s_pPoints[s_cPoints - 1].x, s_pPoints[s_cPoints - 1].y, x, y);
10233fa6d74aSKatayama Hirofumi MZ 
1024*3799d37aSKatayama Hirofumi MZ         pushToPoints(x, y);
1025ee132a05SKatayama Hirofumi MZ 
1026*3799d37aSKatayama Hirofumi MZ         if (s_cPoints > 1 && bDoubleClick)
1027ee132a05SKatayama Hirofumi MZ         {
102837f56d24SKatayama Hirofumi MZ             OnEndDraw(FALSE);
1029e8c7e300SKatayama Hirofumi MZ             return;
1030e8c7e300SKatayama Hirofumi MZ         }
1031e8c7e300SKatayama Hirofumi MZ 
1032*3799d37aSKatayama Hirofumi MZ         if (s_cPoints == 1)
1033*3799d37aSKatayama Hirofumi MZ             pushToPoints(x, y); // We have to draw the first point
1034e8c7e300SKatayama Hirofumi MZ 
1035bfd42c67SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
1036ee132a05SKatayama Hirofumi MZ     }
1037ee132a05SKatayama Hirofumi MZ 
OnMouseMoveShapeTool1038389d0465SKatayama Hirofumi MZ     BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
1039ee132a05SKatayama Hirofumi MZ     {
1040*3799d37aSKatayama Hirofumi MZ         if (s_cPoints > 1)
1041e5792200SKatayama Hirofumi MZ         {
1042e5792200SKatayama Hirofumi MZ             if (GetAsyncKeyState(VK_SHIFT) < 0)
1043*3799d37aSKatayama Hirofumi MZ                 roundTo8Directions(s_pPoints[s_cPoints - 2].x, s_pPoints[s_cPoints - 2].y, x, y);
1044e8c7e300SKatayama Hirofumi MZ 
1045*3799d37aSKatayama Hirofumi MZ             s_pPoints[s_cPoints - 1] = { x, y };
1046e5792200SKatayama Hirofumi MZ         }
10473fa6d74aSKatayama Hirofumi MZ 
1048e8c7e300SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
1049389d0465SKatayama Hirofumi MZ         return TRUE;
1050ee132a05SKatayama Hirofumi MZ     }
1051ee132a05SKatayama Hirofumi MZ 
OnButtonUpShapeTool1052389d0465SKatayama Hirofumi MZ     BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
1053c2c66affSColin Finck     {
1054*3799d37aSKatayama Hirofumi MZ         if ((s_cPoints > 1) && (GetAsyncKeyState(VK_SHIFT) < 0))
1055*3799d37aSKatayama Hirofumi MZ             roundTo8Directions(s_pPoints[s_cPoints - 2].x, s_pPoints[s_cPoints - 2].y, x, y);
1056ee132a05SKatayama Hirofumi MZ 
1057e8c7e300SKatayama Hirofumi MZ         m_bClosed = FALSE;
1058*3799d37aSKatayama Hirofumi MZ         if (nearlyEqualPoints(x, y, s_pPoints[0].x, s_pPoints[0].y))
1059c2c66affSColin Finck         {
106037f56d24SKatayama Hirofumi MZ             OnEndDraw(FALSE);
1061389d0465SKatayama Hirofumi MZ             return TRUE;
1062c2c66affSColin Finck         }
1063ee132a05SKatayama Hirofumi MZ 
1064*3799d37aSKatayama Hirofumi MZ         pushToPoints(x, y);
1065e8c7e300SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
1066389d0465SKatayama Hirofumi MZ         return TRUE;
1067c2c66affSColin Finck     }
1068ee132a05SKatayama Hirofumi MZ 
OnEndDrawShapeTool106937f56d24SKatayama Hirofumi MZ     void OnEndDraw(BOOL bCancel) override
1070ee132a05SKatayama Hirofumi MZ     {
1071*3799d37aSKatayama Hirofumi MZ         if (!bCancel && s_cPoints > 1)
107208397115SKatayama Hirofumi MZ         {
1073e5792200SKatayama Hirofumi MZ             CRect rcPartial;
1074*3799d37aSKatayama Hirofumi MZ             getBoundaryOfPoints(rcPartial, s_cPoints, s_pPoints);
1075e8c7e300SKatayama Hirofumi MZ 
1076e5792200SKatayama Hirofumi MZ             SIZE size = toolsModel.GetToolSize();
1077e5792200SKatayama Hirofumi MZ             rcPartial.InflateRect((size.cx + 1) / 2, (size.cy + 1) / 2);
1078e5792200SKatayama Hirofumi MZ 
1079e5792200SKatayama Hirofumi MZ             imageModel.PushImageForUndo(rcPartial);
1080e5792200SKatayama Hirofumi MZ 
1081e5792200SKatayama Hirofumi MZ             m_bClosed = TRUE;
1082e8c7e300SKatayama Hirofumi MZ             OnDrawOverlayOnImage(m_hdc);
108308397115SKatayama Hirofumi MZ         }
1084e8c7e300SKatayama Hirofumi MZ         m_bClosed = FALSE;
108537f56d24SKatayama Hirofumi MZ         ToolBase::OnEndDraw(bCancel);
108608397115SKatayama Hirofumi MZ     }
1087f2a01224SKatayama Hirofumi MZ 
OnSpecialTweakShapeTool1088f2a01224SKatayama Hirofumi MZ     void OnSpecialTweak(BOOL bMinus) override
1089f2a01224SKatayama Hirofumi MZ     {
1090f2a01224SKatayama Hirofumi MZ         toolsModel.MakeLineThickerOrThinner(bMinus);
1091f2a01224SKatayama Hirofumi MZ     }
1092ee132a05SKatayama Hirofumi MZ };
1093ee132a05SKatayama Hirofumi MZ 
1094ee132a05SKatayama Hirofumi MZ // TOOL_ELLIPSE
1095e8c7e300SKatayama Hirofumi MZ struct EllipseTool : TwoPointDrawTool
1096ee132a05SKatayama Hirofumi MZ {
OnDrawOverlayOnImageEllipseTool1097e8c7e300SKatayama Hirofumi MZ     void OnDrawOverlayOnImage(HDC hdc) override
1098ee132a05SKatayama Hirofumi MZ     {
1099e8c7e300SKatayama Hirofumi MZ         if (!m_bDrawing)
1100e8c7e300SKatayama Hirofumi MZ             return;
1101ee132a05SKatayama Hirofumi MZ         if (GetAsyncKeyState(VK_SHIFT) < 0)
1102e8c7e300SKatayama Hirofumi MZ             regularize(g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y);
1103e8c7e300SKatayama Hirofumi MZ         if (m_bLeftButton)
1104e8c7e300SKatayama Hirofumi MZ             Ellp(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
1105ee132a05SKatayama Hirofumi MZ         else
1106e8c7e300SKatayama Hirofumi MZ             Ellp(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
1107ee132a05SKatayama Hirofumi MZ     }
1108ee132a05SKatayama Hirofumi MZ };
1109ee132a05SKatayama Hirofumi MZ 
1110ee132a05SKatayama Hirofumi MZ // TOOL_RRECT
1111e8c7e300SKatayama Hirofumi MZ struct RRectTool : TwoPointDrawTool
1112ee132a05SKatayama Hirofumi MZ {
OnDrawOverlayOnImageRRectTool1113e8c7e300SKatayama Hirofumi MZ     void OnDrawOverlayOnImage(HDC hdc) override
1114ee132a05SKatayama Hirofumi MZ     {
1115e8c7e300SKatayama Hirofumi MZ         if (!m_bDrawing)
1116e8c7e300SKatayama Hirofumi MZ             return;
1117ee132a05SKatayama Hirofumi MZ         if (GetAsyncKeyState(VK_SHIFT) < 0)
1118e8c7e300SKatayama Hirofumi MZ             regularize(g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y);
1119e8c7e300SKatayama Hirofumi MZ         if (m_bLeftButton)
1120e8c7e300SKatayama Hirofumi MZ             RRect(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
1121ee132a05SKatayama Hirofumi MZ         else
1122e8c7e300SKatayama Hirofumi MZ             RRect(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
1123ee132a05SKatayama Hirofumi MZ     }
1124ee132a05SKatayama Hirofumi MZ };
1125ee132a05SKatayama Hirofumi MZ 
1126ee132a05SKatayama Hirofumi MZ /*static*/ ToolBase*
createToolObject(TOOLTYPE type)1127ee132a05SKatayama Hirofumi MZ ToolBase::createToolObject(TOOLTYPE type)
1128ee132a05SKatayama Hirofumi MZ {
1129ee132a05SKatayama Hirofumi MZ     switch (type)
1130ee132a05SKatayama Hirofumi MZ     {
1131ee132a05SKatayama Hirofumi MZ         case TOOL_FREESEL:  return new FreeSelTool();
1132ee132a05SKatayama Hirofumi MZ         case TOOL_RECTSEL:  return new RectSelTool();
1133ee132a05SKatayama Hirofumi MZ         case TOOL_RUBBER:   return new RubberTool();
1134ee132a05SKatayama Hirofumi MZ         case TOOL_FILL:     return new FillTool();
1135ee132a05SKatayama Hirofumi MZ         case TOOL_COLOR:    return new ColorTool();
1136ee132a05SKatayama Hirofumi MZ         case TOOL_ZOOM:     return new ZoomTool();
1137ee132a05SKatayama Hirofumi MZ         case TOOL_PEN:      return new PenTool();
1138ee132a05SKatayama Hirofumi MZ         case TOOL_BRUSH:    return new BrushTool();
1139ee132a05SKatayama Hirofumi MZ         case TOOL_AIRBRUSH: return new AirBrushTool();
1140ee132a05SKatayama Hirofumi MZ         case TOOL_TEXT:     return new TextTool();
1141ee132a05SKatayama Hirofumi MZ         case TOOL_LINE:     return new LineTool();
1142ee132a05SKatayama Hirofumi MZ         case TOOL_BEZIER:   return new BezierTool();
1143ee132a05SKatayama Hirofumi MZ         case TOOL_RECT:     return new RectTool();
1144ee132a05SKatayama Hirofumi MZ         case TOOL_SHAPE:    return new ShapeTool();
1145ee132a05SKatayama Hirofumi MZ         case TOOL_ELLIPSE:  return new EllipseTool();
1146ee132a05SKatayama Hirofumi MZ         case TOOL_RRECT:    return new RRectTool();
1147ee132a05SKatayama Hirofumi MZ     }
1148ee132a05SKatayama Hirofumi MZ     UNREACHABLE;
1149ee132a05SKatayama Hirofumi MZ     return NULL;
1150c2c66affSColin Finck }
1151fa4b38d9SKatayama Hirofumi MZ 
OnButtonDown(BOOL bLeftButton,LONG x,LONG y,BOOL bDoubleClick)1152fa4b38d9SKatayama Hirofumi MZ void ToolsModel::OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
1153fa4b38d9SKatayama Hirofumi MZ {
1154fa4b38d9SKatayama Hirofumi MZ     m_pToolObject->beginEvent();
1155e5792200SKatayama Hirofumi MZ     g_ptEnd = g_ptStart = { x, y };
1156fa4b38d9SKatayama Hirofumi MZ     m_pToolObject->OnButtonDown(bLeftButton, x, y, bDoubleClick);
1157fa4b38d9SKatayama Hirofumi MZ     m_pToolObject->endEvent();
1158fa4b38d9SKatayama Hirofumi MZ }
1159fa4b38d9SKatayama Hirofumi MZ 
OnMouseMove(BOOL bLeftButton,LONG x,LONG y)1160fa4b38d9SKatayama Hirofumi MZ void ToolsModel::OnMouseMove(BOOL bLeftButton, LONG x, LONG y)
1161fa4b38d9SKatayama Hirofumi MZ {
1162fa4b38d9SKatayama Hirofumi MZ     m_pToolObject->beginEvent();
1163fa4b38d9SKatayama Hirofumi MZ     if (m_pToolObject->OnMouseMove(bLeftButton, x, y))
1164e5792200SKatayama Hirofumi MZ         g_ptEnd = { x, y };
1165e5792200SKatayama Hirofumi MZ 
1166fa4b38d9SKatayama Hirofumi MZ     m_pToolObject->endEvent();
1167fa4b38d9SKatayama Hirofumi MZ }
1168fa4b38d9SKatayama Hirofumi MZ 
OnButtonUp(BOOL bLeftButton,LONG x,LONG y)1169fa4b38d9SKatayama Hirofumi MZ void ToolsModel::OnButtonUp(BOOL bLeftButton, LONG x, LONG y)
1170fa4b38d9SKatayama Hirofumi MZ {
1171fa4b38d9SKatayama Hirofumi MZ     m_pToolObject->beginEvent();
1172fa4b38d9SKatayama Hirofumi MZ     if (m_pToolObject->OnButtonUp(bLeftButton, x, y))
1173e5792200SKatayama Hirofumi MZ         g_ptEnd = { x, y };
1174e5792200SKatayama Hirofumi MZ 
1175fa4b38d9SKatayama Hirofumi MZ     m_pToolObject->endEvent();
1176fa4b38d9SKatayama Hirofumi MZ }
1177fa4b38d9SKatayama Hirofumi MZ 
OnEndDraw(BOOL bCancel)1178fa4b38d9SKatayama Hirofumi MZ void ToolsModel::OnEndDraw(BOOL bCancel)
1179fa4b38d9SKatayama Hirofumi MZ {
1180fa4b38d9SKatayama Hirofumi MZ     ATLTRACE("ToolsModel::OnEndDraw(%d)\n", bCancel);
1181fa4b38d9SKatayama Hirofumi MZ     m_pToolObject->beginEvent();
1182fa4b38d9SKatayama Hirofumi MZ     m_pToolObject->OnEndDraw(bCancel);
1183fa4b38d9SKatayama Hirofumi MZ     m_pToolObject->endEvent();
1184fa4b38d9SKatayama Hirofumi MZ }
1185fa4b38d9SKatayama Hirofumi MZ 
OnDrawOverlayOnImage(HDC hdc)1186fa4b38d9SKatayama Hirofumi MZ void ToolsModel::OnDrawOverlayOnImage(HDC hdc)
1187fa4b38d9SKatayama Hirofumi MZ {
1188fa4b38d9SKatayama Hirofumi MZ     m_pToolObject->OnDrawOverlayOnImage(hdc);
1189fa4b38d9SKatayama Hirofumi MZ }
1190fa4b38d9SKatayama Hirofumi MZ 
OnDrawOverlayOnCanvas(HDC hdc)1191fa4b38d9SKatayama Hirofumi MZ void ToolsModel::OnDrawOverlayOnCanvas(HDC hdc)
1192fa4b38d9SKatayama Hirofumi MZ {
1193fa4b38d9SKatayama Hirofumi MZ     m_pToolObject->OnDrawOverlayOnCanvas(hdc);
1194fa4b38d9SKatayama Hirofumi MZ }
1195fa4b38d9SKatayama Hirofumi MZ 
SpecialTweak(BOOL bMinus)1196fa4b38d9SKatayama Hirofumi MZ void ToolsModel::SpecialTweak(BOOL bMinus)
1197fa4b38d9SKatayama Hirofumi MZ {
1198fa4b38d9SKatayama Hirofumi MZ     m_pToolObject->OnSpecialTweak(bMinus);
1199fa4b38d9SKatayama Hirofumi MZ }
1200fa4b38d9SKatayama Hirofumi MZ 
DrawWithMouseTool(POINT pt,WPARAM wParam)1201fa4b38d9SKatayama Hirofumi MZ void ToolsModel::DrawWithMouseTool(POINT pt, WPARAM wParam)
1202fa4b38d9SKatayama Hirofumi MZ {
1203fa4b38d9SKatayama Hirofumi MZ     LONG xRel = pt.x - g_ptStart.x, yRel = pt.y - g_ptStart.y;
1204fa4b38d9SKatayama Hirofumi MZ 
1205fa4b38d9SKatayama Hirofumi MZ     switch (m_activeTool)
1206fa4b38d9SKatayama Hirofumi MZ     {
1207fa4b38d9SKatayama Hirofumi MZ         // freesel, rectsel and text tools always show numbers limited to fit into image area
1208fa4b38d9SKatayama Hirofumi MZ         case TOOL_FREESEL:
1209fa4b38d9SKatayama Hirofumi MZ         case TOOL_RECTSEL:
1210fa4b38d9SKatayama Hirofumi MZ         case TOOL_TEXT:
1211fa4b38d9SKatayama Hirofumi MZ             if (xRel < 0)
1212fa4b38d9SKatayama Hirofumi MZ                 xRel = (pt.x < 0) ? -g_ptStart.x : xRel;
1213fa4b38d9SKatayama Hirofumi MZ             else if (pt.x > imageModel.GetWidth())
1214fa4b38d9SKatayama Hirofumi MZ                 xRel = imageModel.GetWidth() - g_ptStart.x;
1215fa4b38d9SKatayama Hirofumi MZ             if (yRel < 0)
1216fa4b38d9SKatayama Hirofumi MZ                 yRel = (pt.y < 0) ? -g_ptStart.y : yRel;
1217fa4b38d9SKatayama Hirofumi MZ             else if (pt.y > imageModel.GetHeight())
1218fa4b38d9SKatayama Hirofumi MZ                 yRel = imageModel.GetHeight() - g_ptStart.y;
1219fa4b38d9SKatayama Hirofumi MZ             break;
1220fa4b38d9SKatayama Hirofumi MZ 
1221fa4b38d9SKatayama Hirofumi MZ         // while drawing, update cursor coordinates only for tools 3, 7, 8, 9, 14
1222fa4b38d9SKatayama Hirofumi MZ         case TOOL_RUBBER:
1223fa4b38d9SKatayama Hirofumi MZ         case TOOL_PEN:
1224fa4b38d9SKatayama Hirofumi MZ         case TOOL_BRUSH:
1225fa4b38d9SKatayama Hirofumi MZ         case TOOL_AIRBRUSH:
1226fa4b38d9SKatayama Hirofumi MZ         case TOOL_SHAPE:
1227fa4b38d9SKatayama Hirofumi MZ         {
1228fa4b38d9SKatayama Hirofumi MZ             CStringW strCoord;
1229fa4b38d9SKatayama Hirofumi MZ             strCoord.Format(L"%ld, %ld", pt.x, pt.y);
1230fa4b38d9SKatayama Hirofumi MZ             ::SendMessageW(g_hStatusBar, SB_SETTEXT, 1, (LPARAM)(LPCWSTR)strCoord);
1231fa4b38d9SKatayama Hirofumi MZ             break;
1232fa4b38d9SKatayama Hirofumi MZ         }
1233fa4b38d9SKatayama Hirofumi MZ         default:
1234fa4b38d9SKatayama Hirofumi MZ             break;
1235fa4b38d9SKatayama Hirofumi MZ     }
1236fa4b38d9SKatayama Hirofumi MZ 
1237fa4b38d9SKatayama Hirofumi MZ     // rectsel and shape tools always show non-negative numbers when drawing
1238fa4b38d9SKatayama Hirofumi MZ     if (m_activeTool == TOOL_RECTSEL || m_activeTool == TOOL_SHAPE)
1239fa4b38d9SKatayama Hirofumi MZ     {
1240fa4b38d9SKatayama Hirofumi MZ         xRel = labs(xRel);
1241fa4b38d9SKatayama Hirofumi MZ         yRel = labs(yRel);
1242fa4b38d9SKatayama Hirofumi MZ     }
1243fa4b38d9SKatayama Hirofumi MZ 
1244fa4b38d9SKatayama Hirofumi MZ     if (wParam & MK_LBUTTON)
1245fa4b38d9SKatayama Hirofumi MZ     {
1246fa4b38d9SKatayama Hirofumi MZ         OnMouseMove(TRUE, pt.x, pt.y);
1247fa4b38d9SKatayama Hirofumi MZ         canvasWindow.Invalidate(FALSE);
1248fa4b38d9SKatayama Hirofumi MZ         if ((m_activeTool >= TOOL_TEXT) || IsSelection())
1249fa4b38d9SKatayama Hirofumi MZ         {
1250fa4b38d9SKatayama Hirofumi MZ             CStringW strSize;
1251fa4b38d9SKatayama Hirofumi MZ             if ((m_activeTool >= TOOL_LINE) && (GetAsyncKeyState(VK_SHIFT) < 0))
1252fa4b38d9SKatayama Hirofumi MZ                 yRel = xRel;
1253fa4b38d9SKatayama Hirofumi MZ             strSize.Format(L"%ld x %ld", xRel, yRel);
1254fa4b38d9SKatayama Hirofumi MZ             ::SendMessageW(g_hStatusBar, SB_SETTEXT, 2, (LPARAM)(LPCWSTR)strSize);
1255fa4b38d9SKatayama Hirofumi MZ         }
1256fa4b38d9SKatayama Hirofumi MZ     }
1257fa4b38d9SKatayama Hirofumi MZ 
1258fa4b38d9SKatayama Hirofumi MZ     if (wParam & MK_RBUTTON)
1259fa4b38d9SKatayama Hirofumi MZ     {
1260fa4b38d9SKatayama Hirofumi MZ         OnMouseMove(FALSE, pt.x, pt.y);
1261fa4b38d9SKatayama Hirofumi MZ         canvasWindow.Invalidate(FALSE);
1262fa4b38d9SKatayama Hirofumi MZ         if (m_activeTool >= TOOL_TEXT)
1263fa4b38d9SKatayama Hirofumi MZ         {
1264fa4b38d9SKatayama Hirofumi MZ             CStringW strSize;
1265fa4b38d9SKatayama Hirofumi MZ             if ((m_activeTool >= TOOL_LINE) && (GetAsyncKeyState(VK_SHIFT) < 0))
1266fa4b38d9SKatayama Hirofumi MZ                 yRel = xRel;
1267fa4b38d9SKatayama Hirofumi MZ             strSize.Format(L"%ld x %ld", xRel, yRel);
1268fa4b38d9SKatayama Hirofumi MZ             ::SendMessageW(g_hStatusBar, SB_SETTEXT, 2, (LPARAM)(LPCWSTR)strSize);
1269fa4b38d9SKatayama Hirofumi MZ         }
1270fa4b38d9SKatayama Hirofumi MZ     }
1271fa4b38d9SKatayama Hirofumi MZ }
1272