OSDN Git Service

Change Dir Structure to be same as TortoiseSVN'
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / RevisionGraph / RevisionGraphDlg.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseSVN\r
4 \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
9 \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
14 \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
18 //\r
19 #include "stdafx.h"\r
20 #include "TortoiseProc.h"\r
21 #include "Revisiongraphdlg.h"\r
22 #include "MessageBox.h"\r
23 #include "SVN.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
36 \r
37 #ifdef _DEBUG\r
38 #define new DEBUG_NEW\r
39 #undef THIS_FILE\r
40 static char THIS_FILE[] = __FILE__;\r
41 #endif\r
42 \r
43 using namespace Gdiplus;\r
44 \r
45 IMPLEMENT_DYNAMIC(CRevisionGraphDlg, CResizableStandAloneDialog)\r
46 CRevisionGraphDlg::CRevisionGraphDlg(CWnd* pParent /*=NULL*/)\r
47         : CResizableStandAloneDialog(CRevisionGraphDlg::IDD, pParent)\r
48         , m_hAccel(NULL)\r
49         , m_bFetchLogs(true)\r
50         , m_fZoomFactor(0.5)\r
51 {\r
52     // GDI+ initialization\r
53 \r
54     GdiplusStartupInput input;\r
55     GdiplusStartup (&m_gdiPlusToken, &input, NULL);\r
56 \r
57     // restore option state\r
58 \r
59         DWORD dwOpts = CRegStdWORD(_T("Software\\TortoiseSVN\\RevisionGraphOptions"), 0x211);\r
60     m_options.SetRegistryFlags (dwOpts, 0x3ff);\r
61 }\r
62 \r
63 CRevisionGraphDlg::~CRevisionGraphDlg()\r
64 {\r
65     // save option state\r
66 \r
67         CRegStdWORD regOpts = CRegStdWORD(_T("Software\\TortoiseSVN\\RevisionGraphOptions"), 1);\r
68     regOpts = m_options.GetRegistryFlags();\r
69 \r
70     // GDI+ cleanup\r
71 \r
72     GdiplusShutdown (m_gdiPlusToken);\r
73 }\r
74 \r
75 void CRevisionGraphDlg::DoDataExchange(CDataExchange* pDX)\r
76 {\r
77         CResizableStandAloneDialog::DoDataExchange(pDX);\r
78 }\r
79 \r
80 \r
81 BEGIN_MESSAGE_MAP(CRevisionGraphDlg, CResizableStandAloneDialog)\r
82         ON_WM_SIZE()\r
83         ON_WM_LBUTTONDOWN()\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
109 END_MESSAGE_MAP()\r
110 \r
111 BOOL CRevisionGraphDlg::InitializeToolbar()\r
112 {\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
119 \r
120         // toolbars aren't true-color without some tweaking:\r
121         {\r
122                 CImageList      cImageList;\r
123                 CBitmap         cBitmap;\r
124                 BITMAP          bmBitmap;\r
125 \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
130 \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
135 \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
140                 cBitmap.Detach();\r
141         }\r
142         RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);\r
143 \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
147         int index = 0;\r
148         while (m_ToolBar.GetItemID(index) != ID_REVGRAPH_ZOOMCOMBO) index++;\r
149 \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
152                 SNAP_WIDTH);\r
153         RECT rect;\r
154         m_ToolBar.GetItemRect(index, &rect);\r
155 \r
156         // expand the rectangle to allow the combo box room to drop down\r
157         rect.top+=3;\r
158         rect.bottom += 200;\r
159 \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
163         {\r
164                 TRACE0("Failed to create combo-box\n");\r
165                 return FALSE;\r
166         }\r
167         m_ToolBar.m_ZoomCombo.ShowWindow(SW_SHOW);\r
168 \r
169         // set toolbar button styles\r
170 \r
171         UINT styles[] = { TBBS_CHECKBOX|TBBS_CHECKED\r
172                                         , TBBS_CHECKBOX\r
173                                         , 0};\r
174 \r
175         UINT itemIDs[] = { ID_VIEW_GROUPBRANCHES \r
176                                          , 0            // separate styles by "0"\r
177                                          , ID_VIEW_SHOWOVERVIEW\r
178                                          , ID_VIEW_TOPDOWN\r
179                                          , ID_VIEW_SHOWHEAD\r
180                                          , ID_VIEW_EXACTCOPYSOURCE\r
181                                          , ID_VIEW_FOLDTAGS\r
182                                          , ID_VIEW_REDUCECROSSLINES\r
183                      , ID_VIEW_REMOVEDELETEDONES\r
184                      , ID_VIEW_SHOWWCREV\r
185                                          , 0};\r
186 \r
187         for (UINT* itemID = itemIDs, *style = styles; *style != 0; ++itemID)\r
188         {\r
189                 if (*itemID == 0)\r
190                 {\r
191                         ++style;\r
192                         continue;\r
193                 }\r
194 \r
195                 int index = 0;\r
196                 while (m_ToolBar.GetItemID(index) != *itemID)\r
197                         index++;\r
198                 m_ToolBar.SetButtonStyle(index, m_ToolBar.GetButtonStyle(index)|*style);\r
199         }\r
200 \r
201         // fill the combo box\r
202 \r
203         TCHAR* texts[] = { _T("5%")\r
204                                          , _T("10%")\r
205                                          , _T("20%")\r
206                                          , _T("40%")\r
207                                          , _T("50%")\r
208                                          , _T("75%")\r
209                                          , _T("100%")\r
210                                          , _T("200%")\r
211                                          , NULL};\r
212 \r
213         COMBOBOXEXITEM cbei;\r
214         SecureZeroMemory(&cbei, sizeof cbei);\r
215         cbei.mask = CBEIF_TEXT;\r
216 \r
217         for (TCHAR** text = texts; *text != NULL; ++text)\r
218         {\r
219                 cbei.pszText = *text;\r
220                 m_ToolBar.m_ZoomCombo.InsertItem(&cbei);\r
221         }\r
222 \r
223         m_ToolBar.m_ZoomCombo.SetCurSel(1);\r
224 \r
225         return TRUE;\r
226 }\r
227 \r
228 BOOL CRevisionGraphDlg::OnInitDialog()\r
229 {\r
230         CResizableStandAloneDialog::OnInitDialog();\r
231 \r
232         EnableToolTips();\r
233 \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
239 \r
240         if (InitializeToolbar() != TRUE)\r
241                 return FALSE;\r
242 \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
246 \r
247         CMenu * pMenu = GetMenu();\r
248         if (pMenu)\r
249         {\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
255         }\r
256 \r
257         m_hAccel = LoadAccelerators(AfxGetResourceHandle(),MAKEINTRESOURCE(IDR_ACC_REVISIONGRAPH));\r
258 \r
259         CRect graphrect = GetGraphRect();\r
260         m_Graph.Init(this, &graphrect);\r
261         m_Graph.SetOwner(this);\r
262         m_Graph.UpdateWindow();\r
263     DoZoom (0.75);\r
264 \r
265         EnableSaveRestore(_T("RevisionGraphDlg"));\r
266 \r
267         if (AfxBeginThread(WorkerThread, this)==NULL)\r
268         {\r
269                 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);\r
270         }\r
271         if (hWndExplorer)\r
272                 CenterWindow(CWnd::FromHandle(hWndExplorer));\r
273         return TRUE;  // return TRUE unless you set the focus to a control\r
274 }\r
275 \r
276 UINT CRevisionGraphDlg::WorkerThread(LPVOID pVoid)\r
277 {\r
278         CRevisionGraphDlg*      pDlg;\r
279         pDlg = (CRevisionGraphDlg*)pVoid;\r
280         InterlockedExchange(&pDlg->m_Graph.m_bThreadRunning, TRUE);\r
281         CoInitialize(NULL);\r
282 \r
283     if (pDlg->m_bFetchLogs)\r
284     {\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
290 \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
294 \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
297 \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
301 \r
302         pDlg->m_bFetchLogs = false;     // we've got the logs, no need to fetch them a second time\r
303     }\r
304 \r
305     // standard plus user settings\r
306 \r
307     pDlg->m_options.Prepare();\r
308     if (pDlg->m_Graph.AnalyzeRevisionData (pDlg->m_options))\r
309         pDlg->UpdateStatusBar();\r
310 \r
311         CoUninitialize();\r
312         InterlockedExchange(&pDlg->m_Graph.m_bThreadRunning, FALSE);\r
313 \r
314     pDlg->m_Graph.SendMessage (CRevisionGraphWnd::WM_WORKERTHREADDONE, 0, 0);\r
315         return 0;\r
316 }\r
317 \r
318 void CRevisionGraphDlg::OnSize(UINT nType, int cx, int cy)\r
319 {\r
320         __super::OnSize(nType, cx, cy);\r
321         CRect rect;\r
322         GetClientRect(&rect);\r
323         if (IsWindow(m_ToolBar))\r
324         {\r
325                 RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);\r
326         }\r
327         if (IsWindow(m_StatusBar))\r
328         {\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
333         }\r
334         if (IsWindow(m_Graph))\r
335         {\r
336                 m_Graph.MoveWindow (GetGraphRect());\r
337         }\r
338 }\r
339 \r
340 BOOL CRevisionGraphDlg::PreTranslateMessage(MSG* pMsg)\r
341 {\r
342 #define SCROLL_STEP  20\r
343         if (pMsg->message == WM_KEYDOWN)\r
344         {\r
345                 int pos = 0;\r
346                 switch (pMsg->wParam)\r
347                 {\r
348                 case VK_UP:\r
349                         pos = m_Graph.GetScrollPos(SB_VERT);\r
350                         m_Graph.SetScrollPos(SB_VERT, pos - SCROLL_STEP);\r
351                         m_Graph.Invalidate();\r
352                         break;\r
353                 case VK_DOWN:\r
354                         pos = m_Graph.GetScrollPos(SB_VERT);\r
355                         m_Graph.SetScrollPos(SB_VERT, pos + SCROLL_STEP);\r
356                         m_Graph.Invalidate();\r
357                         break;\r
358                 case VK_LEFT:\r
359                         pos = m_Graph.GetScrollPos(SB_HORZ);\r
360                         m_Graph.SetScrollPos(SB_HORZ, pos - SCROLL_STEP);\r
361                         m_Graph.Invalidate();\r
362                         break;\r
363                 case VK_RIGHT:\r
364                         pos = m_Graph.GetScrollPos(SB_HORZ);\r
365                         m_Graph.SetScrollPos(SB_HORZ, pos + SCROLL_STEP);\r
366                         m_Graph.Invalidate();\r
367                         break;\r
368                 case VK_PRIOR:\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
372                         break;\r
373                 case VK_NEXT:\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
377                         break;\r
378                 case VK_F5:\r
379                 m_Graph.SetDlgTitle (false);\r
380 \r
381             SVN svn;\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
386 \r
387             cachedProperties.ResetHeadRevision (uuid, root);\r
388 \r
389             m_bFetchLogs = true;\r
390             StartWorkerThread();\r
391 \r
392                         break;\r
393                 }\r
394         }\r
395         if ((m_hAccel)&&(pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST))\r
396         {\r
397                 return TranslateAccelerator(m_hWnd,m_hAccel,pMsg);\r
398         }\r
399         return __super::PreTranslateMessage(pMsg);\r
400 }\r
401 \r
402 void CRevisionGraphDlg::DoZoom (float zoom)\r
403 {\r
404     m_fZoomFactor = zoom;\r
405     m_Graph.DoZoom (zoom);\r
406     UpdateZoomBox();\r
407 }\r
408 \r
409 void CRevisionGraphDlg::OnViewZoomin()\r
410 {\r
411     DoZoom (min (2.0f, m_fZoomFactor / .9f));\r
412 }\r
413 \r
414 void CRevisionGraphDlg::OnViewZoomout()\r
415 {\r
416     DoZoom (max (0.01f, m_fZoomFactor * .9f));\r
417 }\r
418 \r
419 void CRevisionGraphDlg::OnViewZoom100()\r
420 {\r
421         DoZoom (1.0);\r
422 }\r
423 \r
424 void CRevisionGraphDlg::OnViewZoomAll()\r
425 {\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
429 \r
430         float horzfact = float(viewrect.Width())/float(windowrect.Width()-6);\r
431         float vertfact = float(viewrect.Height())/float(windowrect.Height()-6);\r
432 \r
433     DoZoom (1.0f/(max (1.0f, max(horzfact, vertfact))));\r
434 }\r
435 \r
436 void CRevisionGraphDlg::OnMenuexit()\r
437 {\r
438         if (!m_Graph.m_bThreadRunning)\r
439                 EndDialog(IDOK);\r
440 }\r
441 \r
442 void CRevisionGraphDlg::OnMenuhelp()\r
443 {\r
444         OnHelp();\r
445 }\r
446 \r
447 void CRevisionGraphDlg::OnViewCompareheadrevisions()\r
448 {\r
449         m_Graph.CompareRevs(true);\r
450 }\r
451 \r
452 void CRevisionGraphDlg::OnViewComparerevisions()\r
453 {\r
454         m_Graph.CompareRevs(false);\r
455 }\r
456 \r
457 void CRevisionGraphDlg::OnViewUnifieddiff()\r
458 {\r
459         m_Graph.UnifiedDiffRevs(false);\r
460 }\r
461 \r
462 void CRevisionGraphDlg::OnViewUnifieddiffofheadrevisions()\r
463 {\r
464         m_Graph.UnifiedDiffRevs(true);\r
465 }\r
466 \r
467 void CRevisionGraphDlg::SetOption (UINT controlID)\r
468 {\r
469         CMenu * pMenu = GetMenu();\r
470         if (pMenu == NULL)\r
471                 return;\r
472 \r
473         int tbstate = m_ToolBar.GetToolBarCtrl().GetState(controlID);\r
474     if (tbstate != -1)\r
475     {\r
476         if (m_options.IsSelected (controlID))\r
477             {\r
478                     pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_CHECKED);\r
479                     m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate | TBSTATE_CHECKED);\r
480             }\r
481             else\r
482             {\r
483                     pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_UNCHECKED);\r
484                     m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate & (~TBSTATE_CHECKED));\r
485             }\r
486     }\r
487 }\r
488 \r
489 BOOL CRevisionGraphDlg::OnToggleOption (UINT controlID)\r
490 {\r
491     // check request for validity\r
492 \r
493         if (m_Graph.m_bThreadRunning)\r
494         {\r
495                 int state = m_ToolBar.GetToolBarCtrl().GetState(controlID);\r
496                 if (state & TBSTATE_CHECKED)\r
497                         state &= ~TBSTATE_CHECKED;\r
498                 else\r
499                         state |= TBSTATE_CHECKED;\r
500                 m_ToolBar.GetToolBarCtrl().SetState (controlID, state);\r
501                 return FALSE;\r
502         }\r
503 \r
504         CMenu * pMenu = GetMenu();\r
505         if (pMenu == NULL)\r
506                 return FALSE;\r
507 \r
508     // actually toggle the option\r
509 \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
513         {\r
514                 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_UNCHECKED);\r
515                 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate & (~TBSTATE_CHECKED));\r
516         }\r
517         else\r
518         {\r
519                 pMenu->CheckMenuItem(controlID, MF_BYCOMMAND | MF_CHECKED);\r
520                 m_ToolBar.GetToolBarCtrl().SetState(controlID, tbstate | TBSTATE_CHECKED);\r
521         }\r
522 \r
523     if (((state & MF_CHECKED) != 0) == m_options.IsSelected (controlID))\r
524         m_options.ToggleSelection (controlID);\r
525 \r
526     // re-process the data\r
527 \r
528     StartWorkerThread();\r
529 \r
530     return TRUE;\r
531 }\r
532 \r
533 void CRevisionGraphDlg::StartWorkerThread()\r
534 {\r
535         if (InterlockedExchange(&m_Graph.m_bThreadRunning, TRUE) == TRUE)\r
536         return;\r
537 \r
538         if (AfxBeginThread(WorkerThread, this)==NULL)\r
539         {\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
542         }\r
543 }\r
544 \r
545 void CRevisionGraphDlg::OnCancel()\r
546 {\r
547         if (!m_Graph.m_bThreadRunning)\r
548                 __super::OnCancel();\r
549 }\r
550 \r
551 void CRevisionGraphDlg::OnOK()\r
552 {\r
553         OnChangeZoom();\r
554 }\r
555 \r
556 void CRevisionGraphDlg::OnFileSavegraphas()\r
557 {\r
558         CString tempfile;\r
559         int filterindex = 0;\r
560         if (CAppUtils::FileOpenSave(tempfile, &filterindex, IDS_REVGRAPH_SAVEPIC, IDS_PICTUREFILEFILTER, false, m_hWnd))\r
561         {\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
566                 CString extension;\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
572                 {\r
573                         extension = _T(".wmf");\r
574                         tempfile += extension;\r
575                 }\r
576                 m_Graph.SaveGraphAs(tempfile);\r
577         }\r
578 }\r
579 \r
580 CRect CRevisionGraphDlg::GetGraphRect()\r
581 {\r
582     CRect rect;\r
583     GetClientRect(&rect);\r
584 \r
585     CRect statusbarrect;\r
586     m_StatusBar.GetClientRect(&statusbarrect);\r
587     rect.bottom -= statusbarrect.Height();\r
588 \r
589     CRect toolbarrect;\r
590     m_ToolBar.GetClientRect(&toolbarrect);\r
591     rect.top += toolbarrect.Height();\r
592 \r
593     return rect;\r
594 }\r
595 \r
596 void CRevisionGraphDlg::UpdateStatusBar()\r
597 {\r
598         CString sFormat;\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
603 }\r
604 \r
605 void CRevisionGraphDlg::OnChangeZoom()\r
606 {\r
607         if (!IsWindow(m_Graph.GetSafeHwnd()))\r
608                 return;\r
609         CString strText;\r
610         CString strItem;\r
611         CComboBoxEx* pCBox = (CComboBoxEx*)m_ToolBar.GetDlgItem(ID_REVGRAPH_ZOOMCOMBO);\r
612         pCBox->GetWindowText(strItem);\r
613         if (strItem.IsEmpty())\r
614                 return;\r
615         ATLTRACE(_T("OnChangeZoom to %s\n"), strItem);\r
616 \r
617     DoZoom ((float)(_tstof(strItem)/100.0));\r
618 }\r
619 \r
620 void CRevisionGraphDlg::UpdateZoomBox()\r
621 {\r
622         CString strText;\r
623         CString strItem;\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
629 }\r
630 \r
631 BOOL CRevisionGraphDlg::OnToolTipNotify(UINT /*id*/, NMHDR *pNMHDR, LRESULT *pResult)\r
632 {\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
637 \r
638         UINT_PTR nID = pNMHDR->idFrom;\r
639 \r
640         if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||\r
641                 pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))\r
642         {\r
643                 // idFrom is actually the HWND of the tool \r
644                 nID = ::GetDlgCtrlID((HWND)nID);\r
645         }\r
646 \r
647         if (nID != 0) // will be zero on a separator\r
648         {\r
649                 strTipText.LoadString (static_cast<UINT>(nID));\r
650         }\r
651 \r
652         *pResult = 0;\r
653         if (strTipText.IsEmpty())\r
654                 return TRUE;\r
655 \r
656         if (strTipText.GetLength() >= MAX_TT_LENGTH)\r
657                 strTipText = strTipText.Left(MAX_TT_LENGTH);\r
658 \r
659         if (pNMHDR->code == TTN_NEEDTEXTA)\r
660         {\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
664         }\r
665         else\r
666         {\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
670         }\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
675 }\r
676 \r
677 void CRevisionGraphDlg::OnViewFilter()\r
678 {\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
683 \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
689 \r
690     if (dlg.DoModal()==IDOK)\r
691         {\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
697 \r
698         revisionRange->SetLowerLimit (minrev);\r
699         revisionRange->SetUpperLimit (maxrev);\r
700 \r
701         std::set<std::string>& filterPaths \r
702             = m_options.GetOption<CRemovePathsBySubString>()->GetFilterPaths();\r
703 \r
704         int index = 0;\r
705         filterPaths.clear();\r
706 \r
707         CString path = m_sFilter.Tokenize (_T("*"),  index);\r
708         while (!path.IsEmpty())\r
709         {\r
710             filterPaths.insert (CUnicodeUtils::StdGetUTF8 ((LPCTSTR)path));\r
711             path = m_sFilter.Tokenize (_T("*"),  index);\r
712         }\r
713 \r
714         InterlockedExchange(&m_Graph.m_bThreadRunning, TRUE);\r
715 \r
716                 if (AfxBeginThread(WorkerThread, this)==NULL)\r
717                 {\r
718                         CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);\r
719                 }\r
720         }\r
721 }\r
722 \r
723 void CRevisionGraphDlg::OnViewShowoverview()\r
724 {\r
725         CMenu * pMenu = GetMenu();\r
726         if (pMenu == NULL)\r
727                 return;\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
731         {\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
735         }\r
736         else\r
737         {\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
741         }\r
742 \r
743         CRegDWORD reg = CRegDWORD(_T("Software\\TortoiseSVN\\ShowRevGraphOverview"), FALSE);\r
744         reg = m_Graph.GetShowOverview();\r
745         m_Graph.Invalidate(FALSE);\r
746 }\r
747 \r
748 \r
749 \r
750 \r
751 \r
752 \r
753 \r