DeleteRemoteTagDlg: Allow to delete multiple tags at once
[TortoiseGit.git] / src / Utils / MiscUI / FilterEdit.cpp
blob4bccf353904ac4fda3e6a3ec3d8bd7e1f1f08e0e
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2007 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "stdafx.h"
20 #include "FilterEdit.h"
22 IMPLEMENT_DYNAMIC(CFilterEdit, CEdit)
24 CFilterEdit::CFilterEdit() : m_hIconCancelNormal(NULL)
25 , m_hIconCancelPressed(NULL)
26 , m_hIconInfo(NULL)
27 , m_bPressed(FALSE)
28 , m_bShowCancelButtonAlways(FALSE)
29 , m_iButtonClickedMessageId(WM_FILTEREDIT_INFOCLICKED)
30 , m_iCancelClickedMessageId(WM_FILTEREDIT_CANCELCLICKED)
31 , m_pValidator(NULL)
32 , m_backColor(GetSysColor(COLOR_WINDOW))
33 , m_brBack(NULL)
34 , m_pCueBanner(NULL)
36 m_rcEditArea.SetRect(0, 0, 0, 0);
37 m_rcButtonArea.SetRect(0, 0, 0, 0);
38 m_rcInfoArea.SetRect(0, 0, 0, 0);
39 m_sizeInfoIcon.SetSize(0, 0);
40 m_sizeCancelIcon.SetSize(0, 0);
43 CFilterEdit::~CFilterEdit()
45 if (m_hIconCancelNormal)
46 DestroyIcon(m_hIconCancelNormal);
47 if (m_hIconCancelPressed)
48 DestroyIcon(m_hIconCancelPressed);
49 if (m_hIconInfo)
50 DestroyIcon(m_hIconInfo);
51 if (m_brBack)
52 DeleteObject(m_brBack);
53 if (m_pCueBanner)
54 delete [] m_pCueBanner;
57 BEGIN_MESSAGE_MAP(CFilterEdit, CEdit)
59 ON_MESSAGE(WM_SETFONT, OnSetFont)
60 ON_WM_SIZE()
61 ON_WM_ERASEBKGND()
62 ON_WM_KEYDOWN()
63 ON_WM_LBUTTONDOWN()
64 ON_WM_LBUTTONUP()
65 ON_WM_CREATE()
66 ON_WM_SETCURSOR()
67 ON_CONTROL_REFLECT_EX(EN_CHANGE, &CFilterEdit::OnEnChange)
68 ON_WM_CTLCOLOR_REFLECT()
69 ON_WM_PAINT()
70 ON_CONTROL_REFLECT(EN_KILLFOCUS, &CFilterEdit::OnEnKillfocus)
71 ON_CONTROL_REFLECT(EN_SETFOCUS, &CFilterEdit::OnEnSetfocus)
72 ON_MESSAGE(WM_PASTE, &CFilterEdit::OnPaste)
73 END_MESSAGE_MAP()
77 // CFilterEdit message handlers
79 void CFilterEdit::PreSubclassWindow( )
81 // We must have a multi line edit
82 // to be able to set the edit rect
83 ASSERT( GetStyle() & ES_MULTILINE );
85 ResizeWindow();
88 BOOL CFilterEdit::PreTranslateMessage( MSG* pMsg )
90 return CEdit::PreTranslateMessage(pMsg);
93 BOOL CFilterEdit::SetCancelBitmaps(UINT uCancelNormal, UINT uCancelPressed, BOOL bShowAlways)
95 m_bShowCancelButtonAlways = bShowAlways;
97 if (m_hIconCancelNormal)
98 DestroyIcon(m_hIconCancelNormal);
99 if (m_hIconCancelPressed)
100 DestroyIcon(m_hIconCancelPressed);
102 m_hIconCancelNormal = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(uCancelNormal), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
103 m_hIconCancelPressed = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(uCancelPressed), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
105 if ((m_hIconCancelNormal == 0) || (m_hIconCancelPressed == 0))
106 return FALSE;
108 m_sizeCancelIcon = GetIconSize(m_hIconCancelNormal);
110 ResizeWindow();
111 return TRUE;
114 BOOL CFilterEdit::SetInfoIcon(UINT uInfo)
116 if (m_hIconInfo)
117 DestroyIcon(m_hIconInfo);
119 m_hIconInfo = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(uInfo), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
121 if (m_hIconInfo == 0)
122 return FALSE;
124 m_sizeInfoIcon = GetIconSize(m_hIconInfo);
126 ResizeWindow();
127 return TRUE;
130 BOOL CFilterEdit::SetCueBanner(LPCWSTR lpcwText)
132 if (lpcwText)
134 if (m_pCueBanner)
135 delete [] m_pCueBanner;
136 size_t len = _tcslen(lpcwText);
137 m_pCueBanner = new TCHAR[len+1];
138 _tcscpy_s(m_pCueBanner, len+1, lpcwText);
139 InvalidateRect(NULL, TRUE);
140 return TRUE;
142 return FALSE;
145 void CFilterEdit::ResizeWindow()
147 if (!::IsWindow(m_hWnd))
148 return;
150 RECT editrc, rc;
151 GetRect(&editrc);
152 GetClientRect(&rc);
153 editrc.left = rc.left + 4;
154 editrc.top = rc.top + 1;
155 editrc.right = rc.right - 4;
156 editrc.bottom = rc.bottom - 4;
158 m_rcEditArea.left = editrc.left + m_sizeInfoIcon.cx;
159 m_rcEditArea.right = editrc.right - m_sizeCancelIcon.cx - 5;
160 m_rcEditArea.top = editrc.top;
161 m_rcEditArea.bottom = editrc.bottom;
163 m_rcButtonArea.left = m_rcEditArea.right + 5;
164 m_rcButtonArea.right = rc.right;
165 m_rcButtonArea.top = (((rc.bottom)-m_sizeCancelIcon.cy)/2);
166 m_rcButtonArea.bottom = m_rcButtonArea.top + m_sizeCancelIcon.cy;
168 m_rcInfoArea.left = 0;
169 m_rcInfoArea.right = m_rcEditArea.left;
170 m_rcInfoArea.top = (((rc.bottom)-m_sizeInfoIcon.cy)/2);
171 m_rcInfoArea.bottom = m_rcInfoArea.top + m_sizeInfoIcon.cy;
173 SetRect(&m_rcEditArea);
176 void CFilterEdit::SetButtonClickedMessageId(UINT iButtonClickedMessageId, UINT iCancelClickedMessageId)
178 m_iButtonClickedMessageId = iButtonClickedMessageId;
179 m_iCancelClickedMessageId = iCancelClickedMessageId;
182 CSize CFilterEdit::GetIconSize(HICON hIcon)
184 CSize size(0, 0);
185 ICONINFO iconinfo;
186 if (GetIconInfo(hIcon, &iconinfo))
188 BITMAP bmp;
189 if (GetObject(iconinfo.hbmColor, sizeof(BITMAP), &bmp))
191 size.cx = bmp.bmWidth;
192 size.cy = bmp.bmHeight;
195 return size;
198 BOOL CFilterEdit::OnEraseBkgnd(CDC* pDC)
200 RECT rc;
201 GetClientRect(&rc);
202 pDC->FillSolidRect(&rc, m_backColor);
204 if (GetWindowTextLength() || m_bShowCancelButtonAlways)
206 if (!m_bPressed)
208 DrawIconEx(pDC->GetSafeHdc(), m_rcButtonArea.left, m_rcButtonArea.top, m_hIconCancelNormal,
209 m_sizeCancelIcon.cx, m_sizeCancelIcon.cy, 0, NULL, DI_NORMAL);
211 else
213 DrawIconEx(pDC->GetSafeHdc(), m_rcButtonArea.left, m_rcButtonArea.top, m_hIconCancelPressed,
214 m_sizeCancelIcon.cx, m_sizeCancelIcon.cy, 0, NULL, DI_NORMAL);
217 if (m_hIconInfo)
219 DrawIconEx(pDC->GetSafeHdc(), m_rcInfoArea.left, m_rcInfoArea.top, m_hIconInfo,
220 m_sizeInfoIcon.cx, m_sizeInfoIcon.cy, 0, NULL, DI_NORMAL);
223 return TRUE;
226 void CFilterEdit::OnLButtonUp(UINT nFlags, CPoint point)
228 m_bPressed = FALSE;
229 InvalidateRect(NULL);
230 if (m_rcButtonArea.PtInRect(point))
232 SetWindowText(_T(""));
233 CWnd *pOwner = GetOwner();
234 if (pOwner)
236 pOwner->SendMessage(m_iCancelClickedMessageId, 0, 0);
238 Validate();
240 if (m_rcInfoArea.PtInRect(point))
242 CWnd *pOwner = GetOwner();
243 if (pOwner)
245 RECT rc = m_rcInfoArea;
246 ClientToScreen(&rc);
247 pOwner->SendMessage(m_iButtonClickedMessageId, 0, (LPARAM)(LPRECT)&rc);
251 CEdit::OnLButtonUp(nFlags, point);
254 void CFilterEdit::OnLButtonDown(UINT nFlags, CPoint point)
256 m_bPressed = m_rcButtonArea.PtInRect(point);
257 //InvalidateRect(NULL);
258 CEdit::OnLButtonDown(nFlags, point);
261 int CFilterEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
263 if (CEdit::OnCreate(lpCreateStruct) == -1)
264 return -1;
266 ResizeWindow();
268 return 0;
271 LRESULT CFilterEdit::OnSetFont( WPARAM wParam, LPARAM lParam )
273 DefWindowProc( WM_SETFONT, wParam, lParam );
275 ResizeWindow();
277 return 0;
280 void CFilterEdit::OnSize( UINT nType, int cx, int cy )
282 CEdit::OnSize( nType, cx, cy );
283 ResizeWindow();
286 BOOL CFilterEdit::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
288 CPoint pntCursor;
289 GetCursorPos(&pntCursor);
290 ScreenToClient(&pntCursor);
291 // if the cursor is not in the edit area, show the normal arrow cursor
292 if (!m_rcEditArea.PtInRect(pntCursor))
294 SetCursor(AfxGetApp()->LoadStandardCursor(MAKEINTRESOURCE(IDC_ARROW)));
295 return TRUE;
298 return CEdit::OnSetCursor(pWnd, nHitTest, message);
301 BOOL CFilterEdit::OnEnChange()
303 // check whether the entered text is valid
304 Validate();
305 InvalidateRect(NULL);
306 return FALSE;
309 HBRUSH CFilterEdit::CtlColor(CDC* pDC, UINT /*nCtlColor*/)
311 if (m_backColor != GetSysColor(COLOR_WINDOW))
313 pDC->SetBkColor(m_backColor);
314 return m_brBack;
316 return NULL;
319 void CFilterEdit::Validate()
321 if (m_pValidator)
323 int len = GetWindowTextLength();
324 TCHAR * pBuf = new TCHAR[len+1];
325 GetWindowText(pBuf, len+1);
326 m_backColor = GetSysColor(COLOR_WINDOW);
327 if (!m_pValidator->Validate(pBuf))
329 // Use a background color slightly shifted to red.
330 // We do this by increasing red component and decreasing green and blue.
331 const int SHIFT_PRECENTAGE = 10;
332 int r = GetRValue(m_backColor);
333 int g = GetGValue(m_backColor);
334 int b = GetBValue(m_backColor);
336 r = min(r * (100 + SHIFT_PRECENTAGE) / 100, 255);
337 // Ensure that there is at least some redness.
338 r = max(r, 255 * SHIFT_PRECENTAGE / 100);
339 g = g * (100 - SHIFT_PRECENTAGE) / 100;
340 b = b * (100 - SHIFT_PRECENTAGE) / 100;
341 m_backColor = RGB(r, g, b);
342 if (m_brBack)
343 DeleteObject(m_brBack);
344 m_brBack = CreateSolidBrush(m_backColor);
346 delete [] pBuf;
350 void CFilterEdit::OnPaint()
352 Default();
354 DrawDimText();
356 return;
359 void CFilterEdit::DrawDimText()
361 if (m_pCueBanner == NULL)
362 return;
363 if (GetWindowTextLength())
364 return;
365 if (_tcslen(m_pCueBanner) == 0)
366 return;
367 if (GetFocus() == this)
368 return;
370 CClientDC dcDraw(this);
371 CRect rRect;
372 int iState = dcDraw.SaveDC();
374 GetClientRect(&rRect);
375 rRect.OffsetRect(1, 1);
377 dcDraw.SelectObject((*GetFont()));
378 dcDraw.SetTextColor(GetSysColor(COLOR_GRAYTEXT));
379 dcDraw.SetBkColor(GetSysColor(COLOR_WINDOW));
380 dcDraw.DrawText(m_pCueBanner, (int)_tcslen(m_pCueBanner), &rRect, DT_CENTER | DT_VCENTER);
381 dcDraw.RestoreDC(iState);
382 return;
385 void CFilterEdit::OnEnKillfocus()
387 InvalidateRect(NULL);
390 void CFilterEdit::OnEnSetfocus()
392 InvalidateRect(NULL);
395 LRESULT CFilterEdit::OnPaste(WPARAM, LPARAM)
397 if (OpenClipboard())
399 HANDLE hData = GetClipboardData (CF_TEXT);
400 CString toInsert((const char*)GlobalLock(hData));
401 GlobalUnlock(hData);
402 CloseClipboard();
404 // elimate control chars, especially newlines
405 toInsert.Replace(_T('\t'), _T(' '));
407 // only insert first line
408 toInsert.Replace(_T('\r'), _T('\n'));
409 int pos = 0;
410 toInsert = toInsert.Tokenize(_T("\n"), pos);
411 toInsert.Trim();
413 // get the current text
414 CString text;
415 GetWindowText(text);
417 // construct the new text
418 int from, to;
419 GetSel(from, to);
420 text.Delete(from, to - from);
421 text.Insert(from, toInsert);
422 from += toInsert.GetLength();
424 // update & notify controls
425 SetWindowText(text);
426 SetSel(from, from, FALSE);
427 SetModify(TRUE);
429 GetParent()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), EN_CHANGE), (LPARAM)GetSafeHwnd());
431 return 0;