OSDN Git Service

Change Dir Structure to be same as TortoiseSVN'
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / RevisionGraph / RevisionGraphDlgFunc.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 <gdiplus.h>\r
22 #include "Revisiongraphdlg.h"\r
23 #include "MessageBox.h"\r
24 #include "SVN.h"\r
25 #include "TempFile.h"\r
26 #include "UnicodeUtils.h"\r
27 #include "TSVNPath.h"\r
28 #include "SVNInfo.h"\r
29 #include ".\revisiongraphwnd.h"\r
30 #include "CachedLogInfo.h"\r
31 #include "RevisionGraph/IRevisionGraphLayout.h"\r
32 #include "RevisionGraph/FullGraphBuilder.h"\r
33 #include "RevisionGraph/FullGraphFinalizer.h"\r
34 #include "RevisionGraph/VisibleGraphBuilder.h"\r
35 #include "RevisionGraph/StandardLayout.h"\r
36 #include "RevisionGraph/ShowWC.h"\r
37 \r
38 #ifdef _DEBUG\r
39 #define new DEBUG_NEW\r
40 #undef THIS_FILE\r
41 static char THIS_FILE[] = __FILE__;\r
42 #endif\r
43 \r
44 using namespace Gdiplus;\r
45 \r
46 void CRevisionGraphWnd::InitView()\r
47 {\r
48         m_bIsRubberBand = false;\r
49 \r
50     CRect viewRect = GetViewRect();\r
51         SetScrollbars (0,0,viewRect.Width(),viewRect.Height());\r
52 }\r
53 \r
54 void CRevisionGraphWnd::BuildPreview()\r
55 {\r
56         m_Preview.DeleteObject();\r
57         if (!m_bShowOverview)\r
58                 return;\r
59 \r
60         // is there a point in drawing this at all?\r
61 \r
62     int nodeCount = GetNodeCount();\r
63         if ((nodeCount > REVGRAPH_PREVIEW_MAX_NODES) || (nodeCount == 0))\r
64                 return;\r
65 \r
66         float origZoom = m_fZoomFactor;\r
67 \r
68     CRect clientRect;\r
69     GetClientRect (&clientRect);\r
70     CSize preViewSize (max (REVGRAPH_PREVIEW_WIDTH, clientRect.Width() / 4)\r
71                       ,max (REVGRAPH_PREVIEW_HEIGHT, clientRect.Height() / 4));\r
72 \r
73     // zoom the graph so that it is completely visible in the window\r
74     CRect graphRect = GetGraphRect();\r
75         float horzfact = float(graphRect.Width())/float(preViewSize.cx);\r
76         float vertfact = float(graphRect.Height())/float(preViewSize.cy);\r
77         m_previewZoom = min (1.0f, 1.0f/(max(horzfact, vertfact)));\r
78 \r
79     // make sure the preview window has a minimal size\r
80 \r
81     m_previewWidth = (int)min (max (graphRect.Width() * m_previewZoom, 30), preViewSize.cx);\r
82         m_previewHeight = (int)max (max (graphRect.Height() * m_previewZoom, 30), preViewSize.cy);\r
83 \r
84         CClientDC ddc(this);\r
85         CDC dc;\r
86         if (!dc.CreateCompatibleDC(&ddc))\r
87                 return;\r
88 \r
89         m_Preview.CreateCompatibleBitmap(&ddc, m_previewWidth, m_previewHeight);\r
90         HBITMAP oldbm = (HBITMAP)dc.SelectObject (m_Preview);\r
91 \r
92     // paint the whole graph\r
93     DoZoom (m_previewZoom);\r
94     CRect rect (0, 0, m_previewWidth, m_previewHeight);\r
95         DrawGraph(&dc, rect, 0, 0, true);\r
96 \r
97         // now we have a bitmap the size of the preview window\r
98         dc.SelectObject(oldbm);\r
99         dc.DeleteDC();\r
100 \r
101         DoZoom (origZoom);\r
102 }\r
103 \r
104 void CRevisionGraphWnd::SetScrollbars(int nVert, int nHorz, int oldwidth, int oldheight)\r
105 {\r
106         CRect clientrect;\r
107         GetClientRect(&clientrect);\r
108         const CRect& pRect = GetGraphRect();\r
109 \r
110     SCROLLINFO ScrollInfo = {sizeof(SCROLLINFO), SIF_ALL};\r
111         GetScrollInfo(SB_VERT, &ScrollInfo);\r
112 \r
113         if ((nVert)||(oldheight==0))\r
114                 ScrollInfo.nPos = nVert;\r
115         else\r
116                 ScrollInfo.nPos = ScrollInfo.nPos * pRect.Height() / oldheight;\r
117 \r
118     ScrollInfo.nMin = 0;\r
119         ScrollInfo.nMax = static_cast<int>(pRect.bottom * m_fZoomFactor);\r
120         ScrollInfo.nPage = clientrect.Height();\r
121         ScrollInfo.nTrackPos = 0;\r
122         SetScrollInfo(SB_VERT, &ScrollInfo);\r
123 \r
124         GetScrollInfo(SB_HORZ, &ScrollInfo);\r
125         if ((nHorz)||(oldwidth==0))\r
126                 ScrollInfo.nPos = nHorz;\r
127         else\r
128                 ScrollInfo.nPos = ScrollInfo.nPos * pRect.Width() / oldwidth;\r
129 \r
130         ScrollInfo.nMax = static_cast<int>(pRect.right * m_fZoomFactor);\r
131         ScrollInfo.nPage = clientrect.Width();\r
132         SetScrollInfo(SB_HORZ, &ScrollInfo);\r
133 }\r
134 \r
135 CRect CRevisionGraphWnd::GetGraphRect()\r
136 {\r
137     return m_layout.get() != NULL\r
138         ? m_layout->GetRect()\r
139         : CRect (0,0,0,0);\r
140 }\r
141 \r
142 CRect CRevisionGraphWnd::GetViewRect()\r
143 {\r
144         CRect clientRect;\r
145         GetClientRect (&clientRect);\r
146 \r
147     CRect result;\r
148     result.UnionRect (clientRect, GetGraphRect()); \r
149     return result;\r
150 }\r
151 \r
152 int CRevisionGraphWnd::GetNodeCount()\r
153 {\r
154     return m_visibleGraph.get() != NULL\r
155         ? static_cast<int>(m_visibleGraph->GetNodeCount())\r
156         : 0;\r
157 }\r
158 \r
159 svn_revnum_t CRevisionGraphWnd::GetHeadRevision() const\r
160 {\r
161     return m_fullHistory.get() != NULL\r
162         ? m_fullHistory->GetHeadRevision()\r
163         : 0;\r
164 }\r
165 \r
166 CString CRevisionGraphWnd::GetRepositoryRoot() const\r
167 {\r
168     return m_fullHistory.get() != NULL\r
169         ? m_fullHistory->GetRepositoryRoot()\r
170         : CString();\r
171 }\r
172 \r
173 CString CRevisionGraphWnd::GetRepositoryUUID() const\r
174 {\r
175     return m_fullHistory.get() != NULL\r
176         ? m_fullHistory->GetRepositoryUUID()\r
177         : CString();\r
178 }\r
179 \r
180 int CRevisionGraphWnd::GetEncoderClsid(const WCHAR* format, CLSID* pClsid)\r
181 {\r
182         UINT  num = 0;          // number of image encoders\r
183         UINT  size = 0;         // size of the image encoder array in bytes\r
184 \r
185         ImageCodecInfo* pImageCodecInfo = NULL;\r
186 \r
187         if (GetImageEncodersSize(&num, &size)!=Ok)\r
188                 return -1;\r
189         if(size == 0)\r
190                 return -1;  // Failure\r
191 \r
192         pImageCodecInfo = (ImageCodecInfo*)(malloc(size));\r
193         if(pImageCodecInfo == NULL)\r
194                 return -1;  // Failure\r
195 \r
196         if (GetImageEncoders(num, size, pImageCodecInfo)==Ok)\r
197         {\r
198                 for(UINT j = 0; j < num; ++j)\r
199                 {\r
200                         if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )\r
201                         {\r
202                                 *pClsid = pImageCodecInfo[j].Clsid;\r
203                                 free(pImageCodecInfo);\r
204                                 return j;  // Success\r
205                         }\r
206                 }\r
207 \r
208         }\r
209         free(pImageCodecInfo);\r
210         return -1;  // Failure\r
211 }\r
212 \r
213 void CRevisionGraphWnd::Compare (TDiffFunc diffFunc, TStartDiffFunc startDiffFunc, bool bHead)\r
214 {\r
215         ASSERT(m_SelectedEntry1 != NULL);\r
216         ASSERT(m_SelectedEntry2 != NULL);\r
217 \r
218         CString sRepoRoot = m_fullHistory.get() != NULL\r
219                       ? m_fullHistory->GetRepositoryRoot()\r
220                       : CString();\r
221 \r
222         CTSVNPath url1;\r
223         CTSVNPath url2;\r
224         url1.SetFromSVN (sRepoRoot + CUnicodeUtils::GetUnicode (m_SelectedEntry1->GetPath().GetPath().c_str()));\r
225         url2.SetFromSVN (sRepoRoot + CUnicodeUtils::GetUnicode (m_SelectedEntry2->GetPath().GetPath().c_str()));\r
226 \r
227     SVNRev rev1 (bHead ? SVNRev::REV_HEAD : m_SelectedEntry1->GetRevision());\r
228     SVNRev rev2 (bHead ? SVNRev::REV_HEAD : m_SelectedEntry2->GetRevision());\r
229         SVNRev peg (bHead ? m_SelectedEntry1->GetRevision() : SVNRev());\r
230 \r
231     if (PromptShown())\r
232     {\r
233         SVNDiff diff (&m_fullHistory->GetSVN(), this->m_hWnd);\r
234             diff.SetAlternativeTool(!!(GetAsyncKeyState(VK_SHIFT) & 0x8000));\r
235             (diff.*diffFunc)(url1, rev1,\r
236                              url2, rev2,\r
237                              peg, false, false);\r
238     }\r
239     else\r
240     {\r
241                 (*startDiffFunc)(m_hWnd, url1, rev1,\r
242                                                  url2, rev2, peg, \r
243                                                  SVNRev(), !!(GetAsyncKeyState(VK_SHIFT) & 0x8000), false, false);\r
244     }\r
245 }\r
246 \r
247 bool CRevisionGraphWnd::PromptShown() const\r
248 {\r
249     return m_fullHistory.get() != NULL\r
250         ? m_fullHistory->GetSVN().PromptShown()\r
251         : false;\r
252 }\r
253 \r
254 bool CRevisionGraphWnd::FetchRevisionData \r
255     ( const CString& path\r
256     , SVNRev pegRevision\r
257     , const CAllRevisionGraphOptions& options)\r
258 {\r
259     // (re-)fetch the data\r
260 \r
261     m_fullHistory.reset (new CFullHistory());\r
262 \r
263     bool showWCRev = options.GetOption<CShowWC>()->IsActive();\r
264         bool result = m_fullHistory->FetchRevisionData (path, pegRevision, showWCRev, m_pProgress);\r
265     if (result)\r
266     {\r
267         m_fullGraph.reset (new CFullGraph());\r
268         m_visibleGraph.reset();\r
269         m_layout.reset();\r
270 \r
271         CFullGraphBuilder builder (*m_fullHistory, *m_fullGraph);\r
272         builder.Run();\r
273 \r
274         CFullGraphFinalizer finalizer (*m_fullHistory, *m_fullGraph);\r
275         finalizer.Run();\r
276     }\r
277 \r
278     return result;\r
279 }\r
280 \r
281 bool CRevisionGraphWnd::AnalyzeRevisionData \r
282     (const CAllRevisionGraphOptions& options)\r
283 {\r
284     m_layout.reset();\r
285     if ((m_fullGraph.get() != NULL) && (m_fullGraph->GetNodeCount() > 0))\r
286     {\r
287         // filter graph\r
288 \r
289         m_visibleGraph.reset (new CVisibleGraph());\r
290         CVisibleGraphBuilder builder ( *m_fullGraph\r
291                                      , *m_visibleGraph\r
292                                      , options.GetCopyFilterOptions());\r
293         builder.Run();\r
294         options.GetModificationOptions().Apply (m_visibleGraph.get());\r
295 \r
296         index_t index = 0;\r
297         for (size_t i = 0, count = m_visibleGraph->GetRootCount(); i < count; ++i)\r
298             index = m_visibleGraph->GetRoot (i)->InitIndex (index);\r
299 \r
300         // layout nodes\r
301 \r
302         std::auto_ptr<CStandardLayout> newLayout \r
303             ( new CStandardLayout ( m_fullHistory->GetCache()\r
304                                   , m_visibleGraph.get()));\r
305         options.GetLayoutOptions().Apply (newLayout.get());\r
306         newLayout->Finalize();\r
307 \r
308         m_layout = newLayout;\r
309     }\r
310 \r
311     return m_layout.get() != NULL;\r
312 }\r
313 \r
314 CString CRevisionGraphWnd::GetLastErrorMessage() const\r
315 {\r
316     return m_fullHistory->GetLastErrorMessage();\r
317 }\r
318 \r
319 bool CRevisionGraphWnd::GetShowOverview() const\r
320 {\r
321     return m_bShowOverview != FALSE;\r
322 }\r
323 \r
324 void CRevisionGraphWnd::SetShowOverview (bool value)\r
325 {\r
326     m_bShowOverview = value;\r
327         if (m_bShowOverview)\r
328                 BuildPreview();\r
329 }\r
330 \r
331 void CRevisionGraphWnd::CompareRevs(bool bHead)\r
332 {\r
333     Compare (&SVNDiff::ShowCompare, &CAppUtils::StartShowCompare, bHead);\r
334 }\r
335 \r
336 void CRevisionGraphWnd::UnifiedDiffRevs(bool bHead)\r
337 {\r
338     Compare (&SVNDiff::ShowUnifiedDiff, &CAppUtils::StartShowUnifiedDiff, bHead);\r
339 }\r
340 \r
341 void CRevisionGraphWnd::DoZoom(float fZoomFactor)\r
342 {\r
343         float oldzoom = m_fZoomFactor;\r
344         m_fZoomFactor = fZoomFactor;\r
345 \r
346     m_nFontSize = max(1, int(12.0f * fZoomFactor));\r
347     if (m_nFontSize < 7)\r
348         m_nFontSize = min (7, int(15.0f * fZoomFactor));\r
349 \r
350         for (int i=0; i<MAXFONTS; i++)\r
351         {\r
352                 if (m_apFonts[i] != NULL)\r
353                 {\r
354                         m_apFonts[i]->DeleteObject();\r
355                         delete m_apFonts[i];\r
356                 }\r
357                 m_apFonts[i] = NULL;\r
358         }\r
359 \r
360         SCROLLINFO si1 = {sizeof(SCROLLINFO), SIF_ALL};\r
361         GetScrollInfo(SB_VERT, &si1);\r
362         SCROLLINFO si2 = {sizeof(SCROLLINFO), SIF_ALL};\r
363         GetScrollInfo(SB_HORZ, &si2);\r
364 \r
365         InitView();\r
366 \r
367         si1.nPos = int(float(si1.nPos)*m_fZoomFactor/oldzoom);\r
368         si2.nPos = int(float(si2.nPos)*m_fZoomFactor/oldzoom);\r
369         SetScrollPos (SB_VERT, si1.nPos);\r
370         SetScrollPos (SB_HORZ, si2.nPos);\r
371 \r
372         Invalidate();\r
373 }\r
374 \r