Revision Graph: Add filter to walk from Only Local Branches
[TortoiseGit.git] / src / TortoiseProc / RevisionGraph / RevisionGraphDlg.cpp
blob37d6a00adc7197cbe8610234e264c3b2fd9e66c5
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2012 - TortoiseSVN
4 // Copyright (C) 2012-2014 - TortoiseGit
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "stdafx.h"
21 #include "TortoiseProc.h"
22 #include "RevisionGraphDlg.h"
23 #include "MessageBox.h"
24 #include "Git.h"
25 #include "AppUtils.h"
26 #include "StringUtils.h"
27 #include "TempFile.h"
28 #include "UnicodeUtils.h"
29 #include "TGitPath.h"
30 //#include "SVNInfo.h"
31 //#include "SVNDiff.h"
32 #include "RevGraphFilterDlg.h"
33 //#include "RepositoryInfo.h"
34 //#include "RevisionInRange.h"
35 //#include "RemovePathsBySubString.h"
37 #ifdef _DEBUG
38 #define new DEBUG_NEW
39 #undef THIS_FILE
40 static char THIS_FILE[] = __FILE__;
41 #endif
43 using namespace Gdiplus;
45 IMPLEMENT_DYNAMIC(CRevisionGraphDlg, CResizableStandAloneDialog)
46 CRevisionGraphDlg::CRevisionGraphDlg(CWnd* pParent /*=NULL*/)
47 : CResizableStandAloneDialog(CRevisionGraphDlg::IDD, pParent)
48 , m_hAccel(NULL)
49 , m_bFetchLogs(true)
50 , m_fZoomFactor(DEFAULT_ZOOM)
51 , m_bVisible(true)
53 // GDI+ initialization
55 GdiplusStartupInput input;
56 GdiplusStartup (&m_gdiPlusToken, &input, NULL);
58 // restore option state
60 // DWORD dwOpts = CRegStdDWORD(_T("Software\\TortoiseGit\\RevisionGraphOptions"), 0x1ff199);
61 // m_Graph.m_state.GetOptions()->SetRegistryFlags (dwOpts, 0x407fbf);
63 m_szTip[0] = 0;
64 m_wszTip[0] = 0;
67 CRevisionGraphDlg::~CRevisionGraphDlg()
69 // save option state
71 CRegStdDWORD regOpts = CRegStdDWORD(_T("Software\\TortoiseGit\\RevisionGraphOptions"), 1);
72 // regOpts = m_Graph.m_state.GetOptions()->GetRegistryFlags();
74 // GDI+ cleanup
76 GdiplusShutdown (m_gdiPlusToken);
79 void CRevisionGraphDlg::DoDataExchange(CDataExchange* pDX)
81 CResizableStandAloneDialog::DoDataExchange(pDX);
85 BEGIN_MESSAGE_MAP(CRevisionGraphDlg, CResizableStandAloneDialog)
86 ON_WM_SIZE()
87 ON_WM_LBUTTONDOWN()
89 ON_COMMAND(ID_VIEW_ZOOMIN, OnViewZoomin)
90 ON_COMMAND(ID_VIEW_ZOOMOUT, OnViewZoomout)
91 ON_COMMAND(ID_VIEW_ZOOM100, OnViewZoom100)
92 ON_COMMAND(ID_VIEW_ZOOMHEIGHT, OnViewZoomHeight)
93 ON_COMMAND(ID_VIEW_ZOOMWIDTH, OnViewZoomWidth)
94 ON_COMMAND(ID_VIEW_ZOOMALL, OnViewZoomAll)
95 ON_CBN_SELCHANGE(ID_REVGRAPH_ZOOMCOMBO, OnChangeZoom)
96 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
97 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
98 ON_COMMAND(ID_MENUEXIT, OnMenuexit)
99 ON_COMMAND(ID_MENUHELP, OnMenuhelp)
100 ON_COMMAND(ID_FILE_SAVEGRAPHAS, OnFileSavegraphas)
101 ON_COMMAND(ID_VIEW_SHOWOVERVIEW, OnViewShowoverview)
102 ON_COMMAND(ID_VIEW_FILTER, OnViewFilter)
103 ON_COMMAND(ID_VIEW_COMPAREHEADREVISIONS, OnViewCompareheadrevisions)
104 ON_COMMAND(ID_VIEW_COMPAREREVISIONS, OnViewComparerevisions)
105 ON_COMMAND(ID_VIEW_UNIFIEDDIFF, OnViewUnifieddiff)
106 ON_COMMAND(ID_VIEW_UNIFIEDDIFFOFHEADREVISIONS, OnViewUnifieddiffofheadrevisions)
108 #if 0
109 ON_COMMAND_EX(ID_VIEW_SHOWALLREVISIONS, OnToggleOption)
110 ON_COMMAND_EX(ID_VIEW_GROUPBRANCHES, OnToggleOption)
111 ON_COMMAND_EX(ID_VIEW_TOPDOWN, OnToggleOption)
112 ON_COMMAND_EX(ID_VIEW_TOPALIGNTREES, OnToggleOption)
113 ON_COMMAND_EX(ID_VIEW_SHOWHEAD, OnToggleOption)
114 ON_COMMAND_EX(ID_VIEW_EXACTCOPYSOURCE, OnToggleOption)
115 ON_COMMAND_EX(ID_VIEW_FOLDTAGS, OnToggleOption)
116 ON_COMMAND_EX(ID_VIEW_REDUCECROSSLINES, OnToggleOption)
117 ON_COMMAND_EX(ID_VIEW_REMOVEDELETEDONES, OnToggleOption)
118 ON_COMMAND_EX(ID_VIEW_SHOWWCREV, OnToggleReloadOption)
119 ON_COMMAND_EX(ID_VIEW_REMOVEUNCHANGEDBRANCHES, OnToggleOption)
120 ON_COMMAND_EX(ID_VIEW_REMOVETAGS, OnToggleOption)
121 ON_COMMAND_EX(ID_VIEW_SHOWWCMODIFICATION, OnToggleReloadOption)
122 ON_COMMAND_EX(ID_VIEW_SHOWDIFFPATHS, OnToggleOption)
123 ON_COMMAND_EX(ID_VIEW_SHOWTREESTRIPES, OnToggleRedrawOption)
124 #endif
125 ON_WM_WINDOWPOSCHANGING()
127 END_MESSAGE_MAP()
129 BOOL CRevisionGraphDlg::InitializeToolbar()
131 // set up the toolbar
132 // add the tool bar to the dialog
133 m_ToolBar.CreateEx(this, TBSTYLE_FLAT | TBSTYLE_WRAPABLE | TBSTYLE_TRANSPARENT | CBRS_SIZE_DYNAMIC);
134 m_ToolBar.LoadToolBar(IDR_REVGRAPHBAR);
135 m_ToolBar.ShowWindow(SW_SHOW);
136 m_ToolBar.SetBarStyle(CBRS_ALIGN_TOP | CBRS_TOOLTIPS | CBRS_FLYBY);
138 // toolbars aren't true-color without some tweaking:
140 CImageList cImageList;
141 CBitmap cBitmap;
142 BITMAP bmBitmap;
144 cBitmap.Attach(LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_REVGRAPHBAR),
145 IMAGE_BITMAP, 0, 0,
146 LR_DEFAULTSIZE|LR_CREATEDIBSECTION));
147 cBitmap.GetBitmap(&bmBitmap);
149 CSize cSize(bmBitmap.bmWidth, bmBitmap.bmHeight);
150 int nNbBtn = cSize.cx/20;
151 RGBTRIPLE * rgb = (RGBTRIPLE*)(bmBitmap.bmBits);
152 COLORREF rgbMask = RGB(rgb[0].rgbtRed, rgb[0].rgbtGreen, rgb[0].rgbtBlue);
154 cImageList.Create(20, cSize.cy, ILC_COLOR32|ILC_MASK, nNbBtn, 0);
155 cImageList.Add(&cBitmap, rgbMask);
156 m_ToolBar.SendMessage(TB_SETIMAGELIST, 0, (LPARAM)cImageList.m_hImageList);
157 cImageList.Detach();
158 cBitmap.Detach();
160 RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
163 #define SNAP_WIDTH 60 //the width of the combo box
164 // set up the ComboBox control as a snap mode select box
165 // First get the index of the placeholders position in the toolbar
166 int zoomComboIndex = 0;
167 while (m_ToolBar.GetItemID(zoomComboIndex) != ID_REVGRAPH_ZOOMCOMBO) ++zoomComboIndex;
169 // next convert that button to a separator and get its position
170 m_ToolBar.SetButtonInfo(zoomComboIndex, ID_REVGRAPH_ZOOMCOMBO, TBBS_SEPARATOR,
171 SNAP_WIDTH);
172 RECT rect;
173 m_ToolBar.GetItemRect(zoomComboIndex, &rect);
175 // expand the rectangle to allow the combo box room to drop down
176 rect.top+=3;
177 rect.bottom += 200;
179 // then create the combo box and show it
180 if (!m_ToolBar.m_ZoomCombo.CreateEx(WS_EX_RIGHT, WS_CHILD|WS_VISIBLE|CBS_AUTOHSCROLL|CBS_DROPDOWN,
181 rect, &m_ToolBar, ID_REVGRAPH_ZOOMCOMBO))
183 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Failed to create combo-box\n");
184 return FALSE;
186 m_ToolBar.m_ZoomCombo.ShowWindow(SW_SHOW);
188 // fill the combo box
190 TCHAR* texts[] = { _T("5%")
191 , _T("10%")
192 , _T("20%")
193 , _T("40%")
194 , _T("50%")
195 , _T("75%")
196 , _T("100%")
197 , _T("200%")
198 , NULL};
200 COMBOBOXEXITEM cbei;
201 SecureZeroMemory(&cbei, sizeof cbei);
202 cbei.mask = CBEIF_TEXT;
204 for (TCHAR** text = texts; *text != NULL; ++text)
206 cbei.pszText = *text;
207 m_ToolBar.m_ZoomCombo.InsertItem(&cbei);
210 m_ToolBar.m_ZoomCombo.SetCurSel(1);
212 UpdateOptionAvailability();
214 return TRUE;
217 BOOL CRevisionGraphDlg::OnInitDialog()
219 CResizableStandAloneDialog::OnInitDialog();
220 CAppUtils::MarkWindowAsUnpinnable(m_hWnd);
222 EnableToolTips();
224 CString sWindowTitle;
225 GetWindowText(sWindowTitle);
226 CAppUtils::SetWindowTitle(m_hWnd, g_Git.m_CurrentDir, sWindowTitle);
229 // set up the status bar
230 m_StatusBar.Create(WS_CHILD|WS_VISIBLE|SBT_OWNERDRAW,
231 CRect(0,0,0,0), this, 1);
232 int strPartDim[2]= {120, -1};
233 m_StatusBar.SetParts(2, strPartDim);
235 if (InitializeToolbar() != TRUE)
236 return FALSE;
238 m_pTaskbarList.Release();
239 if (FAILED(m_pTaskbarList.CoCreateInstance(CLSID_TaskbarList)))
240 m_pTaskbarList = nullptr;
242 // CSyncPointer<CAllRevisionGraphOptions>
243 // options (m_Graph.m_state.GetOptions());
245 // for (size_t i = 0; i < options->count(); ++i)
246 // if ((*options)[i]->CommandID() != 0)
247 // SetOption ((*options)[i]->CommandID());
249 #if 0
250 CMenu * pMenu = GetMenu();
251 if (pMenu)
253 CRegDWORD reg = CRegDWORD(_T("Software\\TortoiseGit\\ShowRevGraphOverview"), FALSE);
254 m_Graph.SetShowOverview ((DWORD)reg != FALSE);
255 pMenu->CheckMenuItem(ID_VIEW_SHOWOVERVIEW, MF_BYCOMMAND | (DWORD(reg) ? MF_CHECKED : 0));
256 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(ID_VIEW_SHOWOVERVIEW);
257 m_ToolBar.GetToolBarCtrl().SetState(ID_VIEW_SHOWOVERVIEW, tbstate | (DWORD(reg) ? TBSTATE_CHECKED : 0));
259 #endif
261 // m_hAccel = LoadAccelerators(AfxGetResourceHandle(),MAKEINTRESOURCE(IDR_ACC_REVISIONGRAPH));
264 CRect graphrect = GetGraphRect();
265 m_Graph.Init(this, &graphrect);
266 m_Graph.SetOwner(this);
267 m_Graph.UpdateWindow();
268 DoZoom (DEFAULT_ZOOM);
270 // begin background operation
271 StartWorkerThread();
273 EnableSaveRestore(_T("RevisionGraphDlg"));
274 // if (GetExplorerHWND())
275 // CenterWindow(CWnd::FromHandle(GetExplorerHWND()));
277 return TRUE; // return TRUE unless you set the focus to a control
280 bool CRevisionGraphDlg::UpdateData()
282 CoInitialize(NULL);
284 if (!m_Graph.FetchRevisionData (m_Graph.m_sPath, GitRev(), NULL, m_pTaskbarList, m_hWnd))
286 // only show the error dialog if we're not in hidden mode
287 //if (m_bVisible)
289 // TGitMessageBox( m_hWnd
290 // , // m_Graph.m_state.GetLastErrorMessage()
291 // , _T("TortoiseGit")
292 // , MB_ICONERROR);
296 #if 0
297 if (m_bFetchLogs)
299 CProgressDlg progress;
300 progress.SetTitle(IDS_REVGRAPH_PROGTITLE);
301 progress.SetCancelMsg(IDS_REVGRAPH_PROGCANCEL);
302 progress.SetTime();
303 progress.SetProgress(0, 100);
304 if (m_pTaskbarList)
306 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NORMAL);
307 m_pTaskbarList->SetProgressValue(m_hWnd, 0, 100);
310 svn_revnum_t pegRev = m_Graph.m_pegRev.IsNumber()
311 ? (svn_revnum_t)m_Graph.m_pegRev
312 : (svn_revnum_t)-1;
314 if (!m_Graph.FetchRevisionData (m_Graph.m_sPath, pegRev, &progress, m_pTaskbarList, m_hWnd))
316 // only show the error dialog if we're not in hidden mode
317 if (m_bVisible)
319 TSVNMessageBox( m_hWnd
320 , m_Graph.m_state.GetLastErrorMessage()
321 , _T("TortoiseGit")
322 , MB_ICONERROR);
326 progress.Stop();
327 if (m_pTaskbarList)
329 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NOPROGRESS);
332 m_bFetchLogs = false; // we've got the logs, no need to fetch them a second time
335 // standard plus user settings
338 if (m_Graph.AnalyzeRevisionData())
340 UpdateStatusBar();
341 UpdateOptionAvailability();
343 #endif
345 CoUninitialize();
346 m_Graph.PostMessage (CRevisionGraphWnd::WM_WORKERTHREADDONE, 0, 0);
348 return true;
351 void CRevisionGraphDlg::OnSize(UINT nType, int cx, int cy)
353 __super::OnSize(nType, cx, cy);
354 CRect rect;
355 GetClientRect(&rect);
356 if (IsWindow(m_ToolBar))
358 RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
360 if (IsWindow(m_StatusBar))
362 CRect statusbarrect;
363 m_StatusBar.GetClientRect(&statusbarrect);
364 statusbarrect.top = rect.bottom - statusbarrect.top + statusbarrect.bottom;
365 m_StatusBar.MoveWindow(&statusbarrect);
367 if (IsWindow(m_Graph))
369 m_Graph.MoveWindow (GetGraphRect());
373 BOOL CRevisionGraphDlg::PreTranslateMessage(MSG* pMsg)
375 #define SCROLL_STEP 20
376 if (pMsg->message == WM_KEYDOWN)
378 int pos = 0;
379 switch (pMsg->wParam)
381 case VK_UP:
382 pos = m_Graph.GetScrollPos(SB_VERT);
383 m_Graph.SetScrollPos(SB_VERT, pos - SCROLL_STEP);
384 m_Graph.Invalidate();
385 break;
386 case VK_DOWN:
387 pos = m_Graph.GetScrollPos(SB_VERT);
388 m_Graph.SetScrollPos(SB_VERT, pos + SCROLL_STEP);
389 m_Graph.Invalidate();
390 break;
391 case VK_LEFT:
392 pos = m_Graph.GetScrollPos(SB_HORZ);
393 m_Graph.SetScrollPos(SB_HORZ, pos - SCROLL_STEP);
394 m_Graph.Invalidate();
395 break;
396 case VK_RIGHT:
397 pos = m_Graph.GetScrollPos(SB_HORZ);
398 m_Graph.SetScrollPos(SB_HORZ, pos + SCROLL_STEP);
399 m_Graph.Invalidate();
400 break;
401 case VK_PRIOR:
402 pos = m_Graph.GetScrollPos(SB_VERT);
403 m_Graph.SetScrollPos(SB_VERT, pos - GetGraphRect().Height() / 2);
404 m_Graph.Invalidate();
405 break;
406 case VK_NEXT:
407 pos = m_Graph.GetScrollPos(SB_VERT);
408 m_Graph.SetScrollPos(SB_VERT, pos + GetGraphRect().Height() / 2);
409 m_Graph.Invalidate();
410 break;
411 case VK_F5:
412 UpdateFullHistory();
413 break;
416 if ((m_hAccel)&&(pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST))
418 if (pMsg->wParam == VK_ESCAPE)
419 if (m_Graph.CancelMouseZoom())
420 return TRUE;
421 return TranslateAccelerator(m_hWnd,m_hAccel,pMsg);
423 return __super::PreTranslateMessage(pMsg);
426 void CRevisionGraphDlg::DoZoom (float zoom)
428 m_fZoomFactor = zoom;
429 m_Graph.DoZoom (zoom);
430 UpdateZoomBox();
433 void CRevisionGraphDlg::OnViewZoomin()
435 DoZoom (min (MAX_ZOOM, m_fZoomFactor / ZOOM_STEP));
438 void CRevisionGraphDlg::OnViewZoomout()
440 DoZoom (max (MIN_ZOOM, m_fZoomFactor * ZOOM_STEP));
443 void CRevisionGraphDlg::OnViewZoom100()
445 DoZoom (DEFAULT_ZOOM);
448 void CRevisionGraphDlg::OnViewZoomHeight()
450 CRect graphRect = m_Graph.GetGraphRect();
451 CRect windowRect = m_Graph.GetWindowRect();
453 float horzfact = (windowRect.Width() - 4.0f)/(4.0f + graphRect.Width());
454 float vertfact = (windowRect.Height() - 4.0f)/(4.0f + graphRect.Height());
455 if ((horzfact < vertfact) && (horzfact < MAX_ZOOM))
456 vertfact = (windowRect.Height() - 20.0f)/(4.0f + graphRect.Height());
458 DoZoom (min (MAX_ZOOM, vertfact));
461 void CRevisionGraphDlg::OnViewZoomWidth()
463 // zoom the graph so that it is completely visible in the window
464 CRect graphRect = m_Graph.GetGraphRect();
465 CRect windowRect = m_Graph.GetWindowRect();
467 float horzfact = (windowRect.Width() - 4.0f)/(4.0f + graphRect.Width());
468 float vertfact = (windowRect.Height() - 4.0f)/(4.0f + graphRect.Height());
469 if ((vertfact < horzfact) && (vertfact < MAX_ZOOM))
470 horzfact = (windowRect.Width() - 20.0f)/(4.0f + graphRect.Width());
472 DoZoom (min (MAX_ZOOM, horzfact));
475 void CRevisionGraphDlg::OnViewZoomAll()
477 // zoom the graph so that it is completely visible in the window
478 CRect graphRect = m_Graph.GetGraphRect();
479 CRect windowRect = m_Graph.GetWindowRect();
481 float horzfact = (windowRect.Width() - 4.0f)/(4.0f + graphRect.Width());
482 float vertfact = (windowRect.Height() - 4.0f)/(4.0f + graphRect.Height());
484 DoZoom (min (MAX_ZOOM, min(horzfact, vertfact)));
487 void CRevisionGraphDlg::OnMenuexit()
489 if (!m_Graph.IsUpdateJobRunning())
490 EndDialog(IDOK);
493 void CRevisionGraphDlg::OnMenuhelp()
495 OnHelp();
498 void CRevisionGraphDlg::OnViewCompareheadrevisions()
500 m_Graph.CompareRevs(_T("HEAD"));
503 void CRevisionGraphDlg::OnViewComparerevisions()
505 m_Graph.CompareRevs(false);
508 void CRevisionGraphDlg::OnViewUnifieddiff()
510 m_Graph.UnifiedDiffRevs(false);
513 void CRevisionGraphDlg::OnViewUnifieddiffofheadrevisions()
515 m_Graph.UnifiedDiffRevs(true);
518 void CRevisionGraphDlg::UpdateFullHistory()
520 m_Graph.SetDlgTitle (false);
521 m_bFetchLogs = true;
522 Invalidate();
523 StartWorkerThread();
525 #if 0
526 m_Graph.SetDlgTitle (false);
528 SVN svn;
529 LogCache::CRepositoryInfo& cachedProperties
530 = svn.GetLogCachePool()->GetRepositoryInfo();
531 CString root = m_Graph.m_state.GetRepositoryRoot();
532 CString uuid = m_Graph.m_state.GetRepositoryUUID();
534 cachedProperties.ResetHeadRevision (uuid, root);
536 m_bFetchLogs = true;
537 StartWorkerThread();
538 #endif
541 void CRevisionGraphDlg::SetOption (UINT /*controlID*/)
543 #if 0
544 CMenu * pMenu = GetMenu();
545 if (pMenu == NULL)
546 return;
548 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(controlID);
549 if (tbstate != -1)
551 if (m_Graph.m_state.GetOptions()->IsSelected (controlID))
553 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_CHECKED);
554 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate | TBSTATE_CHECKED);
556 else
558 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_UNCHECKED);
559 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate & (~TBSTATE_CHECKED));
562 #endif
565 BOOL CRevisionGraphDlg::ToggleOption (UINT controlID)
567 // check request for validity
569 if (m_Graph.IsUpdateJobRunning())
571 // restore previous state
573 int state = m_ToolBar.GetToolBarCtrl().GetState(controlID);
574 if (state & TBSTATE_CHECKED)
575 state &= ~TBSTATE_CHECKED;
576 else
577 state |= TBSTATE_CHECKED;
578 m_ToolBar.GetToolBarCtrl().SetState (controlID, state);
580 return FALSE;
583 CMenu * pMenu = GetMenu();
584 if (pMenu == NULL)
585 return FALSE;
587 // actually toggle the option
589 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(controlID);
590 UINT state = pMenu->GetMenuState(controlID, MF_BYCOMMAND);
591 if (state & MF_CHECKED)
593 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_UNCHECKED);
594 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate & (~TBSTATE_CHECKED));
596 else
598 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_CHECKED);
599 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate | TBSTATE_CHECKED);
602 // CSyncPointer<CAllRevisionGraphOptions>
603 // options (m_Graph.m_state.GetOptions());
604 // if (((state & MF_CHECKED) != 0) == options->IsSelected (controlID))
605 // options->ToggleSelection (controlID);
607 return TRUE;
610 BOOL CRevisionGraphDlg::OnToggleOption (UINT controlID)
612 if (!ToggleOption (controlID))
613 return FALSE;
615 // re-process the data
617 StartWorkerThread();
619 return TRUE;
622 BOOL CRevisionGraphDlg::OnToggleReloadOption (UINT controlID)
624 #if 0
625 if (!m_Graph.m_state.GetFetchedWCState())
626 m_bFetchLogs = true;
627 #endif
628 return OnToggleOption (controlID);
631 BOOL CRevisionGraphDlg::OnToggleRedrawOption (UINT controlID)
633 if (!ToggleOption (controlID))
634 return FALSE;
636 m_Graph.BuildPreview();
637 Invalidate();
639 return TRUE;
642 void CRevisionGraphDlg::StartWorkerThread()
644 if (!m_Graph.IsUpdateJobRunning())
645 m_Graph.updateJob.reset (new CFuture<bool>(this, &CRevisionGraphDlg::UpdateData));
648 void CRevisionGraphDlg::OnCancel()
650 if (!m_Graph.IsUpdateJobRunning())
651 __super::OnCancel();
654 void CRevisionGraphDlg::OnOK()
656 OnChangeZoom();
659 void CRevisionGraphDlg::OnFileSavegraphas()
661 CString tempfile;
662 int filterindex = 0;
663 if (CAppUtils::FileOpenSave(tempfile, &filterindex, IDS_REVGRAPH_SAVEPIC, IDS_PICTUREFILEFILTER, false, m_hWnd))
665 // if the user doesn't specify a file extension, default to
666 // svg and add that extension to the filename. But only if the
667 // user chose the 'pictures' filter. The filename isn't changed
668 // if the 'All files' filter was chosen.
669 CString extension;
670 int dotPos = tempfile.ReverseFind('.');
671 int slashPos = tempfile.ReverseFind('\\');
672 if (dotPos > slashPos)
673 extension = tempfile.Mid(dotPos);
674 if ((filterindex == 1)&&(extension.IsEmpty()))
676 extension = _T(".svg");
677 tempfile += extension;
679 if ((filterindex == 2)&&(extension.IsEmpty()))
681 extension = _T(".gv");
682 tempfile += extension;
684 m_Graph.SaveGraphAs(tempfile);
688 CRect CRevisionGraphDlg::GetGraphRect()
690 CRect rect;
691 GetClientRect(&rect);
693 CRect statusbarrect;
694 m_StatusBar.GetClientRect(&statusbarrect);
695 rect.bottom -= statusbarrect.Height();
697 CRect toolbarrect;
698 m_ToolBar.GetClientRect(&toolbarrect);
699 rect.top += toolbarrect.Height();
701 return rect;
704 void CRevisionGraphDlg::UpdateStatusBar()
706 // CString sFormat;
707 // sFormat.Format(IDS_REVGRAPH_STATUSBARURL, (LPCTSTR)m_Graph.m_sPath);
708 // m_StatusBar.SetText(sFormat,1,0);
709 // sFormat.Format(IDS_REVGRAPH_STATUSBARNUMNODES, m_Graph.m_state.GetNodeCount());
710 // m_StatusBar.SetText(sFormat,0,0);
713 void CRevisionGraphDlg::OnChangeZoom()
715 if (!IsWindow(m_Graph.GetSafeHwnd()))
716 return;
717 CString strText;
718 CString strItem;
719 CComboBoxEx* pCBox = (CComboBoxEx*)m_ToolBar.GetDlgItem(ID_REVGRAPH_ZOOMCOMBO);
720 pCBox->GetWindowText(strItem);
721 if (strItem.IsEmpty())
722 return;
724 DoZoom ((float)(_tstof(strItem)/100.0));
727 void CRevisionGraphDlg::UpdateZoomBox()
729 CString strText;
730 CString strItem;
731 CComboBoxEx* pCBox = (CComboBoxEx*)m_ToolBar.GetDlgItem(ID_REVGRAPH_ZOOMCOMBO);
732 pCBox->GetWindowText(strItem);
733 strText.Format(_T("%.0f%%"), (m_fZoomFactor*100.0));
734 if (strText.Compare(strItem) != 0)
735 pCBox->SetWindowText(strText);
738 BOOL CRevisionGraphDlg::OnToolTipNotify(UINT /*id*/, NMHDR *pNMHDR, LRESULT *pResult)
740 // need to handle both ANSI and UNICODE versions of the message
741 TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
742 TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
743 CString strTipText;
745 UINT_PTR nID = pNMHDR->idFrom;
747 if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
748 pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
750 // idFrom is actually the HWND of the tool
751 nID = ::GetDlgCtrlID((HWND)nID);
754 if (nID != 0) // will be zero on a separator
756 strTipText.LoadString (static_cast<UINT>(nID));
759 *pResult = 0;
760 if (strTipText.IsEmpty())
761 return TRUE;
763 if (strTipText.GetLength() >= MAX_TT_LENGTH)
764 strTipText = strTipText.Left(MAX_TT_LENGTH);
766 if (pNMHDR->code == TTN_NEEDTEXTA)
768 ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 600);
769 pTTTA->lpszText = m_szTip;
770 WideCharToMultiByte(CP_ACP, 0, strTipText, -1, m_szTip, strTipText.GetLength()+1, 0, 0);
772 else
774 ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 600);
775 lstrcpyn(m_wszTip, strTipText, strTipText.GetLength()+1);
776 pTTTW->lpszText = m_wszTip;
778 // bring the tooltip window above other pop up windows
779 ::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,
780 SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER);
781 return TRUE; // message was handled
784 void CRevisionGraphDlg::OnViewFilter()
787 /* CSyncPointer<CAllRevisionGraphOptions>
788 options (m_Graph.m_state.GetOptions());
790 CRevisionInRange* revisionRange = options->GetOption<CRevisionInRange>();
791 svn_revnum_t head = m_Graph.m_state.GetHeadRevision();
792 svn_revnum_t lowerLimit = revisionRange->GetLowerLimit();
793 svn_revnum_t upperLimit = revisionRange->GetUpperLimit();
795 CRemovePathsBySubString* pathFilter = options->GetOption<CRemovePathsBySubString>();
797 CRevGraphFilterDlg dlg;
799 dlg.m_bCurrentBranch = this->m_Graph.m_bCurrentBranch;
800 dlg.m_bLocalBranches = m_Graph.m_bLocalBranches;
801 dlg.SetRevisionRange(m_Graph.m_FromRev, m_Graph.m_ToRev);
803 if (dlg.DoModal()==IDOK)
806 // user pressed OK to dismiss the dialog, which means
807 // we have to accept the new filter settings and apply them
809 dlg.GetRevisionRange(m_Graph.m_FromRev, m_Graph.m_ToRev);
810 // update menu & toolbar
812 this->m_Graph.m_bCurrentBranch = dlg.m_bCurrentBranch;
813 m_Graph.m_bLocalBranches = dlg.m_bLocalBranches;
815 CMenu * pMenu = GetMenu();
816 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(ID_VIEW_FILTER);
817 if (m_Graph.m_bCurrentBranch || m_Graph.m_bLocalBranches || !m_Graph.m_FromRev.IsEmpty() || !m_Graph.m_ToRev.IsEmpty())
819 if (pMenu != NULL)
820 pMenu->CheckMenuItem(ID_VIEW_FILTER, MF_BYCOMMAND | MF_CHECKED);
821 m_ToolBar.GetToolBarCtrl().SetState(ID_VIEW_FILTER, tbstate | TBSTATE_CHECKED);
823 else
825 if (pMenu != NULL)
826 pMenu->CheckMenuItem(ID_VIEW_FILTER, MF_BYCOMMAND | MF_UNCHECKED);
827 m_ToolBar.GetToolBarCtrl().SetState(ID_VIEW_FILTER, tbstate & (~TBSTATE_CHECKED));
830 // re-run query
832 StartWorkerThread();
838 void CRevisionGraphDlg::OnViewShowoverview()
840 CMenu * pMenu = GetMenu();
841 if (pMenu == NULL)
842 return;
843 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(ID_VIEW_SHOWOVERVIEW);
844 UINT state = pMenu->GetMenuState(ID_VIEW_SHOWOVERVIEW, MF_BYCOMMAND);
845 if (state & MF_CHECKED)
847 pMenu->CheckMenuItem(ID_VIEW_SHOWOVERVIEW, MF_BYCOMMAND | MF_UNCHECKED);
848 m_ToolBar.GetToolBarCtrl().SetState(ID_VIEW_SHOWOVERVIEW, tbstate & (~TBSTATE_CHECKED));
849 m_Graph.SetShowOverview (false);
851 else
853 pMenu->CheckMenuItem(ID_VIEW_SHOWOVERVIEW, MF_BYCOMMAND | MF_CHECKED);
854 m_ToolBar.GetToolBarCtrl().SetState(ID_VIEW_SHOWOVERVIEW, tbstate | TBSTATE_CHECKED);
855 m_Graph.SetShowOverview (true);
858 CRegDWORD reg = CRegDWORD(_T("Software\\TortoiseGit\\ShowRevGraphOverview"), FALSE);
859 reg = m_Graph.GetShowOverview();
860 m_Graph.Invalidate(FALSE);
863 void CRevisionGraphDlg::UpdateOptionAvailability (UINT id, bool available)
865 CMenu * pMenu = GetMenu();
866 if (pMenu == NULL)
867 return;
869 pMenu->EnableMenuItem (id, available ? MF_ENABLED : MF_GRAYED);
871 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(id);
872 int newTbstate = available
873 ? tbstate | TBSTATE_ENABLED
874 : tbstate & ~TBSTATE_ENABLED;
876 if (tbstate != newTbstate)
877 m_ToolBar.GetToolBarCtrl().SetState(id, newTbstate);
880 void CRevisionGraphDlg::UpdateOptionAvailability()
882 #if 0
883 bool multipleTrees = m_Graph.m_state.GetTreeCount() > 1;
884 bool isWCPath = !CTGitPath (m_Graph.m_sPath).IsUrl();
886 UpdateOptionAvailability (ID_VIEW_TOPALIGNTREES, multipleTrees);
887 UpdateOptionAvailability (ID_VIEW_SHOWTREESTRIPES, multipleTrees);
888 UpdateOptionAvailability (ID_VIEW_SHOWWCREV, isWCPath);
889 UpdateOptionAvailability (ID_VIEW_SHOWWCMODIFICATION, isWCPath);
890 #endif
895 void CRevisionGraphDlg::OnWindowPosChanging(WINDOWPOS* lpwndpos)
897 if (!m_bVisible)
899 lpwndpos->flags &= ~SWP_SHOWWINDOW;
901 CResizableStandAloneDialog::OnWindowPosChanging(lpwndpos);