2 Qanava - Graph drawing library for QT
3 Copyright (C) 2005 Benoit AUTHEMAN
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 //-----------------------------------------------------------------------------
21 // This file is a part of the Qanava software.
24 // \author Benoit Autheman (benoit@faktiss.net)
25 // \date 2004 December 05
26 //-----------------------------------------------------------------------------
34 #include "../utl/utlManager.h"
35 #include "../utl/utlProgress.h"
45 #include "boost/date_time/posix_time/posix_time.hpp"
48 //-----------------------------------------------------------------------------
49 namespace qan
{ // ::qan
50 namespace la
{ // ::qan::la
52 //! Layout a graph in space taking into account group membership (clusters) and respecting a chronological order.
55 <img src="./images/qan-timetree_shot.png" alt="Qanava timetree sample">
59 class TimeTree
: public Layout
63 //! Sort nodes on the basis of their date (older first).
66 bool operator()( const Node
* n1
, const Node
* n2
) const;
69 //! STL set sorting node by date.
70 typedef std::multiset
< la::Node
*, NodeDateComp
> NodeSet
;
72 //! Manager of NodeSet objects.
73 typedef utl::Manager
< NodeSet
> NodeSetManager
;
77 //! Construct the grid for a cluster based time tree graph layout.
83 /*! \name TimeTree Grid Management *///----------------------------
88 GridBuilder( la::Grid
& grid
) : _grid( grid
) { }
92 //! Add _one_ grid element for a given cluster coordinates.
93 void buildClusterGrid( int cy
, int w
, int h
, int r
, int g
, int b
);
95 //! Add all horizontal time grid elements for the given (sorted) nodes.
96 void buildTimeGrid( NodeSet
& nodes
, int width
, int height
);
99 void buildTimeLabel( Node
& node
, int x
, int y
);
102 Grid
& getGrid( ) { return _grid
; }
109 //-----------------------------------------------------------------
114 //! Models a group of nodes in the same track (usually a group equals a cluster of nodes).
122 class GroupMedDateComp
125 bool operator()( const Group
* g1
, const Group
* g2
) const;
136 //! Add a group of nodes corresponding to a line of nodes for a given cluster.
137 /*! The node must be sorted by date ascending order. */
138 void addLine( la::Node::Nodes
* lineNodes
) { _lines
.push_back( lineNodes
); }
140 //! Get the number of lines in this group.
141 int getLineCount( ) const { return _lines
.size( ); }
143 //! Get the ith line in this group.
144 la::Node::Nodes
* getLine( unsigned int line
);
146 //! Collect this group nodes to a given node list (list can be non emtpy).
147 void collectNodes( la::Node::Nodes
& nodes
) const;
149 //! Affect a given style type to all of this group nodes.
150 void setNodesType( int type
);
152 //! Test if a group intersect with this group time interval.
153 bool intersect( const Group
& group
) const;
155 //! Get this group median date.
156 boost::posix_time::ptime
getMedianDate( ) const;
158 typedef std::list
< Group
* > Groups
;
160 typedef std::vector
< la::Node::Nodes
* > Lines
;
162 //! STL multi set with median date group sorting.
163 typedef std::multiset
< Group
*, GroupMedDateComp
> GroupSet
;
167 //! Nodes in each lines must be stored in .
174 //! Models a line of related groups of nodes (the track form a line, but the group in the track can take ultiple single lines).
184 void addGroup( Group
* group
) { _groups
.push_back( group
); }
186 //! Test if a given track time duration interval is disjoint from this track own duration.
187 bool isDisjointOf( Track
& track
);
189 //! Merge a given track groups to this track.
190 void mergeTrack( Track
& track
);
192 typedef std::list
< Track
* > Tracks
;
194 int getLineCount( ) const;
196 float layout( float trackY
, float width
, GridBuilder
& gridBuilder
);
198 //! Collect groups in this track sorted by group's average date.
199 void collectGroups( Group::Groups
& groups
);
201 Group::Groups
& getGroups( ) { return _groups
; }
203 int getNodeCount( ) const;
209 Group::Groups _groups
;
213 //! Sort tracks on the basis of their node (spatial) density.
214 struct TrackDensityComp
216 bool operator()( const Track
* t1
, const Track
* t2
) const;
220 //! Model a series of tracks.
230 void addTrack( Track
* track
);
234 float layout( float width
, GridBuilder
& gridBuilder
);
236 //! Collect all tracks group to a group list in the left-right top to bottom order.
237 void collectGroups( Group::Groups
& groups
);
239 void sortByNodeDensity( );
243 Track::Tracks _tracks
;
247 /*! \name TimeTree Constructor/Destructor *///-------------------------
251 //! TimeTree constructor.
252 TimeTree( NodeSetManager
& nodeSetManager
) :
254 _nodeSetManager( nodeSetManager
) { }
264 NodeSetManager
& _nodeSetManager
;
266 //---------------------------------------------------------------------
270 /*! \name TimeTree Layout Generation Management *///-------------------
276 static float lineIntervalY
;
278 static float trackIntervalY
;
281 virtual void layout( la::Graph
& graph
, la::Grid
& grid
, int width
, int height
, utl::Progress
& progress
);
285 //! Set nodes horizontal position, and return the resulting layout width.
286 float layoutNodesX( NodeSet
& nodes
);
289 Group
* buildGroup( NodeSet
& clusterNodes
);
291 //---------------------------------------------------------------------
295 //-----------------------------------------------------------------------------
298 #endif // laTimeTree_h