OSDN Git Service

Change Dir Structure to be same as TortoiseSVN'
[tortoisegit/TortoiseGitJp.git] / src / Utils / MiscUI / FilterEdit.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2007 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #include "stdafx.h"\r
20 #include "FilterEdit.h"\r
21 \r
22 IMPLEMENT_DYNAMIC(CFilterEdit, CEdit)\r
23 \r
24 CFilterEdit::CFilterEdit() : m_hIconCancelNormal(NULL)\r
25         , m_hIconCancelPressed(NULL)\r
26         , m_hIconInfo(NULL)\r
27         , m_bPressed(FALSE)\r
28         , m_bShowCancelButtonAlways(FALSE)\r
29         , m_iButtonClickedMessageId(WM_FILTEREDIT_INFOCLICKED)\r
30         , m_iCancelClickedMessageId(WM_FILTEREDIT_CANCELCLICKED)\r
31         , m_pValidator(NULL)\r
32         , m_backColor(GetSysColor(COLOR_WINDOW))\r
33         , m_brBack(NULL)\r
34         , m_pCueBanner(NULL)\r
35 {\r
36         m_rcEditArea.SetRect(0, 0, 0, 0);\r
37         m_rcButtonArea.SetRect(0, 0, 0, 0);\r
38         m_rcInfoArea.SetRect(0, 0, 0, 0);\r
39         m_sizeInfoIcon.SetSize(0, 0);\r
40         m_sizeCancelIcon.SetSize(0, 0);\r
41 }\r
42 \r
43 CFilterEdit::~CFilterEdit()\r
44 {\r
45         if (m_hIconCancelNormal)\r
46                 DestroyIcon(m_hIconCancelNormal);\r
47         if (m_hIconCancelPressed)\r
48                 DestroyIcon(m_hIconCancelPressed);\r
49         if (m_hIconInfo)\r
50                 DestroyIcon(m_hIconInfo);\r
51         if (m_brBack)\r
52                 DeleteObject(m_brBack);\r
53         if (m_pCueBanner)\r
54                 delete [] m_pCueBanner;\r
55 }\r
56 \r
57 BEGIN_MESSAGE_MAP(CFilterEdit, CEdit)\r
58 \r
59         ON_MESSAGE(WM_SETFONT, OnSetFont)\r
60         ON_WM_SIZE()\r
61         ON_WM_ERASEBKGND()\r
62         ON_WM_KEYDOWN()\r
63         ON_WM_LBUTTONDOWN()\r
64         ON_WM_LBUTTONUP()\r
65         ON_WM_CREATE()\r
66         ON_WM_SETCURSOR()\r
67         ON_CONTROL_REFLECT_EX(EN_CHANGE, &CFilterEdit::OnEnChange)\r
68         ON_WM_CTLCOLOR_REFLECT()\r
69         ON_WM_PAINT()\r
70         ON_CONTROL_REFLECT(EN_KILLFOCUS, &CFilterEdit::OnEnKillfocus)\r
71         ON_CONTROL_REFLECT(EN_SETFOCUS, &CFilterEdit::OnEnSetfocus)\r
72 END_MESSAGE_MAP()\r
73 \r
74 \r
75 \r
76 // CFilterEdit message handlers\r
77 \r
78 void CFilterEdit::PreSubclassWindow( )\r
79 {       \r
80         // We must have a multi line edit\r
81         // to be able to set the edit rect\r
82         ASSERT( GetStyle() & ES_MULTILINE );\r
83 \r
84         ResizeWindow();\r
85 }\r
86 \r
87 BOOL CFilterEdit::PreTranslateMessage( MSG* pMsg )\r
88 {\r
89         return CEdit::PreTranslateMessage(pMsg);\r
90 }\r
91 \r
92 BOOL CFilterEdit::SetCancelBitmaps(UINT uCancelNormal, UINT uCancelPressed, BOOL bShowAlways)\r
93 {\r
94         m_bShowCancelButtonAlways = bShowAlways;\r
95 \r
96         if (m_hIconCancelNormal)\r
97                 DestroyIcon(m_hIconCancelNormal);\r
98         if (m_hIconCancelPressed)\r
99                 DestroyIcon(m_hIconCancelPressed);\r
100 \r
101         m_hIconCancelNormal = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(uCancelNormal), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);\r
102         m_hIconCancelPressed = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(uCancelPressed), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);\r
103 \r
104         if ((m_hIconCancelNormal == 0) || (m_hIconCancelPressed == 0))\r
105                 return FALSE;\r
106 \r
107         m_sizeCancelIcon = GetIconSize(m_hIconCancelNormal);\r
108 \r
109         ResizeWindow();\r
110         return TRUE;\r
111 }\r
112 \r
113 BOOL CFilterEdit::SetInfoIcon(UINT uInfo)\r
114 {\r
115         if (m_hIconInfo)\r
116                 DestroyIcon(m_hIconInfo);\r
117 \r
118         m_hIconInfo = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(uInfo), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);\r
119 \r
120         if (m_hIconInfo == 0)\r
121                 return FALSE;\r
122 \r
123         m_sizeInfoIcon = GetIconSize(m_hIconInfo);\r
124 \r
125         ResizeWindow();\r
126         return TRUE;\r
127 }\r
128 \r
129 BOOL CFilterEdit::SetCueBanner(LPCWSTR lpcwText)\r
130 {\r
131         if (lpcwText)\r
132         {\r
133                 if (m_pCueBanner)\r
134                         delete [] m_pCueBanner;\r
135                 size_t len = _tcslen(lpcwText);\r
136                 m_pCueBanner = new TCHAR[len+1];\r
137                 _tcscpy_s(m_pCueBanner, len+1, lpcwText);\r
138                 InvalidateRect(NULL, TRUE);\r
139                 return TRUE;\r
140         }\r
141         return FALSE;\r
142 }\r
143 \r
144 void CFilterEdit::ResizeWindow()\r
145 {\r
146         if (!::IsWindow(m_hWnd)) \r
147                 return;\r
148 \r
149         RECT editrc, rc;\r
150         GetRect(&editrc);\r
151         GetClientRect(&rc);\r
152         editrc.left = rc.left + 4;\r
153         editrc.top = rc.top + 1;\r
154         editrc.right = rc.right - 4;\r
155         editrc.bottom = rc.bottom - 4;\r
156 \r
157         m_rcEditArea.left = editrc.left + m_sizeInfoIcon.cx;\r
158         m_rcEditArea.right = editrc.right - m_sizeCancelIcon.cx - 5;\r
159         m_rcEditArea.top = editrc.top;\r
160         m_rcEditArea.bottom = editrc.bottom;\r
161 \r
162         m_rcButtonArea.left = m_rcEditArea.right + 5;\r
163         m_rcButtonArea.right = rc.right;\r
164         m_rcButtonArea.top = (((rc.bottom)-m_sizeCancelIcon.cy)/2);\r
165         m_rcButtonArea.bottom = m_rcButtonArea.top + m_sizeCancelIcon.cy;\r
166 \r
167         m_rcInfoArea.left = 0;\r
168         m_rcInfoArea.right = m_rcEditArea.left;\r
169         m_rcInfoArea.top = (((rc.bottom)-m_sizeInfoIcon.cy)/2);\r
170         m_rcInfoArea.bottom = m_rcInfoArea.top + m_sizeInfoIcon.cy;\r
171 \r
172         SetRect(&m_rcEditArea);\r
173 }\r
174 \r
175 void CFilterEdit::SetButtonClickedMessageId(UINT iButtonClickedMessageId, UINT iCancelClickedMessageId)\r
176 {\r
177         m_iButtonClickedMessageId = iButtonClickedMessageId;\r
178         m_iCancelClickedMessageId = iCancelClickedMessageId;\r
179 }\r
180 \r
181 CSize CFilterEdit::GetIconSize(HICON hIcon)\r
182 {\r
183         CSize size(0, 0);\r
184         ICONINFO iconinfo;\r
185         if (GetIconInfo(hIcon, &iconinfo))\r
186         {\r
187                 BITMAP bmp;\r
188                 if (GetObject(iconinfo.hbmColor, sizeof(BITMAP), &bmp))\r
189                 {\r
190                         size.cx = bmp.bmWidth;\r
191                         size.cy = bmp.bmHeight;\r
192                 }\r
193         }\r
194         return size;\r
195 }\r
196 \r
197 BOOL CFilterEdit::OnEraseBkgnd(CDC* pDC)\r
198 {\r
199         RECT rc;\r
200         GetClientRect(&rc);\r
201         pDC->FillSolidRect(&rc, m_backColor);\r
202 \r
203         if (GetWindowTextLength() || m_bShowCancelButtonAlways)\r
204         {\r
205                 if (!m_bPressed)\r
206                 {\r
207                         DrawIconEx(pDC->GetSafeHdc(), m_rcButtonArea.left, m_rcButtonArea.top, m_hIconCancelNormal, \r
208                                 m_sizeCancelIcon.cx, m_sizeCancelIcon.cy, 0, NULL, DI_NORMAL);\r
209                 }\r
210                 else\r
211                 {\r
212                         DrawIconEx(pDC->GetSafeHdc(), m_rcButtonArea.left, m_rcButtonArea.top, m_hIconCancelPressed, \r
213                                 m_sizeCancelIcon.cx, m_sizeCancelIcon.cy, 0, NULL, DI_NORMAL);\r
214                 }\r
215         }\r
216         if (m_hIconInfo)\r
217         {\r
218                 DrawIconEx(pDC->GetSafeHdc(), m_rcInfoArea.left, m_rcInfoArea.top, m_hIconInfo, \r
219                         m_sizeInfoIcon.cx, m_sizeInfoIcon.cy, 0, NULL, DI_NORMAL);\r
220         }\r
221 \r
222         return TRUE;\r
223 }\r
224 \r
225 void CFilterEdit::OnLButtonUp(UINT nFlags, CPoint point)\r
226 {\r
227         m_bPressed = FALSE;\r
228         InvalidateRect(NULL);\r
229         if (m_rcButtonArea.PtInRect(point))\r
230         {\r
231                 SetWindowText(_T(""));\r
232                 CWnd *pOwner = GetOwner();\r
233                 if (pOwner)\r
234                 {\r
235                         pOwner->SendMessage(m_iCancelClickedMessageId, 0, 0);\r
236                 }\r
237                 Validate();\r
238         }\r
239         if (m_rcInfoArea.PtInRect(point))\r
240         {\r
241                 CWnd *pOwner = GetOwner();\r
242                 if (pOwner)\r
243                 {\r
244                         RECT rc = m_rcInfoArea;\r
245                         ClientToScreen(&rc);\r
246                         pOwner->SendMessage(m_iButtonClickedMessageId, 0, (LPARAM)(LPRECT)&rc);\r
247                 }\r
248         }\r
249 \r
250         CEdit::OnLButtonUp(nFlags, point);\r
251 }\r
252 \r
253 void CFilterEdit::OnLButtonDown(UINT nFlags, CPoint point)\r
254 {\r
255         m_bPressed = m_rcButtonArea.PtInRect(point);\r
256         //InvalidateRect(NULL);\r
257         CEdit::OnLButtonDown(nFlags, point);\r
258 }\r
259 \r
260 int CFilterEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)\r
261 {\r
262         if (CEdit::OnCreate(lpCreateStruct) == -1)\r
263                 return -1;\r
264 \r
265         ResizeWindow();\r
266 \r
267         return 0;\r
268 }\r
269 \r
270 LRESULT CFilterEdit::OnSetFont( WPARAM wParam, LPARAM lParam )\r
271 {\r
272         DefWindowProc( WM_SETFONT, wParam, lParam );\r
273 \r
274         ResizeWindow();\r
275 \r
276         return 0;\r
277 }\r
278 \r
279 void CFilterEdit::OnSize( UINT nType, int cx, int cy ) \r
280 {\r
281         CEdit::OnSize( nType, cx, cy );\r
282         ResizeWindow();\r
283 }\r
284 \r
285 BOOL CFilterEdit::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)\r
286 {\r
287         CPoint pntCursor;\r
288         GetCursorPos(&pntCursor);\r
289         ScreenToClient(&pntCursor);\r
290         // if the cursor is not in the edit area, show the normal arrow cursor\r
291         if (!m_rcEditArea.PtInRect(pntCursor))\r
292         {\r
293                 SetCursor(AfxGetApp()->LoadStandardCursor(MAKEINTRESOURCE(IDC_ARROW)));\r
294                 return TRUE;\r
295         }\r
296 \r
297         return CEdit::OnSetCursor(pWnd, nHitTest, message);\r
298 }\r
299 \r
300 BOOL CFilterEdit::OnEnChange()\r
301 {\r
302         // check whether the entered text is valid\r
303         Validate();\r
304         InvalidateRect(NULL);\r
305         return FALSE;\r
306 }\r
307 \r
308 HBRUSH CFilterEdit::CtlColor(CDC* pDC, UINT /*nCtlColor*/)\r
309 {\r
310         if (m_backColor != GetSysColor(COLOR_WINDOW))\r
311         {\r
312                 pDC->SetBkColor(m_backColor);\r
313                 return m_brBack;\r
314         }\r
315         return NULL;\r
316 }\r
317 \r
318 void CFilterEdit::Validate()\r
319 {\r
320         if (m_pValidator)\r
321         {\r
322                 int len = GetWindowTextLength();\r
323                 TCHAR * pBuf = new TCHAR[len+1];\r
324                 GetWindowText(pBuf, len+1);\r
325                 m_backColor = GetSysColor(COLOR_WINDOW);\r
326                 if (!m_pValidator->Validate(pBuf))\r
327                 {\r
328                         // Use a background color slightly shifted to red.\r
329                         // We do this by increasing red component and decreasing green and blue.\r
330                         const int SHIFT_PRECENTAGE = 10;\r
331                         int r = GetRValue(m_backColor);\r
332                         int g = GetGValue(m_backColor);\r
333                         int b = GetBValue(m_backColor);\r
334 \r
335                         r = min(r * (100 + SHIFT_PRECENTAGE) / 100, 255);\r
336                         // Ensure that there is at least some redness.\r
337                         r = max(r, 255 * SHIFT_PRECENTAGE / 100);\r
338                         g = g * (100 - SHIFT_PRECENTAGE) / 100;\r
339                         b = b * (100 - SHIFT_PRECENTAGE) / 100;\r
340                         m_backColor = RGB(r, g, b);\r
341                         if (m_brBack)\r
342                                 DeleteObject(m_brBack);\r
343                         m_brBack = CreateSolidBrush(m_backColor);\r
344                 }\r
345                 delete [] pBuf;\r
346         }\r
347 }\r
348 \r
349 void CFilterEdit::OnPaint()\r
350 {\r
351         Default();\r
352 \r
353         DrawDimText();\r
354 \r
355         return;\r
356 }\r
357 \r
358 void CFilterEdit::DrawDimText()\r
359 {\r
360         if (m_pCueBanner == NULL)\r
361                 return;\r
362         if (GetWindowTextLength())\r
363                 return;\r
364         if (_tcslen(m_pCueBanner) == 0)\r
365                 return;\r
366         if (GetFocus() == this)\r
367                 return;\r
368 \r
369         CClientDC       dcDraw(this);\r
370         CRect           rRect;\r
371         int                     iState = dcDraw.SaveDC();\r
372 \r
373         GetClientRect(&rRect);\r
374         rRect.OffsetRect(1, 1);\r
375 \r
376         dcDraw.SelectObject((*GetFont()));\r
377         dcDraw.SetTextColor(GetSysColor(COLOR_GRAYTEXT));\r
378         dcDraw.SetBkColor(GetSysColor(COLOR_WINDOW));\r
379         dcDraw.DrawText(m_pCueBanner, (int)_tcslen(m_pCueBanner), &rRect, DT_CENTER | DT_VCENTER);\r
380         dcDraw.RestoreDC(iState);\r
381         return;\r
382 }\r
383 \r
384 void CFilterEdit::OnEnKillfocus()\r
385 {\r
386         InvalidateRect(NULL);\r
387 }\r
388 \r
389 void CFilterEdit::OnEnSetfocus()\r
390 {\r
391         InvalidateRect(NULL);\r
392 }\r