Get rid of magic numbers
[TortoiseGit.git] / src / TortoiseMerge / LocatorBar.cpp
blob716e83ce8c7b56454bcd6182c821b70c7b6c62db
1 // TortoiseGitMerge - a Diff/Patch program
3 // Copyright (C) 2006-2012, 2015 - 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 "TortoiseMerge.h"
21 #include "MainFrm.h"
22 #include "LocatorBar.h"
23 #include "LeftView.h"
24 #include "RightView.h"
25 #include "BottomView.h"
26 #include "DiffColors.h"
27 #include "AppUtils.h"
30 IMPLEMENT_DYNAMIC(CLocatorBar, CPaneDialog)
31 CLocatorBar::CLocatorBar() : CPaneDialog()
32 , m_pMainFrm(nullptr)
33 , m_pCacheBitmap(nullptr)
34 , m_regUseFishEye(L"Software\\TortoiseGitMerge\\UseFishEye", TRUE)
35 , m_nLines(-1)
36 , m_minWidth(0)
40 CLocatorBar::~CLocatorBar()
42 if (m_pCacheBitmap)
44 m_pCacheBitmap->DeleteObject();
45 delete m_pCacheBitmap;
46 m_pCacheBitmap = nullptr;
50 BEGIN_MESSAGE_MAP(CLocatorBar, CPaneDialog)
51 ON_WM_PAINT()
52 ON_WM_SIZE()
53 ON_WM_ERASEBKGND()
54 ON_WM_LBUTTONDOWN()
55 ON_WM_MOUSEMOVE()
56 ON_WM_LBUTTONUP()
57 ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
58 END_MESSAGE_MAP()
60 void CLocatorBar::DocumentUpdated()
62 m_pMainFrm = (CMainFrame *)this->GetParentFrame();
63 if (!m_pMainFrm)
64 return;
66 m_nLines = 0;
67 DocumentUpdated(m_pMainFrm->m_pwndLeftView, m_arLeftIdent, m_arLeftState);
68 DocumentUpdated(m_pMainFrm->m_pwndRightView, m_arRightIdent, m_arRightState);
69 DocumentUpdated(m_pMainFrm->m_pwndBottomView, m_arBottomIdent, m_arBottomState);
71 if (m_pMainFrm->m_pwndLeftView)
73 m_nLines = m_pMainFrm->m_pwndLeftView->GetLineCount();
74 if (m_pMainFrm->m_pwndRightView)
76 m_nLines = std::max<int>(m_nLines, m_pMainFrm->m_pwndRightView->GetLineCount());
77 if (m_pMainFrm->m_pwndBottomView)
79 m_nLines = std::max<int>(m_nLines, m_pMainFrm->m_pwndBottomView->GetLineCount());
83 Invalidate();
86 void CLocatorBar::DocumentUpdated(CBaseView* view, CDWordArray& indents, CDWordArray& states)
88 indents.RemoveAll();
89 states.RemoveAll();
90 CViewData* viewData = view->m_pViewData;
91 if(viewData == 0)
92 return;
94 long identcount = 1;
95 const int linesInView = view->GetLineCount();
96 DiffStates state = DIFFSTATE_UNKNOWN;
97 if (linesInView)
98 state = viewData->GetState(0);
99 for (int i=1; i<linesInView; i++)
101 const DiffStates lineState = viewData->GetState(view->GetViewLineForScreen(i));
102 if (state == lineState)
104 identcount++;
106 else
108 indents.Add(identcount);
109 states.Add(state);
110 state = lineState;
111 identcount = 1;
114 indents.Add(identcount);
115 states.Add(state);
118 CSize CLocatorBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
120 auto s = __super::CalcFixedLayout(bStretch, bHorz);
121 s.cx = m_minWidth;
122 return s;
125 void CLocatorBar::OnPaint()
127 CPaintDC dc(this); // device context for painting
128 CRect rect;
129 GetClientRect(rect);
130 const long height = rect.Height();
131 const long width = rect.Width();
132 long nTopLine = 0;
133 long nBottomLine = 0;
134 if ((m_pMainFrm)&&(m_pMainFrm->m_pwndLeftView))
136 nTopLine = m_pMainFrm->m_pwndLeftView->m_nTopLine;
137 nBottomLine = nTopLine + m_pMainFrm->m_pwndLeftView->GetScreenLines();
139 CDC cacheDC;
140 VERIFY(cacheDC.CreateCompatibleDC(&dc));
142 if (!m_pCacheBitmap)
144 m_pCacheBitmap = new CBitmap;
145 VERIFY(m_pCacheBitmap->CreateCompatibleBitmap(&dc, width, height));
147 CBitmap *pOldBitmap = cacheDC.SelectObject(m_pCacheBitmap);
149 COLORREF color, color2;
150 CDiffColors::GetInstance().GetColors(DIFFSTATE_UNKNOWN, color, color2);
151 cacheDC.FillSolidRect(rect, color);
153 if (m_nLines)
155 cacheDC.FillSolidRect(rect.left, height*nTopLine/m_nLines,
156 width, (height*nBottomLine/m_nLines)-(height*nTopLine/m_nLines), RGB(180,180,255));
158 if (m_pMainFrm)
160 PaintView (cacheDC, m_pMainFrm->m_pwndLeftView, m_arLeftIdent, m_arLeftState, rect, 0);
161 PaintView (cacheDC, m_pMainFrm->m_pwndRightView, m_arRightIdent, m_arRightState, rect, 2);
162 PaintView (cacheDC, m_pMainFrm->m_pwndBottomView, m_arBottomIdent, m_arBottomState, rect, 1);
166 if (m_nLines == 0)
167 m_nLines = 1;
168 cacheDC.FillSolidRect(rect.left, height*nTopLine/m_nLines,
169 width, 2, RGB(0,0,0));
170 cacheDC.FillSolidRect(rect.left, height*nBottomLine/m_nLines,
171 width, 2, RGB(0,0,0));
172 //draw two vertical lines, so there are three rows visible indicating the three panes
173 cacheDC.FillSolidRect(rect.left + (width/3), rect.top, 1, height, RGB(0,0,0));
174 cacheDC.FillSolidRect(rect.left + (width*2/3), rect.top, 1, height, RGB(0,0,0));
176 // draw the fish eye
177 DWORD pos = GetMessagePos();
178 CRect screenRect = rect;
179 ClientToScreen(screenRect);
180 POINT pt;
181 pt.x = GET_X_LPARAM(pos);
182 pt.y = GET_Y_LPARAM(pos);
184 if ((screenRect.PtInRect(pt))&&(DWORD(m_regUseFishEye)))
185 DrawFishEye (cacheDC, rect);
187 VERIFY(dc.BitBlt(rect.left, rect.top, width, height, &cacheDC, 0, 0, SRCCOPY));
189 cacheDC.SelectObject(pOldBitmap);
190 cacheDC.DeleteDC();
193 void CLocatorBar::OnSize(UINT nType, int cx, int cy)
195 CPaneDialog::OnSize(nType, cx, cy);
197 if (m_pCacheBitmap)
199 m_pCacheBitmap->DeleteObject();
200 delete m_pCacheBitmap;
201 m_pCacheBitmap = nullptr;
203 Invalidate();
206 BOOL CLocatorBar::OnEraseBkgnd(CDC* /*pDC*/)
208 return TRUE;
211 void CLocatorBar::OnLButtonDown(UINT nFlags, CPoint point)
213 ScrollOnMouseMove(point);
214 Invalidate();
215 CPaneDialog::OnLButtonDown(nFlags, point);
218 void CLocatorBar::OnMouseMove(UINT nFlags, CPoint point)
220 m_MousePos = point;
222 if (nFlags & MK_LBUTTON)
224 SetCapture();
225 ScrollOnMouseMove(point);
228 TRACKMOUSEEVENT Tme;
229 Tme.cbSize = sizeof(TRACKMOUSEEVENT);
230 Tme.dwFlags = TME_LEAVE;
231 Tme.hwndTrack = m_hWnd;
232 TrackMouseEvent(&Tme);
235 Invalidate();
238 LRESULT CLocatorBar::OnMouseLeave(WPARAM /*wParam*/, LPARAM /*lParam*/)
240 Invalidate();
241 return 0;
244 void CLocatorBar::OnLButtonUp(UINT nFlags, CPoint point)
246 ReleaseCapture();
247 Invalidate();
249 CPaneDialog::OnLButtonUp(nFlags, point);
252 void CLocatorBar::ScrollOnMouseMove(const CPoint& point )
254 if (m_pMainFrm == 0)
255 return;
257 CRect rect;
258 GetClientRect(rect);
260 int nLine = point.y*m_nLines/rect.Height();
261 if (nLine < 0)
262 nLine = 0;
264 ScrollViewToLine(m_pMainFrm->m_pwndBottomView, nLine);
265 ScrollViewToLine(m_pMainFrm->m_pwndLeftView, nLine);
266 ScrollViewToLine(m_pMainFrm->m_pwndRightView, nLine);
269 void CLocatorBar::ScrollViewToLine(CBaseView* view, int nLine) const
271 if (view != 0)
272 view->GoToLine(nLine, FALSE);
275 void CLocatorBar::PaintView(CDC& cacheDC, CBaseView* view, CDWordArray& indents,
276 CDWordArray& states, const CRect& rect, int stripeIndex)
278 if (!view->IsWindowVisible())
279 return;
281 const long height = rect.Height();
282 const long width = rect.Width();
283 const long barwidth = (width/3);
284 long linecount = 0;
285 for (long i=0; i<indents.GetCount(); i++)
287 COLORREF color, color2;
288 const long identcount = indents.GetAt(i);
289 const DWORD state = states.GetAt(i);
290 CDiffColors::GetInstance().GetColors((DiffStates)state, color, color2);
291 if ((DiffStates)state != DIFFSTATE_NORMAL)
293 cacheDC.FillSolidRect(rect.left + (width*stripeIndex/3), height*linecount/m_nLines,
294 barwidth, max(height*identcount/m_nLines,1), color);
296 linecount += identcount;
298 if (view->GetMarkedWord()[0])
300 COLORREF color, color2;
301 CDiffColors::GetInstance().GetColors(DIFFSTATE_NORMAL, color, color2);
302 color = CAppUtils::IntenseColor(200, color);
303 for (size_t i=0; i<view->m_arMarkedWordLines.size(); ++i)
305 if (view->m_arMarkedWordLines[i])
307 cacheDC.FillSolidRect(rect.left + (width*stripeIndex/3), (int)(height*i/m_nLines),
308 barwidth, max(height/m_nLines,2), color);
312 if (view->GetFindString()[0])
314 COLORREF color, color2;
315 CDiffColors::GetInstance().GetColors(DIFFSTATE_NORMAL, color, color2);
316 color = CAppUtils::IntenseColor(30, color);
317 for (size_t i=0; i<view->m_arFindStringLines.size(); ++i)
319 if (view->m_arFindStringLines[i])
321 cacheDC.FillSolidRect(rect.left + (width*stripeIndex/3), (int)(height*i/m_nLines),
322 barwidth, max(height/m_nLines,2), color);
329 void CLocatorBar::DrawFishEye(CDC& cacheDC, const CRect& rect )
331 const long height = rect.Height();
332 const long width = rect.Width();
333 const int fishstart = m_MousePos.y - height/20;
334 const int fishheight = height/10;
335 cacheDC.FillSolidRect(rect.left, fishstart-1, width, 1, RGB(0,0,100));
336 cacheDC.FillSolidRect(rect.left, fishstart+fishheight+1, width, 1, RGB(0,0,100));
337 VERIFY(cacheDC.StretchBlt(rect.left, fishstart, width, fishheight,
338 &cacheDC, 0, fishstart + (3*fishheight/8), width, fishheight/4, SRCCOPY));
339 // draw the magnified area a little darker, so the
340 // user has a clear indication of the magnifier
341 for (int i=rect.left; i<(width - rect.left); i++)
343 for (int j=fishstart; j<fishstart+fishheight; j++)
345 const COLORREF color = cacheDC.GetPixel(i, j);
346 int r = max(GetRValue(color)-20, 0);
347 int g = max(GetGValue(color)-20, 0);
348 int b = max(GetBValue(color)-20, 0);
349 cacheDC.SetPixel(i, j, RGB(r,g,b));