Don't import ogdf namespace
[TortoiseGit.git] / src / TortoiseProc / RevisionGraph / RevisionGraphDlg.cpp
blob00578087bfe59f7180329d44e8d59b0223fb348e
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2012, 2018 - TortoiseSVN
4 // Copyright (C) 2012-2016, 2018 - 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 "Git.h"
24 #include "AppUtils.h"
25 #include "StringUtils.h"
26 #include "TempFile.h"
27 #include "UnicodeUtils.h"
28 #include "TGitPath.h"
29 //#include "SVNInfo.h"
30 //#include "SVNDiff.h"
31 #include "RevGraphFilterDlg.h"
32 //#include "RepositoryInfo.h"
33 //#include "RevisionInRange.h"
34 //#include "RemovePathsBySubString.h"
35 #include "DPIAware.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 struct CToolBarData
47 WORD wVersion;
48 WORD wWidth;
49 WORD wHeight;
50 WORD wItemCount;
51 //WORD aItems[wItemCount]
53 WORD* items()
55 return (WORD*)(this + 1);
59 IMPLEMENT_DYNAMIC(CRevisionGraphDlg, CResizableStandAloneDialog)
60 CRevisionGraphDlg::CRevisionGraphDlg(CWnd* pParent /*=nullptr*/)
61 : CResizableStandAloneDialog(CRevisionGraphDlg::IDD, pParent)
62 , m_hAccel(nullptr)
63 , m_bFetchLogs(true)
64 , m_fZoomFactor(DEFAULT_ZOOM)
65 , m_bVisible(true)
67 // GDI+ initialization
69 GdiplusStartupInput input;
70 GdiplusStartup(&m_gdiPlusToken, &input, nullptr);
72 // restore option state
74 // DWORD dwOpts = CRegStdDWORD(L"Software\\TortoiseGit\\RevisionGraphOptions", 0x1ff199);
75 // m_Graph.m_state.GetOptions()->SetRegistryFlags (dwOpts, 0x407fbf);
77 m_szTip[0] = '\0';
78 m_wszTip[0] = L'\0';
81 CRevisionGraphDlg::~CRevisionGraphDlg()
83 // save option state
85 CRegStdDWORD regOpts = CRegStdDWORD(L"Software\\TortoiseGit\\RevisionGraphOptions", 1);
86 // regOpts = m_Graph.m_state.GetOptions()->GetRegistryFlags();
88 // GDI+ cleanup
90 GdiplusShutdown (m_gdiPlusToken);
93 void CRevisionGraphDlg::DoDataExchange(CDataExchange* pDX)
95 CResizableStandAloneDialog::DoDataExchange(pDX);
99 BEGIN_MESSAGE_MAP(CRevisionGraphDlg, CResizableStandAloneDialog)
100 ON_WM_SIZE()
101 ON_WM_LBUTTONDOWN()
103 ON_COMMAND(ID_VIEW_ZOOMIN, OnViewZoomin)
104 ON_COMMAND(ID_VIEW_ZOOMOUT, OnViewZoomout)
105 ON_COMMAND(ID_VIEW_ZOOM100, OnViewZoom100)
106 ON_COMMAND(ID_VIEW_ZOOMHEIGHT, OnViewZoomHeight)
107 ON_COMMAND(ID_VIEW_ZOOMWIDTH, OnViewZoomWidth)
108 ON_COMMAND(ID_VIEW_ZOOMALL, OnViewZoomAll)
109 ON_CBN_SELCHANGE(ID_REVGRAPH_ZOOMCOMBO, OnChangeZoom)
110 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
111 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
112 ON_COMMAND(ID_MENUEXIT, OnMenuexit)
113 ON_COMMAND(ID_MENUHELP, OnMenuhelp)
114 ON_COMMAND(ID_FILE_SAVEGRAPHAS, OnFileSavegraphas)
115 ON_COMMAND(ID_VIEW_SHOWOVERVIEW, OnViewShowoverview)
116 ON_COMMAND(ID_VIEW_FILTER, OnViewFilter)
117 ON_COMMAND(ID_VIEW_COMPAREHEADREVISIONS, OnViewCompareheadrevisions)
118 ON_COMMAND(ID_VIEW_COMPAREREVISIONS, OnViewComparerevisions)
119 ON_COMMAND(ID_VIEW_UNIFIEDDIFF, OnViewUnifieddiff)
120 ON_COMMAND(ID_VIEW_UNIFIEDDIFFOFHEADREVISIONS, OnViewUnifieddiffofheadrevisions)
122 #if 0
123 ON_COMMAND_EX(ID_VIEW_SHOWALLREVISIONS, OnToggleOption)
124 ON_COMMAND_EX(ID_VIEW_GROUPBRANCHES, OnToggleOption)
125 ON_COMMAND_EX(ID_VIEW_TOPDOWN, OnToggleOption)
126 ON_COMMAND_EX(ID_VIEW_TOPALIGNTREES, OnToggleOption)
127 ON_COMMAND_EX(ID_VIEW_SHOWHEAD, OnToggleOption)
128 ON_COMMAND_EX(ID_VIEW_EXACTCOPYSOURCE, OnToggleOption)
129 ON_COMMAND_EX(ID_VIEW_FOLDTAGS, OnToggleOption)
130 ON_COMMAND_EX(ID_VIEW_REDUCECROSSLINES, OnToggleOption)
131 ON_COMMAND_EX(ID_VIEW_REMOVEDELETEDONES, OnToggleOption)
132 ON_COMMAND_EX(ID_VIEW_SHOWWCREV, OnToggleReloadOption)
133 ON_COMMAND_EX(ID_VIEW_REMOVEUNCHANGEDBRANCHES, OnToggleOption)
134 ON_COMMAND_EX(ID_VIEW_REMOVETAGS, OnToggleOption)
135 ON_COMMAND_EX(ID_VIEW_SHOWWCMODIFICATION, OnToggleReloadOption)
136 ON_COMMAND_EX(ID_VIEW_SHOWDIFFPATHS, OnToggleOption)
137 ON_COMMAND_EX(ID_VIEW_SHOWTREESTRIPES, OnToggleRedrawOption)
138 #endif
139 ON_WM_WINDOWPOSCHANGING()
141 END_MESSAGE_MAP()
143 BOOL CRevisionGraphDlg::InitializeToolbar()
145 // set up the toolbar
146 // add the tool bar to the dialog
147 m_ToolBar.CreateEx(this, TBSTYLE_FLAT | TBSTYLE_WRAPABLE | TBSTYLE_TRANSPARENT | CBRS_SIZE_DYNAMIC);
149 // LoadToolBar() asserts in debug mode because the bitmap
150 // fails to load. That's not a problem because we load the bitmap
151 // further down manually.
152 // but the assertion is ugly, so we load the button resource here
153 // manually as well and call SetButtons().
154 HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(IDR_REVGRAPHBAR), RT_TOOLBAR);
155 HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(IDR_REVGRAPHBAR), RT_TOOLBAR);
156 if (!hRsrc)
157 return FALSE;
159 HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
160 if (!hGlobal)
161 return FALSE;
163 auto pData = reinterpret_cast<CToolBarData*>(LockResource(hGlobal));
164 if (!pData)
165 return FALSE;
166 ASSERT(pData->wVersion == 1);
168 auto pItems = std::make_unique<UINT[]>(pData->wItemCount);
169 for (int i = 0; i < pData->wItemCount; ++i)
170 pItems[i] = pData->items()[i];
171 m_ToolBar.SetButtons(pItems.get(), pData->wItemCount);
173 UnlockResource(hGlobal);
174 FreeResource(hGlobal);
176 m_ToolBar.ShowWindow(SW_SHOW);
177 m_ToolBar.SetBarStyle(CBRS_ALIGN_TOP | CBRS_TOOLTIPS | CBRS_FLYBY);
179 // toolbars aren't true-color without some tweaking:
181 CImageList cImageList;
182 CBitmap cBitmap;
183 BITMAP bmBitmap;
185 // load the toolbar with the dimensions of the bitmap itself
186 cBitmap.Attach(LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_REVGRAPHBAR),
187 IMAGE_BITMAP, 0, 0,
188 LR_DEFAULTSIZE | LR_CREATEDIBSECTION));
189 cBitmap.GetBitmap(&bmBitmap);
190 cBitmap.DeleteObject();
191 // now load the toolbar again, but this time with the dpi-scaled dimensions
192 // note: we could just load it once and then resize the bitmap, but
193 // that's not faster. So loading it again is what we do.
194 cBitmap.Attach(LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_REVGRAPHBAR),
195 IMAGE_BITMAP,
196 CDPIAware::Instance().ScaleX(bmBitmap.bmWidth),
197 CDPIAware::Instance().ScaleY(bmBitmap.bmHeight),
198 LR_CREATEDIBSECTION));
199 cBitmap.GetBitmap(&bmBitmap);
202 CSize cSize(bmBitmap.bmWidth, bmBitmap.bmHeight);
203 int nNbBtn = cSize.cx / CDPIAware::Instance().ScaleX(20);
204 RGBTRIPLE * rgb = (RGBTRIPLE*)(bmBitmap.bmBits);
205 COLORREF rgbMask = RGB(rgb[0].rgbtRed, rgb[0].rgbtGreen, rgb[0].rgbtBlue);
207 cImageList.Create(CDPIAware::Instance().ScaleX(20), cSize.cy, ILC_COLOR32 | ILC_MASK, nNbBtn, 0);
208 cImageList.Add(&cBitmap, rgbMask);
209 // set the sizes of the button and images:
210 // note: buttonX must be 7 pixels more than imageX, and buttonY must be 6 pixels more than imageY.
211 // See the source of SetSizes().
212 m_ToolBar.SetSizes(CSize(CDPIAware::Instance().ScaleX(27), CDPIAware::Instance().ScaleY(26)),
213 CSize(CDPIAware::Instance().ScaleX(20), CDPIAware::Instance().ScaleY(20)));
214 m_ToolBar.SendMessage(TB_SETIMAGELIST, 0, (LPARAM)cImageList.m_hImageList);
215 cImageList.Detach();
216 cBitmap.Detach();
219 RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
221 #define SNAP_WIDTH CDPIAware::Instance().ScaleX(60) //the width of the combo box
222 // set up the ComboBox control as a snap mode select box
223 // First get the index of the placeholders position in the toolbar
224 int zoomComboIndex = 0;
225 while (m_ToolBar.GetItemID(zoomComboIndex) != ID_REVGRAPH_ZOOMCOMBO) ++zoomComboIndex;
227 // next convert that button to a separator and get its position
228 m_ToolBar.SetButtonInfo(zoomComboIndex, ID_REVGRAPH_ZOOMCOMBO, TBBS_SEPARATOR,
229 SNAP_WIDTH);
230 RECT rect;
231 m_ToolBar.GetItemRect(zoomComboIndex, &rect);
233 // expand the rectangle to allow the combo box room to drop down
234 rect.top += CDPIAware::Instance().ScaleY(3);
235 rect.bottom += CDPIAware::Instance().ScaleY(200);
237 // then create the combo box and show it
238 if (!m_ToolBar.m_ZoomCombo.CreateEx(WS_EX_RIGHT, WS_CHILD|WS_VISIBLE|CBS_AUTOHSCROLL|CBS_DROPDOWN,
239 rect, &m_ToolBar, ID_REVGRAPH_ZOOMCOMBO))
241 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Failed to create combo-box\n");
242 return FALSE;
244 m_ToolBar.m_ZoomCombo.ShowWindow(SW_SHOW);
246 // fill the combo box
248 TCHAR* texts[] = { L"5%"
249 , L"10%"
250 , L"20%"
251 , L"40%"
252 , L"50%"
253 , L"75%"
254 , L"100%"
255 , L"200%"
256 , nullptr};
258 COMBOBOXEXITEM cbei = { 0 };
259 cbei.mask = CBEIF_TEXT;
261 for (TCHAR** text = texts; *text; ++text)
263 cbei.pszText = *text;
264 m_ToolBar.m_ZoomCombo.InsertItem(&cbei);
267 m_ToolBar.m_ZoomCombo.SetCurSel(1);
269 UpdateOptionAvailability();
271 return TRUE;
274 BOOL CRevisionGraphDlg::OnInitDialog()
276 CResizableStandAloneDialog::OnInitDialog();
277 CAppUtils::MarkWindowAsUnpinnable(m_hWnd);
279 EnableToolTips();
281 CString sWindowTitle;
282 GetWindowText(sWindowTitle);
283 CAppUtils::SetWindowTitle(m_hWnd, g_Git.m_CurrentDir, sWindowTitle);
286 // set up the status bar
287 m_StatusBar.Create(WS_CHILD|WS_VISIBLE|SBT_OWNERDRAW,
288 CRect(0,0,0,0), this, 1);
289 int strPartDim[2]= {120, -1};
290 m_StatusBar.SetParts(2, strPartDim);
292 if (InitializeToolbar() != TRUE)
293 return FALSE;
295 m_pTaskbarList.Release();
296 if (FAILED(m_pTaskbarList.CoCreateInstance(CLSID_TaskbarList)))
297 m_pTaskbarList = nullptr;
299 // CSyncPointer<CAllRevisionGraphOptions>
300 // options (m_Graph.m_state.GetOptions());
302 // for (size_t i = 0; i < options->count(); ++i)
303 // if ((*options)[i]->CommandID() != 0)
304 // SetOption ((*options)[i]->CommandID());
306 #if 0
307 CMenu * pMenu = GetMenu();
308 if (pMenu)
310 CRegDWORD reg(L"Software\\TortoiseGit\\ShowRevGraphOverview", FALSE);
311 m_Graph.SetShowOverview ((DWORD)reg != FALSE);
312 pMenu->CheckMenuItem(ID_VIEW_SHOWOVERVIEW, MF_BYCOMMAND | (DWORD(reg) ? MF_CHECKED : 0));
313 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(ID_VIEW_SHOWOVERVIEW);
314 m_ToolBar.GetToolBarCtrl().SetState(ID_VIEW_SHOWOVERVIEW, tbstate | (DWORD(reg) ? TBSTATE_CHECKED : 0));
316 #endif
318 // m_hAccel = LoadAccelerators(AfxGetResourceHandle(),MAKEINTRESOURCE(IDR_ACC_REVISIONGRAPH));
321 CRect graphrect = GetGraphRect();
322 m_Graph.Init(this, &graphrect);
323 m_Graph.SetOwner(this);
324 m_Graph.UpdateWindow();
325 DoZoom (DEFAULT_ZOOM);
327 // begin background operation
328 StartWorkerThread();
330 EnableSaveRestore(L"RevisionGraphDlg");
331 // if (GetExplorerHWND())
332 // CenterWindow(CWnd::FromHandle(GetExplorerHWND()));
334 return TRUE; // return TRUE unless you set the focus to a control
337 bool CRevisionGraphDlg::UpdateData()
339 CoInitialize(nullptr);
341 if (!m_Graph.FetchRevisionData (m_Graph.m_sPath, nullptr, m_pTaskbarList, m_hWnd))
343 // only show the error dialog if we're not in hidden mode
344 //if (m_bVisible)
346 // TGitMessageBox( m_hWnd
347 // , // m_Graph.m_state.GetLastErrorMessage()
348 // , L"TortoiseGit"
349 // , MB_ICONERROR);
353 #if 0
354 if (m_bFetchLogs)
356 CProgressDlg progress;
357 progress.SetTitle(IDS_REVGRAPH_PROGTITLE);
358 progress.SetCancelMsg(IDS_REVGRAPH_PROGCANCEL);
359 progress.SetTime();
360 progress.SetProgress(0, 100);
361 if (m_pTaskbarList)
363 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NORMAL);
364 m_pTaskbarList->SetProgressValue(m_hWnd, 0, 100);
367 svn_revnum_t pegRev = m_Graph.m_pegRev.IsNumber()
368 ? (svn_revnum_t)m_Graph.m_pegRev
369 : (svn_revnum_t)-1;
371 if (!m_Graph.FetchRevisionData (m_Graph.m_sPath, pegRev, &progress, m_pTaskbarList, m_hWnd))
373 // only show the error dialog if we're not in hidden mode
374 if (m_bVisible)
376 TSVNMessageBox( m_hWnd
377 , m_Graph.m_state.GetLastErrorMessage()
378 , L"TortoiseGit"
379 , MB_ICONERROR);
383 progress.Stop();
384 if (m_pTaskbarList)
386 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NOPROGRESS);
389 m_bFetchLogs = false; // we've got the logs, no need to fetch them a second time
392 // standard plus user settings
395 if (m_Graph.AnalyzeRevisionData())
397 UpdateStatusBar();
398 UpdateOptionAvailability();
400 #endif
402 CoUninitialize();
403 m_Graph.PostMessage (CRevisionGraphWnd::WM_WORKERTHREADDONE, 0, 0);
405 return true;
408 void CRevisionGraphDlg::OnSize(UINT nType, int cx, int cy)
410 __super::OnSize(nType, cx, cy);
411 CRect rect;
412 GetClientRect(&rect);
413 if (IsWindow(m_ToolBar))
415 RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
417 if (IsWindow(m_StatusBar))
419 CRect statusbarrect;
420 m_StatusBar.GetClientRect(&statusbarrect);
421 statusbarrect.top = rect.bottom - statusbarrect.top + statusbarrect.bottom;
422 m_StatusBar.MoveWindow(&statusbarrect);
424 if (IsWindow(m_Graph))
426 m_Graph.MoveWindow (GetGraphRect());
430 BOOL CRevisionGraphDlg::PreTranslateMessage(MSG* pMsg)
432 #define SCROLL_STEP 20
433 if (pMsg->message == WM_KEYDOWN)
435 int pos = 0;
436 switch (pMsg->wParam)
438 case VK_UP:
439 pos = m_Graph.GetScrollPos(SB_VERT);
440 m_Graph.SetScrollPos(SB_VERT, pos - SCROLL_STEP);
441 m_Graph.Invalidate();
442 break;
443 case VK_DOWN:
444 pos = m_Graph.GetScrollPos(SB_VERT);
445 m_Graph.SetScrollPos(SB_VERT, pos + SCROLL_STEP);
446 m_Graph.Invalidate();
447 break;
448 case VK_LEFT:
449 pos = m_Graph.GetScrollPos(SB_HORZ);
450 m_Graph.SetScrollPos(SB_HORZ, pos - SCROLL_STEP);
451 m_Graph.Invalidate();
452 break;
453 case VK_RIGHT:
454 pos = m_Graph.GetScrollPos(SB_HORZ);
455 m_Graph.SetScrollPos(SB_HORZ, pos + SCROLL_STEP);
456 m_Graph.Invalidate();
457 break;
458 case VK_PRIOR:
459 pos = m_Graph.GetScrollPos(SB_VERT);
460 m_Graph.SetScrollPos(SB_VERT, pos - GetGraphRect().Height() / 2);
461 m_Graph.Invalidate();
462 break;
463 case VK_NEXT:
464 pos = m_Graph.GetScrollPos(SB_VERT);
465 m_Graph.SetScrollPos(SB_VERT, pos + GetGraphRect().Height() / 2);
466 m_Graph.Invalidate();
467 break;
468 case VK_F5:
469 UpdateFullHistory();
470 break;
473 if ((m_hAccel)&&(pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST))
475 if (pMsg->wParam == VK_ESCAPE)
476 if (m_Graph.CancelMouseZoom())
477 return TRUE;
478 return TranslateAccelerator(m_hWnd,m_hAccel,pMsg);
480 return __super::PreTranslateMessage(pMsg);
483 void CRevisionGraphDlg::DoZoom (float zoom)
485 m_fZoomFactor = zoom;
486 m_Graph.DoZoom (zoom);
487 UpdateZoomBox();
490 void CRevisionGraphDlg::OnViewZoomin()
492 DoZoom (min (MAX_ZOOM, m_fZoomFactor / ZOOM_STEP));
495 void CRevisionGraphDlg::OnViewZoomout()
497 DoZoom (max (MIN_ZOOM, m_fZoomFactor * ZOOM_STEP));
500 void CRevisionGraphDlg::OnViewZoom100()
502 DoZoom (DEFAULT_ZOOM);
505 void CRevisionGraphDlg::OnViewZoomHeight()
507 CRect graphRect = m_Graph.GetGraphRect();
508 CRect windowRect = m_Graph.GetWindowRect();
510 float horzfact = (windowRect.Width() - 4.0f)/(4.0f + graphRect.Width());
511 float vertfact = (windowRect.Height() - 4.0f)/(4.0f + graphRect.Height());
512 if ((horzfact < vertfact) && (horzfact < MAX_ZOOM))
513 vertfact = (windowRect.Height() - CDPIAware::Instance().ScaleY(20)) / (4.0f + graphRect.Height());
515 DoZoom (min (MAX_ZOOM, vertfact));
518 void CRevisionGraphDlg::OnViewZoomWidth()
520 // zoom the graph so that it is completely visible in the window
521 CRect graphRect = m_Graph.GetGraphRect();
522 CRect windowRect = m_Graph.GetWindowRect();
524 float horzfact = (windowRect.Width() - 4.0f)/(4.0f + graphRect.Width());
525 float vertfact = (windowRect.Height() - 4.0f)/(4.0f + graphRect.Height());
526 if ((vertfact < horzfact) && (vertfact < MAX_ZOOM))
527 horzfact = (windowRect.Width() - CDPIAware::Instance().ScaleX(20)) / (4.0f + graphRect.Width());
529 DoZoom (min (MAX_ZOOM, horzfact));
532 void CRevisionGraphDlg::OnViewZoomAll()
534 // zoom the graph so that it is completely visible in the window
535 CRect graphRect = m_Graph.GetGraphRect();
536 CRect windowRect = m_Graph.GetWindowRect();
538 float horzfact = (windowRect.Width() - 4.0f)/(4.0f + graphRect.Width());
539 float vertfact = (windowRect.Height() - 4.0f)/(4.0f + graphRect.Height());
541 DoZoom (min (MAX_ZOOM, min(horzfact, vertfact)));
544 void CRevisionGraphDlg::OnMenuexit()
546 if (!m_Graph.IsUpdateJobRunning())
547 EndDialog(IDOK);
550 void CRevisionGraphDlg::OnMenuhelp()
552 OnHelp();
555 void CRevisionGraphDlg::OnViewCompareheadrevisions()
557 m_Graph.CompareRevs(L"HEAD");
560 void CRevisionGraphDlg::OnViewComparerevisions()
562 m_Graph.CompareRevs(false);
565 void CRevisionGraphDlg::OnViewUnifieddiff()
567 m_Graph.UnifiedDiffRevs(false);
570 void CRevisionGraphDlg::OnViewUnifieddiffofheadrevisions()
572 m_Graph.UnifiedDiffRevs(true);
575 void CRevisionGraphDlg::UpdateFullHistory()
577 m_Graph.SetDlgTitle (false);
578 m_bFetchLogs = true;
579 Invalidate();
580 StartWorkerThread();
582 #if 0
583 m_Graph.SetDlgTitle (false);
585 SVN svn;
586 LogCache::CRepositoryInfo& cachedProperties
587 = svn.GetLogCachePool()->GetRepositoryInfo();
588 CString root = m_Graph.m_state.GetRepositoryRoot();
589 CString uuid = m_Graph.m_state.GetRepositoryUUID();
591 cachedProperties.ResetHeadRevision (uuid, root);
593 m_bFetchLogs = true;
594 StartWorkerThread();
595 #endif
598 void CRevisionGraphDlg::SetOption (UINT /*controlID*/)
600 #if 0
601 CMenu * pMenu = GetMenu();
602 if (!pMenu)
603 return;
605 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(controlID);
606 if (tbstate != -1)
608 if (m_Graph.m_state.GetOptions()->IsSelected (controlID))
610 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_CHECKED);
611 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate | TBSTATE_CHECKED);
613 else
615 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_UNCHECKED);
616 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate & (~TBSTATE_CHECKED));
619 #endif
622 BOOL CRevisionGraphDlg::ToggleOption (UINT controlID)
624 // check request for validity
626 if (m_Graph.IsUpdateJobRunning())
628 // restore previous state
630 int state = m_ToolBar.GetToolBarCtrl().GetState(controlID);
631 if (state & TBSTATE_CHECKED)
632 state &= ~TBSTATE_CHECKED;
633 else
634 state |= TBSTATE_CHECKED;
635 m_ToolBar.GetToolBarCtrl().SetState (controlID, state);
637 return FALSE;
640 CMenu * pMenu = GetMenu();
641 if (!pMenu)
642 return FALSE;
644 // actually toggle the option
646 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(controlID);
647 UINT state = pMenu->GetMenuState(controlID, MF_BYCOMMAND);
648 if (state & MF_CHECKED)
650 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_UNCHECKED);
651 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate & (~TBSTATE_CHECKED));
653 else
655 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_CHECKED);
656 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate | TBSTATE_CHECKED);
659 // CSyncPointer<CAllRevisionGraphOptions>
660 // options (m_Graph.m_state.GetOptions());
661 // if (((state & MF_CHECKED) != 0) == options->IsSelected (controlID))
662 // options->ToggleSelection (controlID);
664 return TRUE;
667 BOOL CRevisionGraphDlg::OnToggleOption (UINT controlID)
669 if (!ToggleOption (controlID))
670 return FALSE;
672 // re-process the data
674 StartWorkerThread();
676 return TRUE;
679 BOOL CRevisionGraphDlg::OnToggleReloadOption (UINT controlID)
681 #if 0
682 if (!m_Graph.m_state.GetFetchedWCState())
683 m_bFetchLogs = true;
684 #endif
685 return OnToggleOption (controlID);
688 BOOL CRevisionGraphDlg::OnToggleRedrawOption (UINT controlID)
690 if (!ToggleOption (controlID))
691 return FALSE;
693 m_Graph.BuildPreview();
694 Invalidate();
696 return TRUE;
699 void CRevisionGraphDlg::StartWorkerThread()
701 if (!m_Graph.IsUpdateJobRunning())
702 m_Graph.updateJob = std::make_unique<CFuture<bool>>(this, &CRevisionGraphDlg::UpdateData);
705 void CRevisionGraphDlg::OnCancel()
707 if (!m_Graph.IsUpdateJobRunning())
708 __super::OnCancel();
711 void CRevisionGraphDlg::OnOK()
713 OnChangeZoom();
716 void CRevisionGraphDlg::OnFileSavegraphas()
718 CString tempfile;
719 int filterindex = 0;
720 if (CAppUtils::FileOpenSave(tempfile, &filterindex, IDS_REVGRAPH_SAVEPIC, IDS_PICTUREFILEFILTER, false, m_hWnd))
722 // if the user doesn't specify a file extension, default to
723 // svg and add that extension to the filename. But only if the
724 // user chose the 'pictures' filter. The filename isn't changed
725 // if the 'All files' filter was chosen.
726 CString extension;
727 int dotPos = tempfile.ReverseFind('.');
728 int slashPos = tempfile.ReverseFind('\\');
729 if (dotPos > slashPos)
730 extension = tempfile.Mid(dotPos);
731 if ((filterindex == 1)&&(extension.IsEmpty()))
733 extension = L".svg";
734 tempfile += extension;
736 if ((filterindex == 2)&&(extension.IsEmpty()))
738 extension = L".gv";
739 tempfile += extension;
741 m_Graph.SaveGraphAs(tempfile);
745 CRect CRevisionGraphDlg::GetGraphRect()
747 CRect rect;
748 GetClientRect(&rect);
750 CRect statusbarrect;
751 m_StatusBar.GetClientRect(&statusbarrect);
752 rect.bottom -= statusbarrect.Height();
754 CRect toolbarrect;
755 m_ToolBar.GetClientRect(&toolbarrect);
756 rect.top += toolbarrect.Height();
758 return rect;
761 void CRevisionGraphDlg::UpdateStatusBar()
763 // CString sFormat;
764 // sFormat.Format(IDS_REVGRAPH_STATUSBARURL, (LPCTSTR)m_Graph.m_sPath);
765 // m_StatusBar.SetText(sFormat,1,0);
766 // sFormat.Format(IDS_REVGRAPH_STATUSBARNUMNODES, m_Graph.m_state.GetNodeCount());
767 // m_StatusBar.SetText(sFormat,0,0);
770 void CRevisionGraphDlg::OnChangeZoom()
772 if (!IsWindow(m_Graph.GetSafeHwnd()))
773 return;
774 CString strItem;
775 CComboBoxEx* pCBox = (CComboBoxEx*)m_ToolBar.GetDlgItem(ID_REVGRAPH_ZOOMCOMBO);
776 pCBox->GetWindowText(strItem);
777 if (strItem.IsEmpty())
778 return;
780 DoZoom ((float)(_wtof(strItem) / 100.0));
783 void CRevisionGraphDlg::UpdateZoomBox()
785 CString strText;
786 CString strItem;
787 CComboBoxEx* pCBox = (CComboBoxEx*)m_ToolBar.GetDlgItem(ID_REVGRAPH_ZOOMCOMBO);
788 pCBox->GetWindowText(strItem);
789 strText.Format(L"%.0f%%", (m_fZoomFactor * 100.0));
790 if (strText.Compare(strItem) != 0)
791 pCBox->SetWindowText(strText);
794 BOOL CRevisionGraphDlg::OnToolTipNotify(UINT /*id*/, NMHDR *pNMHDR, LRESULT *pResult)
796 // need to handle both ANSI and UNICODE versions of the message
797 TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
798 TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
799 CString strTipText;
801 UINT_PTR nID = pNMHDR->idFrom;
803 if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
804 pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
806 // idFrom is actually the HWND of the tool
807 nID = ::GetDlgCtrlID((HWND)nID);
810 if (nID != 0) // will be zero on a separator
811 strTipText.LoadString (static_cast<UINT>(nID));
813 *pResult = 0;
814 if (strTipText.IsEmpty())
815 return TRUE;
817 if (strTipText.GetLength() >= MAX_TT_LENGTH)
818 strTipText = strTipText.Left(MAX_TT_LENGTH);
820 if (pNMHDR->code == TTN_NEEDTEXTA)
822 ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 600);
823 pTTTA->lpszText = m_szTip;
824 WideCharToMultiByte(CP_ACP, 0, strTipText, -1, m_szTip, strTipText.GetLength()+1, 0, 0);
826 else
828 ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 600);
829 lstrcpyn(m_wszTip, strTipText, strTipText.GetLength()+1);
830 pTTTW->lpszText = m_wszTip;
832 // bring the tooltip window above other pop up windows
833 ::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,
834 SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER);
835 return TRUE; // message was handled
838 void CRevisionGraphDlg::OnViewFilter()
840 /* CSyncPointer<CAllRevisionGraphOptions>
841 options (m_Graph.m_state.GetOptions());
843 CRevisionInRange* revisionRange = options->GetOption<CRevisionInRange>();
844 svn_revnum_t head = m_Graph.m_state.GetHeadRevision();
845 svn_revnum_t lowerLimit = revisionRange->GetLowerLimit();
846 svn_revnum_t upperLimit = revisionRange->GetUpperLimit();
848 CRemovePathsBySubString* pathFilter = options->GetOption<CRemovePathsBySubString>();
850 CRevGraphFilterDlg dlg;
852 dlg.m_bCurrentBranch = this->m_Graph.m_bCurrentBranch;
853 dlg.m_bLocalBranches = m_Graph.m_bLocalBranches;
854 dlg.SetRevisionRange(m_Graph.m_FromRev, m_Graph.m_ToRev);
856 if (dlg.DoModal()==IDOK)
858 // user pressed OK to dismiss the dialog, which means
859 // we have to accept the new filter settings and apply them
861 dlg.GetRevisionRange(m_Graph.m_FromRev, m_Graph.m_ToRev);
862 // update menu & toolbar
864 this->m_Graph.m_bCurrentBranch = dlg.m_bCurrentBranch;
865 m_Graph.m_bLocalBranches = dlg.m_bLocalBranches;
867 CMenu * pMenu = GetMenu();
868 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(ID_VIEW_FILTER);
869 if (m_Graph.m_bCurrentBranch || m_Graph.m_bLocalBranches || !m_Graph.m_FromRev.IsEmpty() || !m_Graph.m_ToRev.IsEmpty())
871 if (pMenu)
872 pMenu->CheckMenuItem(ID_VIEW_FILTER, MF_BYCOMMAND | MF_CHECKED);
873 m_ToolBar.GetToolBarCtrl().SetState(ID_VIEW_FILTER, tbstate | TBSTATE_CHECKED);
875 else
877 if (pMenu)
878 pMenu->CheckMenuItem(ID_VIEW_FILTER, MF_BYCOMMAND | MF_UNCHECKED);
879 m_ToolBar.GetToolBarCtrl().SetState(ID_VIEW_FILTER, tbstate & (~TBSTATE_CHECKED));
882 // re-run query
884 StartWorkerThread();
888 void CRevisionGraphDlg::OnViewShowoverview()
890 CMenu * pMenu = GetMenu();
891 if (!pMenu)
892 return;
893 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(ID_VIEW_SHOWOVERVIEW);
894 UINT state = pMenu->GetMenuState(ID_VIEW_SHOWOVERVIEW, MF_BYCOMMAND);
895 if (state & MF_CHECKED)
897 pMenu->CheckMenuItem(ID_VIEW_SHOWOVERVIEW, MF_BYCOMMAND | MF_UNCHECKED);
898 m_ToolBar.GetToolBarCtrl().SetState(ID_VIEW_SHOWOVERVIEW, tbstate & (~TBSTATE_CHECKED));
899 m_Graph.SetShowOverview (false);
901 else
903 pMenu->CheckMenuItem(ID_VIEW_SHOWOVERVIEW, MF_BYCOMMAND | MF_CHECKED);
904 m_ToolBar.GetToolBarCtrl().SetState(ID_VIEW_SHOWOVERVIEW, tbstate | TBSTATE_CHECKED);
905 m_Graph.SetShowOverview (true);
908 CRegDWORD reg(L"Software\\TortoiseGit\\ShowRevGraphOverview", FALSE);
909 reg = m_Graph.GetShowOverview();
910 m_Graph.Invalidate(FALSE);
913 void CRevisionGraphDlg::UpdateOptionAvailability (UINT id, bool available)
915 CMenu * pMenu = GetMenu();
916 if (!pMenu)
917 return;
919 pMenu->EnableMenuItem (id, available ? MF_ENABLED : MF_GRAYED);
921 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(id);
922 int newTbstate = available
923 ? tbstate | TBSTATE_ENABLED
924 : tbstate & ~TBSTATE_ENABLED;
926 if (tbstate != newTbstate)
927 m_ToolBar.GetToolBarCtrl().SetState(id, newTbstate);
930 void CRevisionGraphDlg::UpdateOptionAvailability()
932 #if 0
933 bool multipleTrees = m_Graph.m_state.GetTreeCount() > 1;
934 bool isWCPath = !CTGitPath (m_Graph.m_sPath).IsUrl();
936 UpdateOptionAvailability (ID_VIEW_TOPALIGNTREES, multipleTrees);
937 UpdateOptionAvailability (ID_VIEW_SHOWTREESTRIPES, multipleTrees);
938 UpdateOptionAvailability (ID_VIEW_SHOWWCREV, isWCPath);
939 UpdateOptionAvailability (ID_VIEW_SHOWWCMODIFICATION, isWCPath);
940 #endif
945 void CRevisionGraphDlg::OnWindowPosChanging(WINDOWPOS* lpwndpos)
947 if (!m_bVisible)
948 lpwndpos->flags &= ~SWP_SHOWWINDOW;
949 CResizableStandAloneDialog::OnWindowPosChanging(lpwndpos);