#ifndef Dynagraph_h
#define Dynagraph_h
#include "common/LGraph-cdt.h"
#include "common/traversal.h"
#include "common/StrAttr.h"
#include "common/Geometry.h"
#include "common/genpoly.h"
typedef enum {
DG_UPD_MOVE = 1<<0, DG_UPD_REGION = 1<<1, DG_UPD_NAIL = 1<<2, DG_UPD_TAIL = 1<<3, DG_UPD_HEAD = 1<<4, DG_UPD_WIDTH = 1<<5, DG_UPD_LENGTH = 1<<6, DG_UPD_COST = 1<<7, DG_UPD_CONSTRAINT = 1<<8, DG_UPD_LABEL = 1<<9, DG_UPD_BOUNDS = 1<<10, DG_UPD_NESTING = 1<<11, DG_UPD_EDGESTYLE = 1<<12, DG_UPD_RESOLUTION = 1<<13, DG_UPD_SEPARATION = 1<<14, DG_UPD_DRAWN = 1<<15, DG_UPD_POLYDEF = 1<<16 } UpdateFlags;
struct Update { unsigned flags;
Update(unsigned flags = 0) : flags(flags) {}
};
struct ModelPointer {
void *model;
ModelPointer() : model(0) {}
};
struct Drawn : Lines {};
typedef enum {
DG_SPLINELEVEL_VNODE,
DG_SPLINELEVEL_BOUNDS,
DG_SPLINELEVEL_SHORTEST,
DG_SPLINELEVEL_SPLINE
} SpliningLevel;
struct GraphGeom {
Bounds bounds;
SpliningLevel splineLevel;
Coord labelGap; Coord resolution; Coord separation; Coord defaultSize; float ticks; GraphGeom() : splineLevel(DG_SPLINELEVEL_SPLINE),labelGap(0,0),resolution(0.1,0.1),separation(0.5,0.5),defaultSize(1,1),ticks(0) {}
};
struct StaticLabel {
Rect bounds;
};
struct StaticLabels {
std::vector<StaticLabel> labels;
};
typedef enum {
DG_ORIENT_RIGHT,
DG_ORIENT_UP,
DG_ORIENT_LEFT,
DG_ORIENT_DOWN
} Orientation;
struct Translation {
Orientation orientation;
Translation() : orientation(DG_ORIENT_DOWN) {}
};
struct GraphAttrs : Name,StrAttrs2,GraphGeom,Drawn,Translation,StaticLabels,ModelPointer,Hit {};
typedef enum {
DG_NONAIL = 0,
DG_NAIL_X = 1,
DG_NAIL_Y = 2,
DG_NAIL_BOTH = 3
} NailType;
struct NodeGeom {
Position pos;
Region region;
NailType nail;
NodeGeom() : nail(DG_NONAIL) {}
Bounds BoundingBox() {
if(!pos.valid)
return Bounds();
if(region.boundary.valid)
return Bounds(region.boundary+pos);
else
return Bounds(pos);
}
bool Overlaps(const NodeGeom &o) {
return region.Overlaps(pos,o.pos,o.region);
}
};
typedef enum {
DG_NODELABEL_CENTER,
DG_NODELABEL_RIGHT,
DG_NODELABEL_TOP,
DG_NODELABEL_LEFT,
DG_NODELABEL_BOTTOM
} NodeLabelPlacement;
struct NodeLabel {
NodeLabelPlacement where;
Coord size;
Position pos;
NodeLabel(NodeLabelPlacement where = DG_NODELABEL_CENTER, Coord size = Coord(0,0)) :
where(where), size(size) {}
};
struct Port {
Coord pos;
double angle;
Port(Coord pos=Coord(),double angle=0) : pos(pos),angle(angle) {}
};
typedef std::vector<std::pair<int,Port> > IdentifiedPorts;
typedef std::vector<NodeLabel> NodeLabels;
struct IfPolyDef : PolyDef {
bool whether; IfPolyDef() : whether(true) {}
};
struct NodeAttrs : Name,StrAttrs2,NodeGeom,NodeLabels,Hit,IfPolyDef,Drawn,ModelPointer {};
struct EdgeGeom {
double width,lengthHint,cost;
Line pos;
bool constraint, manualRoute; Port tailPort,headPort;
bool tailClipped,headClipped;
EdgeGeom() : width(1.0),lengthHint(1.0),cost(0.0),constraint(true),
manualRoute(false),tailPort(Coord(0.0,0.0)),headPort(Coord(0.0,0.0)),
tailClipped(true),headClipped(true) {}
};
struct EdgeLabel {
double where, length; Line *shape; Position pos1,pos2;
EdgeLabel(double where = 0.5f,double length = 0.0f) : where(where),length(length),shape(0) {}
};
typedef std::vector<EdgeLabel> EdgeLabels;
struct EdgeAttrs : Name,StrAttrs2,EdgeGeom,EdgeLabels,ModelPointer,Hit,Drawn {
};
typedef LGraph<GraphAttrs,NodeAttrs,EdgeAttrs,Update,Update,Update> Layout;
struct ChangeQueue {
Layout * const client, * const current;
Layout insN,modN,delN,
insE,modE,delE;
ChangeQueue(Layout *client,Layout *current);
ChangeQueue(ChangeQueue ©); void InsNode(Layout::Node *n);
void InsEdge(Layout::Edge *e);
void ModNode(Layout::Node *n,Update u); void ModEdge(Layout::Edge *e,Update u);
void DelNode(Layout::Node *n);
void DelEdge(Layout::Edge *e);
unsigned &GraphUpdateFlags() { return igd<Update>(&modN).flags; }
void UpdateCurrent();
void CalcBounds();
void Okay(bool doDelete = false);
bool Empty() { return insN.nodes().empty()&&modN.nodes().empty()&&delN.nodes().empty()&&
insE.nodes().empty()&&modE.nodes().empty()&&delE.nodes().empty()&&GraphUpdateFlags()==0; }
ChangeQueue &operator=(ChangeQueue &Q);
ChangeQueue &operator+=(ChangeQueue &Q);
struct InsertInserted : DGException {
InsertInserted() : DGException("insertion of an already inserted object") {}
};
struct ModifyUninserted : DGException {
ModifyUninserted() : DGException("modify of an uninserted object") {}
};
struct DeleteUninserted : DGException {
DeleteUninserted() : DGException("deletion of an uninserted object") {}
};
struct EndnodesNotInserted : DGException {
EndnodesNotInserted() : DGException("insertion of edge without nodes") {}
};
};
struct Server {
Layout *const client, *const current;
virtual void Process(ChangeQueue &Q) = 0;
Server(Layout *client,Layout *current) : client(client), current(current) {}
virtual ~Server() {}
};
struct CompoundServer : Server {
typedef std::vector<Server*> ServerV;
ServerV actors;
void Process(ChangeQueue &Q);
CompoundServer(Layout *client,Layout *currentLayout) : Server(client,currentLayout) {}
~CompoundServer();
};
struct UpdateCurrent : Server {
UpdateCurrent(Layout *client,Layout *currentLayout) : Server(client,currentLayout) {}
void Process(ChangeQueue &Q) {
Q.UpdateCurrent();
}
};
struct LabelPlacer : Server {
void Process(ChangeQueue &Q);
LabelPlacer(Layout *client,Layout *currentLayout) : Server(client,currentLayout) {}
~LabelPlacer() {}
};
struct ShapeGenerator : Server {
void Process(ChangeQueue &Q);
ShapeGenerator(Layout *client,Layout *currentLayout) : Server(client,currentLayout) {}
~ShapeGenerator() {}
};
struct NailWithoutPos : DGException {
Layout::Node *n;
NailWithoutPos(Layout::Node *n) :
DGException("nailing a node without specifying a position"),
n(n) {}
};
struct BackForth : DGException {
Layout::Edge *e;
BackForth(Layout::Edge *e) : DGException("dynadag can't handle a->b->a (a->b->c->a is okay)"),
e(e) {}
};
#endif