1 // TortoiseSVN - a Windows shell extension for easy version control
\r
3 // Copyright (C) 2003-2008 - TortoiseSVN
\r
5 // This program is free software; you can redistribute it and/or
\r
6 // modify it under the terms of the GNU General Public License
\r
7 // as published by the Free Software Foundation; either version 2
\r
8 // of the License, or (at your option) any later version.
\r
10 // This program is distributed in the hope that it will be useful,
\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 // GNU General Public License for more details.
\r
15 // You should have received a copy of the GNU General Public License
\r
16 // along with this program; if not, write to the Free Software Foundation,
\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
20 #include "TortoiseProc.h"
\r
21 #include "Revisiongraphdlg.h"
\r
22 #include "MessageBox.h"
\r
24 #include "AppUtils.h"
\r
25 #include "StringUtils.h"
\r
26 #include "TempFile.h"
\r
27 #include "UnicodeUtils.h"
\r
28 #include "TSVNPath.h"
\r
29 #include "SVNInfo.h"
\r
30 #include "SVNDiff.h"
\r
31 #include "RevGraphFilterDlg.h"
\r
32 #include ".\revisiongraphdlg.h"
\r
33 #include "RepositoryInfo.h"
\r
34 #include "RevisionInRange.h"
\r
35 #include "RemovePathsBySubString.h"
\r
38 #define new DEBUG_NEW
\r
40 static char THIS_FILE[] = __FILE__;
\r
43 using namespace Gdiplus;
\r
45 IMPLEMENT_DYNAMIC(CRevisionGraphDlg, CResizableStandAloneDialog)
\r
46 CRevisionGraphDlg::CRevisionGraphDlg(CWnd* pParent /*=NULL*/)
\r
47 : CResizableStandAloneDialog(CRevisionGraphDlg::IDD, pParent)
\r
49 , m_bFetchLogs(true)
\r
50 , m_fZoomFactor(0.5)
\r
52 // GDI+ initialization
\r
54 GdiplusStartupInput input;
\r
55 GdiplusStartup (&m_gdiPlusToken, &input, NULL);
\r
57 // restore option state
\r
59 DWORD dwOpts = CRegStdWORD(_T("Software\\TortoiseSVN\\RevisionGraphOptions"), 0x211);
\r
60 m_options.SetRegistryFlags (dwOpts, 0x3ff);
\r
63 CRevisionGraphDlg::~CRevisionGraphDlg()
\r
65 // save option state
\r
67 CRegStdWORD regOpts = CRegStdWORD(_T("Software\\TortoiseSVN\\RevisionGraphOptions"), 1);
\r
68 regOpts = m_options.GetRegistryFlags();
\r
72 GdiplusShutdown (m_gdiPlusToken);
\r
75 void CRevisionGraphDlg::DoDataExchange(CDataExchange* pDX)
\r
77 CResizableStandAloneDialog::DoDataExchange(pDX);
\r
81 BEGIN_MESSAGE_MAP(CRevisionGraphDlg, CResizableStandAloneDialog)
\r
84 ON_COMMAND(ID_VIEW_ZOOMIN, OnViewZoomin)
\r
85 ON_COMMAND(ID_VIEW_ZOOMOUT, OnViewZoomout)
\r
86 ON_COMMAND(ID_VIEW_ZOOM100, OnViewZoom100)
\r
87 ON_COMMAND(ID_VIEW_ZOOMALL, OnViewZoomAll)
\r
88 ON_COMMAND(ID_MENUEXIT, OnMenuexit)
\r
89 ON_COMMAND(ID_MENUHELP, OnMenuhelp)
\r
90 ON_COMMAND(ID_VIEW_COMPAREHEADREVISIONS, OnViewCompareheadrevisions)
\r
91 ON_COMMAND(ID_VIEW_COMPAREREVISIONS, OnViewComparerevisions)
\r
92 ON_COMMAND(ID_VIEW_UNIFIEDDIFF, OnViewUnifieddiff)
\r
93 ON_COMMAND(ID_VIEW_UNIFIEDDIFFOFHEADREVISIONS, OnViewUnifieddiffofheadrevisions)
\r
94 ON_COMMAND(ID_FILE_SAVEGRAPHAS, &CRevisionGraphDlg::OnFileSavegraphas)
\r
95 ON_COMMAND_EX(ID_VIEW_SHOWALLREVISIONS, &CRevisionGraphDlg::OnToggleOption)
\r
96 ON_COMMAND_EX(ID_VIEW_GROUPBRANCHES, &CRevisionGraphDlg::OnToggleOption)
\r
97 ON_COMMAND_EX(ID_VIEW_TOPDOWN, &CRevisionGraphDlg::OnToggleOption)
\r
98 ON_COMMAND_EX(ID_VIEW_SHOWHEAD, &CRevisionGraphDlg::OnToggleOption)
\r
99 ON_COMMAND_EX(ID_VIEW_EXACTCOPYSOURCE, &CRevisionGraphDlg::OnToggleOption)
\r
100 ON_COMMAND_EX(ID_VIEW_FOLDTAGS, &CRevisionGraphDlg::OnToggleOption)
\r
101 ON_COMMAND_EX(ID_VIEW_REDUCECROSSLINES, &CRevisionGraphDlg::OnToggleOption)
\r
102 ON_COMMAND_EX(ID_VIEW_REMOVEDELETEDONES, &CRevisionGraphDlg::OnToggleOption)
\r
103 ON_COMMAND_EX(ID_VIEW_SHOWWCREV, &CRevisionGraphDlg::OnToggleOption)
\r
104 ON_CBN_SELCHANGE(ID_REVGRAPH_ZOOMCOMBO, OnChangeZoom)
\r
105 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
\r
106 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
\r
107 ON_COMMAND(ID_VIEW_FILTER, &CRevisionGraphDlg::OnViewFilter)
\r
108 ON_COMMAND(ID_VIEW_SHOWOVERVIEW, &CRevisionGraphDlg::OnViewShowoverview)
\r
111 BOOL CRevisionGraphDlg::InitializeToolbar()
\r
113 // set up the toolbar
\r
114 // add the tool bar to the dialog
\r
115 m_ToolBar.CreateEx(this, TBSTYLE_FLAT | TBSTYLE_WRAPABLE | TBSTYLE_TRANSPARENT | CBRS_SIZE_DYNAMIC);
\r
116 m_ToolBar.LoadToolBar(IDR_REVGRAPHBAR);
\r
117 m_ToolBar.ShowWindow(SW_SHOW);
\r
118 m_ToolBar.SetBarStyle(CBRS_ALIGN_TOP | CBRS_TOOLTIPS | CBRS_FLYBY);
\r
120 // toolbars aren't true-color without some tweaking:
\r
122 CImageList cImageList;
\r
126 cBitmap.Attach(LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_REVGRAPHBAR),
\r
127 IMAGE_BITMAP, 0, 0,
\r
128 LR_DEFAULTSIZE|LR_CREATEDIBSECTION));
\r
129 cBitmap.GetBitmap(&bmBitmap);
\r
131 CSize cSize(bmBitmap.bmWidth, bmBitmap.bmHeight);
\r
132 int nNbBtn = cSize.cx/20;
\r
133 RGBTRIPLE * rgb = (RGBTRIPLE*)(bmBitmap.bmBits);
\r
134 COLORREF rgbMask = RGB(rgb[0].rgbtRed, rgb[0].rgbtGreen, rgb[0].rgbtBlue);
\r
136 cImageList.Create(20, cSize.cy, ILC_COLOR32|ILC_MASK, nNbBtn, 0);
\r
137 cImageList.Add(&cBitmap, rgbMask);
\r
138 m_ToolBar.SendMessage(TB_SETIMAGELIST, 0, (LPARAM)cImageList.m_hImageList);
\r
139 cImageList.Detach();
\r
142 RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
\r
144 #define SNAP_WIDTH 60 //the width of the combo box
\r
145 // set up the ComboBox control as a snap mode select box
\r
146 // First get the index of the placeholders position in the toolbar
\r
148 while (m_ToolBar.GetItemID(index) != ID_REVGRAPH_ZOOMCOMBO) index++;
\r
150 // next convert that button to a separator and get its position
\r
151 m_ToolBar.SetButtonInfo(index, ID_REVGRAPH_ZOOMCOMBO, TBBS_SEPARATOR,
\r
154 m_ToolBar.GetItemRect(index, &rect);
\r
156 // expand the rectangle to allow the combo box room to drop down
\r
158 rect.bottom += 200;
\r
160 // then create the combo box and show it
\r
161 if (!m_ToolBar.m_ZoomCombo.CreateEx(WS_EX_RIGHT, WS_CHILD|WS_VISIBLE|CBS_AUTOHSCROLL|CBS_DROPDOWN,
\r
162 rect, &m_ToolBar, ID_REVGRAPH_ZOOMCOMBO))
\r
164 TRACE0("Failed to create combo-box\n");
\r
167 m_ToolBar.m_ZoomCombo.ShowWindow(SW_SHOW);
\r
169 // set toolbar button styles
\r
171 UINT styles[] = { TBBS_CHECKBOX|TBBS_CHECKED
\r
175 UINT itemIDs[] = { ID_VIEW_GROUPBRANCHES
\r
176 , 0 // separate styles by "0"
\r
177 , ID_VIEW_SHOWOVERVIEW
\r
180 , ID_VIEW_EXACTCOPYSOURCE
\r
182 , ID_VIEW_REDUCECROSSLINES
\r
183 , ID_VIEW_REMOVEDELETEDONES
\r
184 , ID_VIEW_SHOWWCREV
\r
187 for (UINT* itemID = itemIDs, *style = styles; *style != 0; ++itemID)
\r
196 while (m_ToolBar.GetItemID(index) != *itemID)
\r
198 m_ToolBar.SetButtonStyle(index, m_ToolBar.GetButtonStyle(index)|*style);
\r
201 // fill the combo box
\r
203 TCHAR* texts[] = { _T("5%")
\r
213 COMBOBOXEXITEM cbei;
\r
214 SecureZeroMemory(&cbei, sizeof cbei);
\r
215 cbei.mask = CBEIF_TEXT;
\r
217 for (TCHAR** text = texts; *text != NULL; ++text)
\r
219 cbei.pszText = *text;
\r
220 m_ToolBar.m_ZoomCombo.InsertItem(&cbei);
\r
223 m_ToolBar.m_ZoomCombo.SetCurSel(1);
\r
228 BOOL CRevisionGraphDlg::OnInitDialog()
\r
230 CResizableStandAloneDialog::OnInitDialog();
\r
234 // set up the status bar
\r
235 m_StatusBar.Create(WS_CHILD|WS_VISIBLE|SBT_OWNERDRAW,
\r
236 CRect(0,0,0,0), this, 1);
\r
237 int strPartDim[2]= {120, -1};
\r
238 m_StatusBar.SetParts(2, strPartDim);
\r
240 if (InitializeToolbar() != TRUE)
\r
243 for (size_t i = 0; i < m_options.count(); ++i)
\r
244 if (m_options[i]->CommandID() != 0)
\r
245 SetOption (m_options[i]->CommandID());
\r
247 CMenu * pMenu = GetMenu();
\r
250 CRegDWORD reg = CRegDWORD(_T("Software\\TortoiseSVN\\ShowRevGraphOverview"), FALSE);
\r
251 m_Graph.SetShowOverview ((DWORD)reg != FALSE);
\r
252 pMenu->CheckMenuItem(ID_VIEW_SHOWOVERVIEW, MF_BYCOMMAND | (DWORD(reg) ? MF_CHECKED : 0));
\r
253 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(ID_VIEW_SHOWOVERVIEW);
\r
254 m_ToolBar.GetToolBarCtrl().SetState(ID_VIEW_SHOWOVERVIEW, tbstate | (DWORD(reg) ? TBSTATE_CHECKED : 0));
\r
257 m_hAccel = LoadAccelerators(AfxGetResourceHandle(),MAKEINTRESOURCE(IDR_ACC_REVISIONGRAPH));
\r
259 CRect graphrect = GetGraphRect();
\r
260 m_Graph.Init(this, &graphrect);
\r
261 m_Graph.SetOwner(this);
\r
262 m_Graph.UpdateWindow();
\r
265 EnableSaveRestore(_T("RevisionGraphDlg"));
\r
267 if (AfxBeginThread(WorkerThread, this)==NULL)
\r
269 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
\r
272 CenterWindow(CWnd::FromHandle(hWndExplorer));
\r
273 return TRUE; // return TRUE unless you set the focus to a control
\r
276 UINT CRevisionGraphDlg::WorkerThread(LPVOID pVoid)
\r
278 CRevisionGraphDlg* pDlg;
\r
279 pDlg = (CRevisionGraphDlg*)pVoid;
\r
280 InterlockedExchange(&pDlg->m_Graph.m_bThreadRunning, TRUE);
\r
281 CoInitialize(NULL);
\r
283 if (pDlg->m_bFetchLogs)
\r
285 pDlg->m_Graph.m_pProgress = new CProgressDlg();
\r
286 pDlg->m_Graph.m_pProgress->SetTitle(IDS_REVGRAPH_PROGTITLE);
\r
287 pDlg->m_Graph.m_pProgress->SetCancelMsg(IDS_REVGRAPH_PROGCANCEL);
\r
288 pDlg->m_Graph.m_pProgress->SetTime();
\r
289 pDlg->m_Graph.m_pProgress->SetProgress(0, 100);
\r
291 svn_revnum_t pegRev = pDlg->m_Graph.m_pegRev.IsNumber()
\r
292 ? (svn_revnum_t)pDlg->m_Graph.m_pegRev
\r
293 : (svn_revnum_t)-1;
\r
295 if (!pDlg->m_Graph.FetchRevisionData (pDlg->m_Graph.m_sPath, pegRev, pDlg->m_options))
\r
296 CMessageBox::Show (pDlg->m_hWnd, pDlg->m_Graph.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
\r
298 pDlg->m_Graph.m_pProgress->Stop();
\r
299 delete pDlg->m_Graph.m_pProgress;
\r
300 pDlg->m_Graph.m_pProgress = NULL;
\r
302 pDlg->m_bFetchLogs = false; // we've got the logs, no need to fetch them a second time
\r
305 // standard plus user settings
\r
307 pDlg->m_options.Prepare();
\r
308 if (pDlg->m_Graph.AnalyzeRevisionData (pDlg->m_options))
\r
309 pDlg->UpdateStatusBar();
\r
312 InterlockedExchange(&pDlg->m_Graph.m_bThreadRunning, FALSE);
\r
314 pDlg->m_Graph.SendMessage (CRevisionGraphWnd::WM_WORKERTHREADDONE, 0, 0);
\r
318 void CRevisionGraphDlg::OnSize(UINT nType, int cx, int cy)
\r
320 __super::OnSize(nType, cx, cy);
\r
322 GetClientRect(&rect);
\r
323 if (IsWindow(m_ToolBar))
\r
325 RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
\r
327 if (IsWindow(m_StatusBar))
\r
329 CRect statusbarrect;
\r
330 m_StatusBar.GetClientRect(&statusbarrect);
\r
331 statusbarrect.top = rect.bottom - statusbarrect.top + statusbarrect.bottom;
\r
332 m_StatusBar.MoveWindow(&statusbarrect);
\r
334 if (IsWindow(m_Graph))
\r
336 m_Graph.MoveWindow (GetGraphRect());
\r
340 BOOL CRevisionGraphDlg::PreTranslateMessage(MSG* pMsg)
\r
342 #define SCROLL_STEP 20
\r
343 if (pMsg->message == WM_KEYDOWN)
\r
346 switch (pMsg->wParam)
\r
349 pos = m_Graph.GetScrollPos(SB_VERT);
\r
350 m_Graph.SetScrollPos(SB_VERT, pos - SCROLL_STEP);
\r
351 m_Graph.Invalidate();
\r
354 pos = m_Graph.GetScrollPos(SB_VERT);
\r
355 m_Graph.SetScrollPos(SB_VERT, pos + SCROLL_STEP);
\r
356 m_Graph.Invalidate();
\r
359 pos = m_Graph.GetScrollPos(SB_HORZ);
\r
360 m_Graph.SetScrollPos(SB_HORZ, pos - SCROLL_STEP);
\r
361 m_Graph.Invalidate();
\r
364 pos = m_Graph.GetScrollPos(SB_HORZ);
\r
365 m_Graph.SetScrollPos(SB_HORZ, pos + SCROLL_STEP);
\r
366 m_Graph.Invalidate();
\r
369 pos = m_Graph.GetScrollPos(SB_VERT);
\r
370 m_Graph.SetScrollPos(SB_VERT, pos - GetGraphRect().Height() / 2);
\r
371 m_Graph.Invalidate();
\r
374 pos = m_Graph.GetScrollPos(SB_VERT);
\r
375 m_Graph.SetScrollPos(SB_VERT, pos + GetGraphRect().Height() / 2);
\r
376 m_Graph.Invalidate();
\r
379 m_Graph.SetDlgTitle (false);
\r
382 LogCache::CRepositoryInfo& cachedProperties
\r
383 = svn.GetLogCachePool()->GetRepositoryInfo();
\r
384 CString root = m_Graph.GetRepositoryRoot();
\r
385 CString uuid = m_Graph.GetRepositoryUUID();
\r
387 cachedProperties.ResetHeadRevision (uuid, root);
\r
389 m_bFetchLogs = true;
\r
390 StartWorkerThread();
\r
395 if ((m_hAccel)&&(pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST))
\r
397 return TranslateAccelerator(m_hWnd,m_hAccel,pMsg);
\r
399 return __super::PreTranslateMessage(pMsg);
\r
402 void CRevisionGraphDlg::DoZoom (float zoom)
\r
404 m_fZoomFactor = zoom;
\r
405 m_Graph.DoZoom (zoom);
\r
409 void CRevisionGraphDlg::OnViewZoomin()
\r
411 DoZoom (min (2.0f, m_fZoomFactor / .9f));
\r
414 void CRevisionGraphDlg::OnViewZoomout()
\r
416 DoZoom (max (0.01f, m_fZoomFactor * .9f));
\r
419 void CRevisionGraphDlg::OnViewZoom100()
\r
424 void CRevisionGraphDlg::OnViewZoomAll()
\r
426 // zoom the graph so that it is completely visible in the window
\r
427 CRect windowrect = GetGraphRect();
\r
428 CRect viewrect = m_Graph.GetViewRect();
\r
430 float horzfact = float(viewrect.Width())/float(windowrect.Width()-6);
\r
431 float vertfact = float(viewrect.Height())/float(windowrect.Height()-6);
\r
433 DoZoom (1.0f/(max (1.0f, max(horzfact, vertfact))));
\r
436 void CRevisionGraphDlg::OnMenuexit()
\r
438 if (!m_Graph.m_bThreadRunning)
\r
442 void CRevisionGraphDlg::OnMenuhelp()
\r
447 void CRevisionGraphDlg::OnViewCompareheadrevisions()
\r
449 m_Graph.CompareRevs(true);
\r
452 void CRevisionGraphDlg::OnViewComparerevisions()
\r
454 m_Graph.CompareRevs(false);
\r
457 void CRevisionGraphDlg::OnViewUnifieddiff()
\r
459 m_Graph.UnifiedDiffRevs(false);
\r
462 void CRevisionGraphDlg::OnViewUnifieddiffofheadrevisions()
\r
464 m_Graph.UnifiedDiffRevs(true);
\r
467 void CRevisionGraphDlg::SetOption (UINT controlID)
\r
469 CMenu * pMenu = GetMenu();
\r
473 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(controlID);
\r
476 if (m_options.IsSelected (controlID))
\r
478 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_CHECKED);
\r
479 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate | TBSTATE_CHECKED);
\r
483 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_UNCHECKED);
\r
484 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate & (~TBSTATE_CHECKED));
\r
489 BOOL CRevisionGraphDlg::OnToggleOption (UINT controlID)
\r
491 // check request for validity
\r
493 if (m_Graph.m_bThreadRunning)
\r
495 int state = m_ToolBar.GetToolBarCtrl().GetState(controlID);
\r
496 if (state & TBSTATE_CHECKED)
\r
497 state &= ~TBSTATE_CHECKED;
\r
499 state |= TBSTATE_CHECKED;
\r
500 m_ToolBar.GetToolBarCtrl().SetState (controlID, state);
\r
504 CMenu * pMenu = GetMenu();
\r
508 // actually toggle the option
\r
510 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(controlID);
\r
511 UINT state = pMenu->GetMenuState(controlID, MF_BYCOMMAND);
\r
512 if (state & MF_CHECKED)
\r
514 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_UNCHECKED);
\r
515 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate & (~TBSTATE_CHECKED));
\r
519 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_CHECKED);
\r
520 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate | TBSTATE_CHECKED);
\r
523 if (((state & MF_CHECKED) != 0) == m_options.IsSelected (controlID))
\r
524 m_options.ToggleSelection (controlID);
\r
526 // re-process the data
\r
528 StartWorkerThread();
\r
533 void CRevisionGraphDlg::StartWorkerThread()
\r
535 if (InterlockedExchange(&m_Graph.m_bThreadRunning, TRUE) == TRUE)
\r
538 if (AfxBeginThread(WorkerThread, this)==NULL)
\r
540 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
\r
541 InterlockedExchange(&m_Graph.m_bThreadRunning, FALSE);
\r
545 void CRevisionGraphDlg::OnCancel()
\r
547 if (!m_Graph.m_bThreadRunning)
\r
548 __super::OnCancel();
\r
551 void CRevisionGraphDlg::OnOK()
\r
556 void CRevisionGraphDlg::OnFileSavegraphas()
\r
559 int filterindex = 0;
\r
560 if (CAppUtils::FileOpenSave(tempfile, &filterindex, IDS_REVGRAPH_SAVEPIC, IDS_PICTUREFILEFILTER, false, m_hWnd))
\r
562 // if the user doesn't specify a file extension, default to
\r
563 // wmf and add that extension to the filename. But only if the
\r
564 // user chose the 'pictures' filter. The filename isn't changed
\r
565 // if the 'All files' filter was chosen.
\r
567 int dotPos = tempfile.ReverseFind('.');
\r
568 int slashPos = tempfile.ReverseFind('\\');
\r
569 if (dotPos > slashPos)
\r
570 extension = tempfile.Mid(dotPos);
\r
571 if ((filterindex == 1)&&(extension.IsEmpty()))
\r
573 extension = _T(".wmf");
\r
574 tempfile += extension;
\r
576 m_Graph.SaveGraphAs(tempfile);
\r
580 CRect CRevisionGraphDlg::GetGraphRect()
\r
583 GetClientRect(&rect);
\r
585 CRect statusbarrect;
\r
586 m_StatusBar.GetClientRect(&statusbarrect);
\r
587 rect.bottom -= statusbarrect.Height();
\r
590 m_ToolBar.GetClientRect(&toolbarrect);
\r
591 rect.top += toolbarrect.Height();
\r
596 void CRevisionGraphDlg::UpdateStatusBar()
\r
599 sFormat.Format(IDS_REVGRAPH_STATUSBARURL, (LPCTSTR)m_Graph.m_sPath);
\r
600 m_StatusBar.SetText(sFormat,1,0);
\r
601 sFormat.Format(IDS_REVGRAPH_STATUSBARNUMNODES, m_Graph.GetNodeCount());
\r
602 m_StatusBar.SetText(sFormat,0,0);
\r
605 void CRevisionGraphDlg::OnChangeZoom()
\r
607 if (!IsWindow(m_Graph.GetSafeHwnd()))
\r
611 CComboBoxEx* pCBox = (CComboBoxEx*)m_ToolBar.GetDlgItem(ID_REVGRAPH_ZOOMCOMBO);
\r
612 pCBox->GetWindowText(strItem);
\r
613 if (strItem.IsEmpty())
\r
615 ATLTRACE(_T("OnChangeZoom to %s\n"), strItem);
\r
617 DoZoom ((float)(_tstof(strItem)/100.0));
\r
620 void CRevisionGraphDlg::UpdateZoomBox()
\r
624 CComboBoxEx* pCBox = (CComboBoxEx*)m_ToolBar.GetDlgItem(ID_REVGRAPH_ZOOMCOMBO);
\r
625 pCBox->GetWindowText(strItem);
\r
626 strText.Format(_T("%.0f%%"), (m_fZoomFactor*100.0));
\r
627 if (strText.Compare(strItem) != 0)
\r
628 pCBox->SetWindowText(strText);
\r
631 BOOL CRevisionGraphDlg::OnToolTipNotify(UINT /*id*/, NMHDR *pNMHDR, LRESULT *pResult)
\r
633 // need to handle both ANSI and UNICODE versions of the message
\r
634 TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
\r
635 TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
\r
636 CString strTipText;
\r
638 UINT_PTR nID = pNMHDR->idFrom;
\r
640 if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
\r
641 pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
\r
643 // idFrom is actually the HWND of the tool
\r
644 nID = ::GetDlgCtrlID((HWND)nID);
\r
647 if (nID != 0) // will be zero on a separator
\r
649 strTipText.LoadString (static_cast<UINT>(nID));
\r
653 if (strTipText.IsEmpty())
\r
656 if (strTipText.GetLength() >= MAX_TT_LENGTH)
\r
657 strTipText = strTipText.Left(MAX_TT_LENGTH);
\r
659 if (pNMHDR->code == TTN_NEEDTEXTA)
\r
661 ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 600);
\r
662 pTTTA->lpszText = m_szTip;
\r
663 WideCharToMultiByte(CP_ACP, 0, strTipText, -1, m_szTip, strTipText.GetLength()+1, 0, 0);
\r
667 ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 600);
\r
668 lstrcpyn(m_wszTip, strTipText, strTipText.GetLength()+1);
\r
669 pTTTW->lpszText = m_wszTip;
\r
671 // bring the tooltip window above other pop up windows
\r
672 ::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,
\r
673 SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER);
\r
674 return TRUE; // message was handled
\r
677 void CRevisionGraphDlg::OnViewFilter()
\r
679 CRevisionInRange* revisionRange = m_options.GetOption<CRevisionInRange>();
\r
680 svn_revnum_t head = m_Graph.GetHeadRevision();
\r
681 svn_revnum_t lowerLimit = revisionRange->GetLowerLimit();
\r
682 svn_revnum_t upperLimit = revisionRange->GetUpperLimit();
\r
684 CRevGraphFilterDlg dlg;
\r
685 dlg.SetMaxRevision (head);
\r
686 dlg.SetFilterString (m_sFilter);
\r
687 dlg.SetRevisionRange ( min (head, lowerLimit == -1 ? 1 : lowerLimit)
\r
688 , min (head, upperLimit == -1 ? head : upperLimit));
\r
690 if (dlg.DoModal()==IDOK)
\r
692 // user pressed OK to dismiss the dialog, which means
\r
693 // we have to accept the new filter settings and apply them
\r
694 svn_revnum_t minrev, maxrev;
\r
695 dlg.GetRevisionRange(minrev, maxrev);
\r
696 m_sFilter = dlg.GetFilterString();
\r
698 revisionRange->SetLowerLimit (minrev);
\r
699 revisionRange->SetUpperLimit (maxrev);
\r
701 std::set<std::string>& filterPaths
\r
702 = m_options.GetOption<CRemovePathsBySubString>()->GetFilterPaths();
\r
705 filterPaths.clear();
\r
707 CString path = m_sFilter.Tokenize (_T("*"), index);
\r
708 while (!path.IsEmpty())
\r
710 filterPaths.insert (CUnicodeUtils::StdGetUTF8 ((LPCTSTR)path));
\r
711 path = m_sFilter.Tokenize (_T("*"), index);
\r
714 InterlockedExchange(&m_Graph.m_bThreadRunning, TRUE);
\r
716 if (AfxBeginThread(WorkerThread, this)==NULL)
\r
718 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
\r
723 void CRevisionGraphDlg::OnViewShowoverview()
\r
725 CMenu * pMenu = GetMenu();
\r
728 int tbstate = m_ToolBar.GetToolBarCtrl().GetState(ID_VIEW_SHOWOVERVIEW);
\r
729 UINT state = pMenu->GetMenuState(ID_VIEW_SHOWOVERVIEW, MF_BYCOMMAND);
\r
730 if (state & MF_CHECKED)
\r
732 pMenu->CheckMenuItem(ID_VIEW_SHOWOVERVIEW, MF_BYCOMMAND | MF_UNCHECKED);
\r
733 m_ToolBar.GetToolBarCtrl().SetState(ID_VIEW_SHOWOVERVIEW, tbstate & (~TBSTATE_CHECKED));
\r
734 m_Graph.SetShowOverview (false);
\r
738 pMenu->CheckMenuItem(ID_VIEW_SHOWOVERVIEW, MF_BYCOMMAND | MF_CHECKED);
\r
739 m_ToolBar.GetToolBarCtrl().SetState(ID_VIEW_SHOWOVERVIEW, tbstate | TBSTATE_CHECKED);
\r
740 m_Graph.SetShowOverview (true);
\r
743 CRegDWORD reg = CRegDWORD(_T("Software\\TortoiseSVN\\ShowRevGraphOverview"), FALSE);
\r
744 reg = m_Graph.GetShowOverview();
\r
745 m_Graph.Invalidate(FALSE);
\r