Ask what file to save as, defaults to last view
[TortoiseGit.git] / src / TortoiseMerge / LocatorBar.cpp
blob2d64bd48b02e04357639ee7c5912dafcee516ec6
1 // TortoiseGitMerge - a Diff/Patch program
3 // Copyright (C) 2006-2012 - 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(NULL)
33 , m_pCacheBitmap(NULL)
34 , m_regUseFishEye(_T("Software\\TortoiseGitMerge\\UseFishEye"), TRUE)
35 , m_nLines(-1)
39 CLocatorBar::~CLocatorBar()
41 if (m_pCacheBitmap)
43 m_pCacheBitmap->DeleteObject();
44 delete m_pCacheBitmap;
45 m_pCacheBitmap = NULL;
49 BEGIN_MESSAGE_MAP(CLocatorBar, CPaneDialog)
50 ON_WM_PAINT()
51 ON_WM_SIZE()
52 ON_WM_ERASEBKGND()
53 ON_WM_LBUTTONDOWN()
54 ON_WM_MOUSEMOVE()
55 ON_WM_LBUTTONUP()
56 ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
57 END_MESSAGE_MAP()
59 void CLocatorBar::DocumentUpdated()
61 m_pMainFrm = (CMainFrame *)this->GetParentFrame();
62 if (m_pMainFrm == NULL)
63 return;
65 m_nLines = 0;
66 DocumentUpdated(m_pMainFrm->m_pwndLeftView, m_arLeftIdent, m_arLeftState);
67 DocumentUpdated(m_pMainFrm->m_pwndRightView, m_arRightIdent, m_arRightState);
68 DocumentUpdated(m_pMainFrm->m_pwndBottomView, m_arBottomIdent, m_arBottomState);
70 if (m_pMainFrm->m_pwndLeftView)
72 m_nLines = m_pMainFrm->m_pwndLeftView->GetLineCount();
73 if (m_pMainFrm->m_pwndRightView)
75 m_nLines = std::max<int>(m_nLines, m_pMainFrm->m_pwndRightView->GetLineCount());
76 if (m_pMainFrm->m_pwndBottomView)
78 m_nLines = std::max<int>(m_nLines, m_pMainFrm->m_pwndBottomView->GetLineCount());
82 Invalidate();
85 void CLocatorBar::DocumentUpdated(CBaseView* view, CDWordArray& indents, CDWordArray& states)
87 indents.RemoveAll();
88 states.RemoveAll();
89 CViewData* viewData = view->m_pViewData;
90 if(viewData == 0)
91 return;
93 long identcount = 1;
94 const int linesInView = view->GetLineCount();
95 DiffStates state = DIFFSTATE_UNKNOWN;
96 if (linesInView)
97 state = viewData->GetState(0);
98 for (int i=1; i<linesInView; i++)
100 const DiffStates lineState = viewData->GetState(view->GetViewLineForScreen(i));
101 if (state == lineState)
103 identcount++;
105 else
107 indents.Add(identcount);
108 states.Add(state);
109 state = lineState;
110 identcount = 1;
113 indents.Add(identcount);
114 states.Add(state);
117 void CLocatorBar::OnPaint()
119 CPaintDC dc(this); // device context for painting
120 CRect rect;
121 GetClientRect(rect);
122 const long height = rect.Height();
123 const long width = rect.Width();
124 long nTopLine = 0;
125 long nBottomLine = 0;
126 if ((m_pMainFrm)&&(m_pMainFrm->m_pwndLeftView))
128 nTopLine = m_pMainFrm->m_pwndLeftView->m_nTopLine;
129 nBottomLine = nTopLine + m_pMainFrm->m_pwndLeftView->GetScreenLines();
131 CDC cacheDC;
132 VERIFY(cacheDC.CreateCompatibleDC(&dc));
134 if (m_pCacheBitmap == NULL)
136 m_pCacheBitmap = new CBitmap;
137 VERIFY(m_pCacheBitmap->CreateCompatibleBitmap(&dc, width, height));
139 CBitmap *pOldBitmap = cacheDC.SelectObject(m_pCacheBitmap);
141 COLORREF color, color2;
142 CDiffColors::GetInstance().GetColors(DIFFSTATE_UNKNOWN, color, color2);
143 cacheDC.FillSolidRect(rect, color);
145 if (m_nLines)
147 cacheDC.FillSolidRect(rect.left, height*nTopLine/m_nLines,
148 width, (height*nBottomLine/m_nLines)-(height*nTopLine/m_nLines), RGB(180,180,255));
150 if (m_pMainFrm)
152 PaintView (cacheDC, m_pMainFrm->m_pwndLeftView, m_arLeftIdent, m_arLeftState, rect, 0);
153 PaintView (cacheDC, m_pMainFrm->m_pwndRightView, m_arRightIdent, m_arRightState, rect, 2);
154 PaintView (cacheDC, m_pMainFrm->m_pwndBottomView, m_arBottomIdent, m_arBottomState, rect, 1);
158 if (m_nLines == 0)
159 m_nLines = 1;
160 cacheDC.FillSolidRect(rect.left, height*nTopLine/m_nLines,
161 width, 2, RGB(0,0,0));
162 cacheDC.FillSolidRect(rect.left, height*nBottomLine/m_nLines,
163 width, 2, RGB(0,0,0));
164 //draw two vertical lines, so there are three rows visible indicating the three panes
165 cacheDC.FillSolidRect(rect.left + (width/3), rect.top, 1, height, RGB(0,0,0));
166 cacheDC.FillSolidRect(rect.left + (width*2/3), rect.top, 1, height, RGB(0,0,0));
168 // draw the fish eye
169 DWORD pos = GetMessagePos();
170 CRect screenRect = rect;
171 ClientToScreen(screenRect);
172 POINT pt;
173 pt.x = GET_X_LPARAM(pos);
174 pt.y = GET_Y_LPARAM(pos);
176 if ((screenRect.PtInRect(pt))&&(DWORD(m_regUseFishEye)))
177 DrawFishEye (cacheDC, rect);
179 VERIFY(dc.BitBlt(rect.left, rect.top, width, height, &cacheDC, 0, 0, SRCCOPY));
181 cacheDC.SelectObject(pOldBitmap);
182 cacheDC.DeleteDC();
185 void CLocatorBar::OnSize(UINT nType, int cx, int cy)
187 CPaneDialog::OnSize(nType, cx, cy);
189 if (m_pCacheBitmap != NULL)
191 m_pCacheBitmap->DeleteObject();
192 delete m_pCacheBitmap;
193 m_pCacheBitmap = NULL;
195 Invalidate();
198 BOOL CLocatorBar::OnEraseBkgnd(CDC* /*pDC*/)
200 return TRUE;
203 void CLocatorBar::OnLButtonDown(UINT nFlags, CPoint point)
205 ScrollOnMouseMove(point);
206 Invalidate();
207 CPaneDialog::OnLButtonDown(nFlags, point);
210 void CLocatorBar::OnMouseMove(UINT nFlags, CPoint point)
212 m_MousePos = point;
214 if (nFlags & MK_LBUTTON)
216 SetCapture();
217 ScrollOnMouseMove(point);
220 TRACKMOUSEEVENT Tme;
221 Tme.cbSize = sizeof(TRACKMOUSEEVENT);
222 Tme.dwFlags = TME_LEAVE;
223 Tme.hwndTrack = m_hWnd;
224 TrackMouseEvent(&Tme);
227 Invalidate();
230 LRESULT CLocatorBar::OnMouseLeave(WPARAM /*wParam*/, LPARAM /*lParam*/)
232 Invalidate();
233 return 0;
236 void CLocatorBar::OnLButtonUp(UINT nFlags, CPoint point)
238 ReleaseCapture();
239 Invalidate();
241 CPaneDialog::OnLButtonUp(nFlags, point);
244 void CLocatorBar::ScrollOnMouseMove(const CPoint& point )
246 if (m_pMainFrm == 0)
247 return;
249 CRect rect;
250 GetClientRect(rect);
252 int nLine = point.y*m_nLines/rect.Height();
253 if (nLine < 0)
254 nLine = 0;
256 ScrollViewToLine(m_pMainFrm->m_pwndBottomView, nLine);
257 ScrollViewToLine(m_pMainFrm->m_pwndLeftView, nLine);
258 ScrollViewToLine(m_pMainFrm->m_pwndRightView, nLine);
261 void CLocatorBar::ScrollViewToLine(CBaseView* view, int nLine) const
263 if (view != 0)
264 view->GoToLine(nLine, FALSE);
267 void CLocatorBar::PaintView(CDC& cacheDC, CBaseView* view, CDWordArray& indents,
268 CDWordArray& states, const CRect& rect, int stripeIndex)
270 if (!view->IsWindowVisible())
271 return;
273 const long height = rect.Height();
274 const long width = rect.Width();
275 const long barwidth = (width/3);
276 long linecount = 0;
277 for (long i=0; i<indents.GetCount(); i++)
279 COLORREF color, color2;
280 const long identcount = indents.GetAt(i);
281 const DWORD state = states.GetAt(i);
282 CDiffColors::GetInstance().GetColors((DiffStates)state, color, color2);
283 if ((DiffStates)state != DIFFSTATE_NORMAL)
285 cacheDC.FillSolidRect(rect.left + (width*stripeIndex/3), height*linecount/m_nLines,
286 barwidth, max(height*identcount/m_nLines,1), color);
288 linecount += identcount;
290 if (view->GetMarkedWord()[0])
292 COLORREF color, color2;
293 CDiffColors::GetInstance().GetColors(DIFFSTATE_NORMAL, color, color2);
294 color = CAppUtils::IntenseColor(200, color);
295 for (size_t i=0; i<view->m_arMarkedWordLines.size(); ++i)
297 if (view->m_arMarkedWordLines[i])
299 cacheDC.FillSolidRect(rect.left + (width*stripeIndex/3), (int)(height*i/m_nLines),
300 barwidth, max(height/m_nLines,2), color);
304 if (view->GetFindString()[0])
306 COLORREF color, color2;
307 CDiffColors::GetInstance().GetColors(DIFFSTATE_NORMAL, color, color2);
308 color = CAppUtils::IntenseColor(30, color);
309 for (size_t i=0; i<view->m_arFindStringLines.size(); ++i)
311 if (view->m_arFindStringLines[i])
313 cacheDC.FillSolidRect(rect.left + (width*stripeIndex/3), (int)(height*i/m_nLines),
314 barwidth, max(height/m_nLines,2), color);
321 void CLocatorBar::DrawFishEye(CDC& cacheDC, const CRect& rect )
323 const long height = rect.Height();
324 const long width = rect.Width();
325 const int fishstart = m_MousePos.y - height/20;
326 const int fishheight = height/10;
327 cacheDC.FillSolidRect(rect.left, fishstart-1, width, 1, RGB(0,0,100));
328 cacheDC.FillSolidRect(rect.left, fishstart+fishheight+1, width, 1, RGB(0,0,100));
329 VERIFY(cacheDC.StretchBlt(rect.left, fishstart, width, fishheight,
330 &cacheDC, 0, fishstart + (3*fishheight/8), width, fishheight/4, SRCCOPY));
331 // draw the magnified area a little darker, so the
332 // user has a clear indication of the magnifier
333 for (int i=rect.left; i<(width - rect.left); i++)
335 for (int j=fishstart; j<fishstart+fishheight; j++)
337 const COLORREF color = cacheDC.GetPixel(i, j);
338 int r = max(GetRValue(color)-20, 0);
339 int g = max(GetGValue(color)-20, 0);
340 int b = max(GetBValue(color)-20, 0);
341 cacheDC.SetPixel(i, j, RGB(r,g,b));