1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2011 - TortoiseSVN
4 // Copyright (C) 2012-2014 - TortoiseGit
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 //#include "RevisionGraph/RevisionGraphState.h"
23 #pragma warning(disable: 4481) // nonstandard extension used: override specifier 'override'
26 #include "ProgressDlg.h"
28 //#include "SVNDiff.h"
31 #include "LogDlgHelper.h"
35 #pragma warning(disable: 4100) // unreferenced formal parameter
36 #include <ogdf/layered/SugiyamaLayout.h>
37 #include <ogdf/layered/OptimalRanking.h>
38 #include <ogdf/layered/MedianHeuristic.h>
39 #include <ogdf/layered/OptimalHierarchyLayout.h>
40 #include <ogdf/layered/FastHierarchyLayout.h>
43 typedef void CVisibleGraphNode
;
46 using namespace Gdiplus
;
47 using namespace async
;
51 REVGRAPH_PREVIEW_WIDTH
= 100,
52 REVGRAPH_PREVIEW_HEIGHT
= 200,
54 // don't draw pre-views with more than that number of nodes
56 REVGRAPH_PREVIEW_MAX_NODES
= 10000
59 // don't try to draw nodes smaller than that:
61 #define REVGRAPH_MIN_NODE_HIGHT (0.5f)
65 // size of the node marker
69 // radius of the rounded / slanted box corners of the expand / collapse / split / join square gylphs
75 DEFAULT_ZOOM_FONT
= 9, // default font size
76 SMALL_ZOOM_FONT
= 11, // rel. larger font size for small zoom factors
77 SMALL_ZOOM_FONT_THRESHOLD
= 6, // max. "small zoom" font size after scaling
79 // size of the expand / collapse / split / join square gylphs
81 GLYPH_BITMAP_SIZE
= 16,
84 // glyph display delay definitions
86 GLYPH_HOVER_EVENT
= 10, // timer ID for the glyph display delay
87 GLYPH_HOVER_DELAY
= 250, // delay until the glyphs are shown [ms]
92 const float MIN_ZOOM
= 0.01f
;
93 const float MAX_ZOOM
= 2.0f
;
94 const float DEFAULT_ZOOM
= 1.0f
;
95 const float ZOOM_STEP
= 0.9f
;
97 // don't draw shadows below this zoom level
99 const float SHADOW_ZOOM_THRESHOLD
= 0.2f
;
102 * \ingroup TortoiseProc
103 * node shapes for the revision graph
114 #define MAX_TT_LENGTH 60000
115 #define MAX_TT_LENGTH_DEFAULT 1000
117 // forward declarations
119 class CRevisionGraphDlg
;
121 // simplify usage of classes from other namespaces
124 //using async::CFuture;
127 * \ingroup TortoiseProc
128 * Window class showing a revision graph.
130 * The analyzation of the log data is done in the child class CRevisionGraph.
131 * Here, we handle the window notifications.
133 class CRevisionGraphWnd
: public CWnd
//, public CRevisionGraph
136 CRevisionGraphWnd(); // standard constructor
137 virtual ~CRevisionGraphWnd();
140 IDD
= IDD_REVISIONGRAPH
,
141 WM_WORKERTHREADDONE
= WM_APP
+1
148 CLogCache m_LogCache
;
149 CLogDataVector m_logEntries
;
150 MAP_HASH_NAME m_HashMap
;
151 CString m_CurrentBranch
;
154 BOOL m_bCurrentBranch
;
155 BOOL m_bLocalBranches
;
162 if (g_Git
.GetMapHashToFriendName(m_HashMap
))
163 MessageBox(g_Git
.GetGitLastErr(_T("Could not get all refs.")), _T("TortoiseGit"), MB_ICONERROR
);
164 m_CurrentBranch
=g_Git
.GetCurrentBranch();
165 if (g_Git
.GetHash(m_HeadHash
, _T("HEAD")))
166 MessageBox(g_Git
.GetGitLastErr(_T("Could not get HEAD hash.")), _T("TortoiseGit"), MB_ICONERROR
);
169 std::auto_ptr
<CFuture
<bool>> updateJob
;
170 // CRevisionGraphState m_state;
173 void Init(CWnd
* pParent
, LPRECT rect
);
174 void SaveGraphAs(CString sSavePath
);
176 bool FetchRevisionData ( const CString
& path
178 , CProgressDlg
* progress
179 , ITaskbarList3
* pTaskbarList
181 bool AnalyzeRevisionData();
182 bool IsUpdateJobRunning() const;
184 bool GetShowOverview() const;
185 void SetShowOverview (bool value
);
187 void GetSelected (const CVisibleGraphNode
* node
, bool head
, CTGitPath
& path
, GitRev
& rev
, GitRev
& peg
);
188 void CompareRevs(const CString
& revTo
);
189 void UnifiedDiffRevs(bool bHead
);
191 CRect
GetGraphRect();
192 CRect
GetClientRect();
193 CRect
GetWindowRect();
195 void DoZoom (float nZoomFactor
, bool updateScrollbars
= true);
196 bool CancelMouseZoom();
198 void SetDlgTitle (bool offline
);
204 CRect m_OverviewPosRect
;
205 CRect m_OverviewRect
;
207 bool m_bShowOverview
;
209 CRevisionGraphDlg
*m_parent
;
211 ogdf::node m_HeadNode
;
212 ogdf::node m_SelectedEntry1
;
213 ogdf::node m_SelectedEntry2
;
214 LOGFONT m_lfBaseFont
;
215 CFont
* m_apFonts
[MAXFONTS
];
217 CToolTipCtrl
* m_pDlgTip
;
218 char m_szTip
[MAX_TT_LENGTH
+1];
219 wchar_t m_wszTip
[MAX_TT_LENGTH
+1];
224 bool m_bTweakTrunkColors
;
225 bool m_bTweakTagsColors
;
226 bool m_bIsCanvasMove
;
227 CPoint m_ptMoveCanvas
;
228 CPoint m_ptRubberEnd
;
235 // index_t m_hoverIndex; // node the cursor currently hovers over
236 ogdf::node m_hoverIndex
;
237 DWORD m_hoverGlyphs
; // the glyphs shown for \ref m_hoverIndex
238 mutable ogdf::node m_tooltipIndex
; // the node index we fetched the tooltip for
239 bool m_showHoverGlyphs
; // if true, show the glyphs we currently hover over
240 // (will be activated only after some delay)
242 CString
GetFriendRefName(ogdf::node
);
243 STRING_VECTOR
GetFriendRefNames(ogdf::node
, CGit::REF_TYPE
*refTypes
= NULL
, int refTypeCount
= 0);
246 ogdf::GraphAttributes m_GraphAttr
;
247 ogdf::SugiyamaLayout m_SugiyamLayout
;
251 int GetLeftRightMargin() {return 20;};
252 int GetTopBottomMargin() {return 5;};
253 virtual void DoDataExchange(CDataExchange
* pDX
); // DDX/DDV support
254 afx_msg
void OnPaint();
255 afx_msg BOOL
OnEraseBkgnd(CDC
* pDC
);
256 afx_msg
void OnHScroll(UINT nSBCode
, UINT nPos
, CScrollBar
* pScrollBar
);
257 afx_msg
void OnVScroll(UINT nSBCode
, UINT nPos
, CScrollBar
* pScrollBar
);
258 afx_msg
void OnSize(UINT nType
, int cx
, int cy
);
259 afx_msg INT_PTR
OnToolHitTest(CPoint point
, TOOLINFO
* pTI
) const;
260 afx_msg
void OnLButtonDown(UINT nFlags
, CPoint point
);
261 afx_msg BOOL
OnToolTipNotify(UINT id
, NMHDR
*pNMHDR
, LRESULT
*pResult
);
262 afx_msg BOOL
OnMouseWheel(UINT nFlags
, short zDelta
, CPoint pt
);
263 afx_msg
void OnMouseHWheel(UINT nFlags
, short zDelta
, CPoint pt
);
264 afx_msg
void OnContextMenu(CWnd
* /*pWnd*/, CPoint
/*point*/);
265 afx_msg
void OnMouseMove(UINT nFlags
, CPoint point
);
266 afx_msg
void OnLButtonUp(UINT nFlags
, CPoint point
);
267 afx_msg BOOL
OnSetCursor(CWnd
* pWnd
, UINT nHitTest
, UINT message
);
268 afx_msg
void OnTimer(UINT_PTR nIDEvent
);
269 afx_msg
void OnCaptureChanged(CWnd
*pWnd
);
270 afx_msg LRESULT
OnWorkerThreadDone(WPARAM
, LPARAM
);
272 DECLARE_MESSAGE_MAP()
288 ExpandGlyph
= 0, // "+"
289 CollapseGlyph
= 1, // "-"
290 SplitGlyph
= 2, // "x"
291 JoinGlyph
= 3, // "o"
316 Graphviz
* pGraphviz
;
322 SVGGrouper(SVG
* pSVG
)
326 m_pSVG
->StartGroup();
339 bool UpdateSelectedEntry (ogdf::node clickedentry
);
340 void AppendMenu (CMenu
& popup
, UINT title
, UINT command
, UINT flags
= MF_ENABLED
);
341 void AppendMenu (CMenu
&popup
, CString title
, UINT command
, CString
*extra
= NULL
, CMenu
*submenu
= NULL
);
342 void AddGitOps (CMenu
& popup
);
343 void AddGraphOps (CMenu
& popup
, const CVisibleGraphNode
* node
);
344 CString
GetSelectedURL() const;
345 CString
GetWCURL() const;
347 void DoCheckForModification();
350 void DoSwitch(CString rev
);
351 void DoSwitchToHead();
353 void ResetNodeFlags (DWORD flags
);
354 void ToggleNodeFlag (const CVisibleGraphNode
*node
, DWORD flag
);
357 void SetScrollbar (int bar
, int newPos
, int clientMax
, int graphMax
);
358 void SetScrollbars (int nVert
= -1, int nHorz
= -1);
359 CFont
* GetFont(BOOL bItalic
= FALSE
, BOOL bBold
= FALSE
);
361 CSize
UsableTooltipRect();
362 CString
DisplayableText (const CString
& wholeText
, const CSize
& tooltipSize
);
363 CString
TooltipText (ogdf::node index
);
365 CPoint
GetLogCoordinates (CPoint point
) const;
366 ogdf::node
GetHitNode (CPoint point
, CSize border
= CSize (0, 0)) const;
367 DWORD
GetHoverGlyphs (CPoint point
) const;
368 PointF
cutPoint(ogdf::node v
,double lw
,PointF ps
, PointF pt
);
370 // const CRevisionGraphState::SVisibleGlyph* GetHitGlyph (CPoint point) const;
372 void ClearVisibleGlyphs (const CRect
& rect
);
374 typedef PointF TCutRectangle
[8];
375 void CutawayPoints (const RectF
& rect
, float cutLen
, TCutRectangle
& result
);
382 void DrawRoundedRect (GraphicsDevice
& graphics
, const Color
& penColor
, int penWidth
, const Pen
* pen
, const Color
& fillColor
, const Brush
* brush
, const RectF
& rect
, int mask
=ROUND_BOTH
);
383 void DrawOctangle (GraphicsDevice
& graphics
, const Color
& penColor
, int penWidth
, const Pen
* pen
, const Color
& fillColor
, const Brush
* brush
, const RectF
& rect
);
384 void DrawShape (GraphicsDevice
& graphics
, const Color
& penColor
, int penWidth
, const Pen
* pen
, const Color
& fillColor
, const Brush
* brush
, const RectF
& rect
, NodeShape shape
);
385 void DrawShadow(GraphicsDevice
& graphics
, const RectF
& rect
,
386 Color shadowColor
, NodeShape shape
);
387 void DrawNode(GraphicsDevice
& graphics
, const RectF
& rect
,
388 Color contour
, Color overlayColor
,
389 const CVisibleGraphNode
*node
, NodeShape shape
);
390 RectF
TransformRectToScreen (const CRect
& rect
, const CSize
& offset
) const;
391 RectF
GetNodeRect (const ogdf::node
& v
, const CSize
& offset
) const;
392 // RectF GetBranchCover (const ILayoutNodeList* nodeList, index_t nodeIndex, bool upward, const CSize& offset);
394 void DrawSquare (GraphicsDevice
& graphics
, const PointF
& leftTop
,
395 const Color
& lightColor
, const Color
& darkColor
, const Color
& penColor
);
396 void DrawGlyph (GraphicsDevice
& graphics
, Image
* glyphs
, const PointF
& leftTop
,
397 GlyphType glyph
, GlyphPosition position
);
398 void DrawGlyphs (GraphicsDevice
& graphics
, Image
* glyphs
, const CVisibleGraphNode
* node
, const PointF
& center
,
399 GlyphType glyph1
, GlyphType glyph2
, GlyphPosition position
, DWORD state1
, DWORD state2
, bool showAll
);
400 void DrawGlyphs (GraphicsDevice
& graphics
, Image
* glyphs
, const CVisibleGraphNode
* node
, const RectF
& nodeRect
,
401 DWORD state
, DWORD allowed
, bool upsideDown
);
402 void DrawMarker ( GraphicsDevice
& graphics
, const RectF
& noderect
403 , MarkerPosition position
, int relPosition
, const Color
& penColor
, int num
);
404 // void IndicateGlyphDirection ( GraphicsDevice& graphics, const ILayoutNodeList* nodeList
405 // , const ILayoutNodeList::SNode& node, const RectF& nodeRect
406 // , DWORD glyphs, bool upsideDown, const CSize& offset);
408 void DrawStripes (GraphicsDevice
& graphics
, const CSize
& offset
);
410 void DrawShadows (GraphicsDevice
& graphics
, const CRect
& logRect
, const CSize
& offset
);
411 void DrawNodes (GraphicsDevice
& graphics
, Image
* glyphs
, const CRect
& logRect
, const CSize
& offset
);
412 void DrawConnections (GraphicsDevice
& graphics
, const CRect
& logRect
, const CSize
& offset
);
413 void DrawTexts (GraphicsDevice
& graphics
, const CRect
& logRect
, const CSize
& offset
);
414 void DrawCurrentNodeGlyphs (GraphicsDevice
& graphics
, Image
* glyphs
, const CSize
& offset
);
415 void DrawGraph(GraphicsDevice
& graphics
, const CRect
& rect
, int nVScrollPos
, int nHScrollPos
, bool bDirectDraw
);
417 int GetEncoderClsid(const WCHAR
* format
, CLSID
* pClsid
);
418 void DrawRubberBand();
419 void SetNodeRect(GraphicsDevice
& graphics
, ogdf::node
*pnode
, CGitHash rev
, int mode
= 0);