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.
20 #include "FilterEdit.h"
22 IMPLEMENT_DYNAMIC(CFilterEdit
, CEdit
)
24 CFilterEdit::CFilterEdit() : m_hIconCancelNormal(NULL
)
25 , m_hIconCancelPressed(NULL
)
28 , m_bShowCancelButtonAlways(FALSE
)
29 , m_iButtonClickedMessageId(WM_FILTEREDIT_INFOCLICKED
)
30 , m_iCancelClickedMessageId(WM_FILTEREDIT_CANCELCLICKED
)
32 , m_backColor(GetSysColor(COLOR_WINDOW
))
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
);
50 DestroyIcon(m_hIconInfo
);
52 DeleteObject(m_brBack
);
54 delete [] m_pCueBanner
;
57 BEGIN_MESSAGE_MAP(CFilterEdit
, CEdit
)
59 ON_MESSAGE(WM_SETFONT
, OnSetFont
)
67 ON_CONTROL_REFLECT_EX(EN_CHANGE
, &CFilterEdit::OnEnChange
)
68 ON_WM_CTLCOLOR_REFLECT()
70 ON_CONTROL_REFLECT(EN_KILLFOCUS
, &CFilterEdit::OnEnKillfocus
)
71 ON_CONTROL_REFLECT(EN_SETFOCUS
, &CFilterEdit::OnEnSetfocus
)
72 ON_MESSAGE(WM_PASTE
, &CFilterEdit::OnPaste
)
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
);
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))
108 m_sizeCancelIcon
= GetIconSize(m_hIconCancelNormal
);
114 BOOL
CFilterEdit::SetInfoIcon(UINT uInfo
)
117 DestroyIcon(m_hIconInfo
);
119 m_hIconInfo
= (HICON
)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(uInfo
), IMAGE_ICON
, 0, 0, LR_DEFAULTCOLOR
);
121 if (m_hIconInfo
== 0)
124 m_sizeInfoIcon
= GetIconSize(m_hIconInfo
);
130 BOOL
CFilterEdit::SetCueBanner(LPCWSTR lpcwText
)
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
);
145 void CFilterEdit::ResizeWindow()
147 if (!::IsWindow(m_hWnd
))
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
)
186 if (GetIconInfo(hIcon
, &iconinfo
))
189 if (GetObject(iconinfo
.hbmColor
, sizeof(BITMAP
), &bmp
))
191 size
.cx
= bmp
.bmWidth
;
192 size
.cy
= bmp
.bmHeight
;
198 BOOL
CFilterEdit::OnEraseBkgnd(CDC
* pDC
)
202 pDC
->FillSolidRect(&rc
, m_backColor
);
204 if (GetWindowTextLength() || m_bShowCancelButtonAlways
)
208 DrawIconEx(pDC
->GetSafeHdc(), m_rcButtonArea
.left
, m_rcButtonArea
.top
, m_hIconCancelNormal
,
209 m_sizeCancelIcon
.cx
, m_sizeCancelIcon
.cy
, 0, NULL
, DI_NORMAL
);
213 DrawIconEx(pDC
->GetSafeHdc(), m_rcButtonArea
.left
, m_rcButtonArea
.top
, m_hIconCancelPressed
,
214 m_sizeCancelIcon
.cx
, m_sizeCancelIcon
.cy
, 0, NULL
, DI_NORMAL
);
219 DrawIconEx(pDC
->GetSafeHdc(), m_rcInfoArea
.left
, m_rcInfoArea
.top
, m_hIconInfo
,
220 m_sizeInfoIcon
.cx
, m_sizeInfoIcon
.cy
, 0, NULL
, DI_NORMAL
);
226 void CFilterEdit::OnLButtonUp(UINT nFlags
, CPoint point
)
229 InvalidateRect(NULL
);
230 if (m_rcButtonArea
.PtInRect(point
))
232 SetWindowText(_T(""));
233 CWnd
*pOwner
= GetOwner();
236 pOwner
->SendMessage(m_iCancelClickedMessageId
, 0, 0);
240 if (m_rcInfoArea
.PtInRect(point
))
242 CWnd
*pOwner
= GetOwner();
245 RECT rc
= m_rcInfoArea
;
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)
271 LRESULT
CFilterEdit::OnSetFont( WPARAM wParam
, LPARAM lParam
)
273 DefWindowProc( WM_SETFONT
, wParam
, lParam
);
280 void CFilterEdit::OnSize( UINT nType
, int cx
, int cy
)
282 CEdit::OnSize( nType
, cx
, cy
);
286 BOOL
CFilterEdit::OnSetCursor(CWnd
* pWnd
, UINT nHitTest
, UINT message
)
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
)));
298 return CEdit::OnSetCursor(pWnd
, nHitTest
, message
);
301 BOOL
CFilterEdit::OnEnChange()
303 // check whether the entered text is valid
305 InvalidateRect(NULL
);
309 HBRUSH
CFilterEdit::CtlColor(CDC
* pDC
, UINT
/*nCtlColor*/)
311 if (m_backColor
!= GetSysColor(COLOR_WINDOW
))
313 pDC
->SetBkColor(m_backColor
);
319 void CFilterEdit::Validate()
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
);
343 DeleteObject(m_brBack
);
344 m_brBack
= CreateSolidBrush(m_backColor
);
350 void CFilterEdit::OnPaint()
359 void CFilterEdit::DrawDimText()
361 if (m_pCueBanner
== NULL
)
363 if (GetWindowTextLength())
365 if (_tcslen(m_pCueBanner
) == 0)
367 if (GetFocus() == this)
370 CClientDC
dcDraw(this);
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
);
385 void CFilterEdit::OnEnKillfocus()
387 InvalidateRect(NULL
);
390 void CFilterEdit::OnEnSetfocus()
392 InvalidateRect(NULL
);
395 LRESULT
CFilterEdit::OnPaste(WPARAM
, LPARAM
)
399 HANDLE hData
= GetClipboardData (CF_TEXT
);
400 CString
toInsert((const char*)GlobalLock(hData
));
404 // elimate control chars, especially newlines
405 toInsert
.Replace(_T('\t'), _T(' '));
407 // only insert first line
408 toInsert
.Replace(_T('\r'), _T('\n'));
410 toInsert
= toInsert
.Tokenize(_T("\n"), pos
);
413 // get the current text
417 // construct the new text
420 text
.Delete(from
, to
- from
);
421 text
.Insert(from
, toInsert
);
422 from
+= toInsert
.GetLength();
424 // update & notify controls
426 SetSel(from
, from
, FALSE
);
429 GetParent()->SendMessage(WM_COMMAND
, MAKEWPARAM(GetDlgCtrlID(), EN_CHANGE
), (LPARAM
)GetSafeHwnd());