design

package
v0.33.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 21, 2023 License: MIT Imports: 10 Imported by: 3

README

design - package for writing software design diagrams

Sequence diagram

var (
    d   = design.NewSequenceDiagram()
    cli = d.AddStruct(app.Client{})
    srv = d.AddStruct(app.Server{})
    db  = d.AddStruct(sql.DB{})
)
d.Link(cli, srv, "connect()")
d.Link(srv, db, "SELECT").Class = "highlight"
d.Link(db, srv, "Rows")
d.Link(srv, srv, "Transform to view model").Class = "highlight"
d.Skip()
d.Return(srv, cli, "Send HTML")

Activity diagram

Rendered by ExampleActivityDiagram

Class diagram

Class diagrams show relations between structs and interfaces. Reflection includes fields and methods.

This diagram is rendered by ExampleClassDiagram

Generic diagram

It should be easy to just add any extra shapes to any diagram when explaining a design. This diagram is rendered by ExampleDiagram

Grid layout

Simplifying placing shapes in a grid layout aligning different sizes of shapes.

Gantt chart

ExampleGanttChart

Showcase

You can find more examples in the showcase folder.

Documentation

Overview

Package design provides diagram creators

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ActivityDiagram

type ActivityDiagram struct {
	*Diagram

	Spacing int
	// contains filtered or unexported fields
}
Example
package main

import (
	"github.com/gregoryv/draw/design"
)

func main() {
	d := design.NewActivityDiagram()

	d.Start().At(80, 20)
	d.Trans("push", "Commited")
	d.Trans("run git hook", "Build complete")

	test := d.Decide("unit test")
	d.TransRight("fails", "EXIT")

	d.Or(test)
	d.Trans("ok", "Verified")

	d.Trans("deploy to stage", "Deployed")

	itest := d.Decide("integration test")
	d.TransRight("fails", "EXIT")

	d.Or(itest)
	d.Trans("ok", "Verified")

	d.SaveAs("img/activity_diagram.svg")
}
Output:

func NewActivityDiagram

func NewActivityDiagram() *ActivityDiagram

func (*ActivityDiagram) Decide

func (d *ActivityDiagram) Decide(action ...string) *shape.Diamond

Decide adds a diamond below the last activity

func (*ActivityDiagram) Exit

func (d *ActivityDiagram) Exit(action ...string) *shape.ExitDot

Exit adds an ExitDot below the last activity

func (d *ActivityDiagram) Link(from, to shape.Shape, action ...string) *shape.Line

Link places an arrow with a optional label above it between the two shapes.

func (*ActivityDiagram) LinkAll

func (d *ActivityDiagram) LinkAll(s ...shape.Shape)

LinkAll places arrows between each shape, s0->s1->...->sn

func (*ActivityDiagram) Or added in v0.21.0

func (d *ActivityDiagram) Or(next shape.Shape)

func (*ActivityDiagram) Place

func (d *ActivityDiagram) Place(next ...shape.Shape) *shape.Adjuster

func (*ActivityDiagram) Start

func (d *ActivityDiagram) Start() *shape.Adjuster

func (*ActivityDiagram) Trans added in v0.21.0

func (d *ActivityDiagram) Trans(action, label string) *shape.Adjuster

When adds a new state below the last one

func (*ActivityDiagram) TransRight added in v0.21.0

func (d *ActivityDiagram) TransRight(action, label string) *shape.Adjuster

WhenRight adds a new right of last state

type ClassDiagram

type ClassDiagram struct {
	*Diagram
	// contains filtered or unexported fields
}
Example
package main

import (
	"github.com/gregoryv/draw"
	"github.com/gregoryv/draw/design"
	"github.com/gregoryv/draw/shape"
	"github.com/gregoryv/draw/xy"
)

func main() *design.ClassDiagram {
	var (
		d        = design.NewClassDiagram()
		point    = d.Struct(xy.Point{})
		record   = d.Struct(shape.Record{})
		circle   = d.Struct(shape.Circle{})
		diamond  = d.Struct(shape.Diamond{})
		triangle = d.Struct(shape.Triangle{})
		shapE    = d.Interface((*shape.Shape)(nil))
	)
	d.SetScale(1.2)
	d.HideRealizations()

	var (
		fnt      = d.Struct(draw.Font{})
		style    = d.Struct(draw.Style{})
		seqdia   = d.Struct(design.SequenceDiagram{})
		classdia = d.Struct(design.ClassDiagram{})
		dia      = d.Struct(design.Diagram{})
		aligner  = d.Struct(shape.Aligner{})
		adj      = d.Struct(shape.Adjuster{})
		rel      = d.Struct(design.Relation{})
	)
	d.HideRealizations()

	d.Place(shapE).At(280, 20)
	d.Place(record).At(20, 260)

	d.Place(diamond).RightOf(shapE, 200)
	d.Place(circle).Below(diamond, 50)
	d.Place(triangle).Below(circle)
	d.Place(point).RightOf(circle, 100)

	d.Place(fnt).Below(record, 120)
	d.Place(style).RightOf(fnt, 90)
	d.VAlignCenter(record, fnt)

	d.Place(rel).Below(shapE, 20)
	d.Place(dia).RightOf(style, 70)
	d.Place(adj).RightOf(dia, 60)
	d.Place(aligner).RightOf(dia, 60)
	d.HAlignCenter(fnt, style, dia, aligner)
	d.HAlignCenter(record, rel)
	d.HAlignTop(dia, adj)
	shape.Move(adj, 0, -60)

	d.Place(seqdia).Below(aligner, 90)
	d.Place(classdia).Below(dia, 90)
	d.VAlignCenter(dia, classdia)
	d.HAlignBottom(classdia, seqdia)

	d.HAlignCenter(circle, point)

	d.SetCaption("Figure 1. Class diagram of design and design.shape packages")
	d.SaveAs("img/class_example.svg")
	return d
}
Output:

func NewClassDiagram

func NewClassDiagram() *ClassDiagram

NewClassDiagram returns a diagram representing structs and interfaces. Relations are reflected from the types and drawn as arrows.

func (*ClassDiagram) HideRealizations

func (d *ClassDiagram) HideRealizations()

HideRealizations hides all methods of structs that implement a visible interface.

func (*ClassDiagram) Inline added in v0.15.1

func (d *ClassDiagram) Inline() string

Inline returns rendered SVG with inlined style

func (*ClassDiagram) Interface

func (d *ClassDiagram) Interface(obj interface{}) VRecord

func (*ClassDiagram) SaveAs

func (d *ClassDiagram) SaveAs(filename string) error

SaveAs saves the diagram to filename as SVG

func (*ClassDiagram) Slice added in v0.17.0

func (d *ClassDiagram) Slice(obj interface{}) VRecord

func (*ClassDiagram) String added in v0.15.0

func (d *ClassDiagram) String() string

String returns rendered SVG

func (*ClassDiagram) Struct

func (d *ClassDiagram) Struct(obj interface{}) VRecord

func (*ClassDiagram) WriteSVG

func (d *ClassDiagram) WriteSVG(w io.Writer) error

WriteSVG renders the diagram as SVG to the given writer.

type Diagram

type Diagram struct {
	draw.SVG
	shape.Aligner
	draw.Style
	// contains filtered or unexported fields
}

Diagram is a generic SVG image with box related styling

Example
package main

import (
	"github.com/gregoryv/draw/design"
	"github.com/gregoryv/draw/shape"
)

func main() {
	var (
		record     = shape.NewRecord("Record")
		x, y       = 130, 80
		q1arrow    = shape.NewLine(x, y, x+50, y-10)
		q2arrow    = shape.NewLine(x, y, x-30, y-10)
		q3arrow    = shape.NewLine(x, y, x-50, y+20)
		q4arrow    = shape.NewLine(x, y, x+40, y+20)
		rightarrow = shape.NewLine(x, y, x+90, y)
		leftarrow  = shape.NewLine(x, y, x-50, y)
		uparrow    = shape.NewLine(x, y, x, y-40)
		downarrow  = shape.NewLine(x, y, x, y+40)
		label      = shape.NewLabel("Label")
		withtail   = shape.NewLine(20, 100, 150, 100)
		diaarrow   = shape.NewLine(20, 120, 150, 120)
		note       = shape.NewNote(`Notes support
multilines`)
		comp   = shape.NewComponent("database")
		srv    = shape.NewComponent("service")
		circle = shape.NewCircle(10)
		dot    = shape.NewDot()
		exit   = shape.NewExitDot()
		rect   = shape.NewRect("Rect")
		state  = shape.NewState("Waiting for go routine")
		d      = design.NewDiagram()
	)
	d.Place(record).At(10, 30)
	for _, arrow := range []*shape.Line{
		q1arrow, q2arrow, q3arrow, q4arrow,
		rightarrow, leftarrow,
		uparrow, downarrow,
	} {
		d.Place(arrow)
	}
	d.Place(label).RightOf(record, 150)
	withtail.Tail = shape.NewCircle(3)
	d.Place(withtail).At(20, 150)
	diaarrow.Tail = shape.NewDiamond()
	d.Place(diaarrow).Below(withtail)
	d.Place(note).Below(diaarrow)
	d.Place(circle).Below(note)
	d.Place(dot).RightOf(circle)
	d.Place(exit).RightOf(dot)
	d.HAlignCenter(circle, dot, exit)
	d.LinkAll(circle, dot, exit)
	d.Place(comp).RightOf(diaarrow)
	d.Place(rect).Below(circle)
	d.Place(state).RightOf(rect)
	d.Place(srv).Below(comp)
	d.VAlignCenter(comp, srv)
	d.Link(srv, comp, "")

	// labeled arrows
	d1 := shape.NewDot()
	d.Place(d1).At(600, 200)

	d2 := shape.NewDot()
	d.Place(d2).RightOf(d1, 120)
	d.Link(d1, d2, "label")

	d2 = shape.NewDot()
	d.Place(d2).At(660, 260)
	d.Link(d1, d2, "label")

	d2 = shape.NewDot()
	d.Place(d2).Below(d1, 120)
	d.Link(d1, d2, "label")

	d2 = shape.NewDot()
	d.Place(d2).At(520, 280)
	d.Link(d1, d2, "label")

	d2 = shape.NewDot()
	d.Place(d2).LeftOf(d1, 120)
	d.Link(d1, d2, "label")

	d2 = shape.NewDot()
	d.Place(d2).At(520, 120)
	d.Link(d1, d2, "label")

	d2 = shape.NewDot()
	d.Place(d2).Above(d1, 120)
	d.Link(d1, d2, "label")

	d2 = shape.NewDot()
	d.Place(d2).At(660, 120)
	d.Link(d1, d2, "label")

	d.SaveAs("img/diagram_example.svg")
}
Output:

func NewDiagram

func NewDiagram() *Diagram

NewDiagram returns a diagram with present font and padding values.

TODO: size and padding affects eg. records, but is related to the styling

func (*Diagram) AdaptSize

func (d *Diagram) AdaptSize() (int, int)

AdaptSize adapts the diagram size to the shapes inside it so all are visible. Returns the new width and height

func (*Diagram) Caption

func (d *Diagram) Caption() *shape.Label

func (*Diagram) Inline added in v0.15.0

func (d *Diagram) Inline() string

Inline returns rendered SVG with inlined style

func (d *Diagram) Link(from, to shape.Shape, txt ...string) (lnk *shape.Line, label *shape.Label)

Link places an arrow with a optional label above it between the two shapes.

func (*Diagram) LinkAll

func (d *Diagram) LinkAll(s ...shape.Shape)

LinkAll places arrows between each shape, s0->s1->...->sn

func (*Diagram) Note added in v0.24.0

func (d *Diagram) Note(v string) *shape.Adjuster

Note is a convenience method to add a shape.Note to a diagram

func (*Diagram) Place

func (d *Diagram) Place(s ...shape.Shape) *shape.Adjuster

Place adds the shape to the diagram returning an adjuster for positioning.

func (*Diagram) PlaceGrid

func (d *Diagram) PlaceGrid(cols, X, Y int, s ...shape.Shape)

PlaceGrid place all the shapes into a grid starting at X,Y position. Row height is adapted to highest element.

func (*Diagram) SaveAs

func (d *Diagram) SaveAs(filename string) error

SaveAs saves the diagram to filename as SVG

func (*Diagram) SetCaption

func (d *Diagram) SetCaption(txt string)

SetCaption adds a caption to the bottom of the diagram.

func (*Diagram) String added in v0.15.0

func (d *Diagram) String() string

String returns rendered SVG

func (*Diagram) WriteSVG

func (d *Diagram) WriteSVG(w io.Writer) error

type GanttAdjuster

type GanttAdjuster struct {
	// contains filtered or unexported fields
}

func (*GanttAdjuster) After

func (a *GanttAdjuster) After(parent *Task, days int)

func (*GanttAdjuster) At

func (a *GanttAdjuster) At(from date.String, days int)

type GanttChart

type GanttChart struct {
	*Diagram

	// Set a marker at this date.
	Mark time.Time

	Weeks bool
	// contains filtered or unexported fields
}
Example
package main

import (
	"github.com/gregoryv/draw/design"
)

func main() {
	var (
		d   = design.NewGanttChart("20191111", 30)
		dev = d.Add("Develop")
		rel = d.Add("Release").Red()
		vac = d.Add("Vacation").Blue()
	)
	d.MarkDate("20191120")
	d.Place(dev).At("20191111", 10)
	d.Place(rel).After(dev, 1)
	d.Place(vac).At("20191125", 14)
	d.SetCaption("Figure 1. Project estimated delivery")
	d.SaveAs("img/gantt_chart.svg")
}
Output:

Example (Year)
package main

import (
	"github.com/gregoryv/draw/design"
)

func main() {
	var (
		d   = design.NewGanttChart("20191111", 365)
		dev = d.Add("Develop")
		rel = d.Add("Release").Red()
		vac = d.Add("Vacation").Blue()
	)
	d.Weeks = true
	d.MarkDate("20200404")
	d.Place(dev).At("20191111", 60)
	d.Place(rel).After(dev, 1)
	d.Place(vac).At("20200404", 21)
	d.SetCaption("Figure 1. Project estimated delivery")
	d.SaveAs("img/gantt_year.svg")
}
Output:

func NewGanttChart

func NewGanttChart(from date.String, days int) *GanttChart

NewGanttChart returns a GanttChart spanning days from the given date. Panics if date cannot be resolved.

func (*GanttChart) Add

func (g *GanttChart) Add(txt string) *Task

Add new task from start spanning 3 days. Default color is green.

func (*GanttChart) Inline added in v0.15.0

func (d *GanttChart) Inline() string

Inline returns rendered SVG with inlined style

func (*GanttChart) MarkDate

func (g *GanttChart) MarkDate(yyyymmdd date.String)

func (*GanttChart) Place

func (g *GanttChart) Place(task *Task) *GanttAdjuster

Add new task. Default color is green.

func (*GanttChart) SaveAs

func (d *GanttChart) SaveAs(filename string) error

func (*GanttChart) String added in v0.15.0

func (d *GanttChart) String() string

String returns rendered SVG

func (*GanttChart) WriteSVG

func (d *GanttChart) WriteSVG(w io.Writer) error
type Link struct {
	Class     string
	TextClass string
	// contains filtered or unexported fields
}

Link represents an arrow in a sequence diagram

type Relation

type Relation struct {
	// contains filtered or unexported fields
}

Relation defines a relation between two records

type SequenceDiagram

type SequenceDiagram struct {
	*Diagram
	ColWidth int
	VMargin  int // top margin for each horizontal lane
	// contains filtered or unexported fields
}

SequenceDiagram defines columns and links between columns.

Example
package main

import (
	"database/sql"

	"github.com/gregoryv/draw/design"
	"github.com/gregoryv/draw/internal/app"
)

func main() {
	var (
		d   = design.NewSequenceDiagram()
		cli = d.AddStruct(app.Client{})
		srv = d.AddStruct(app.Server{})
		db  = d.AddStruct(sql.DB{})
	)
	d.Group(cli, srv, "Public https", "blue") // default colors classes red, green, blue
	d.Group(srv, db, "Private rpc via Gob", "red")

	d.Link(cli, srv, "connect()")
	d.Link(srv, db, "SELECT").Class = "highlight"
	d.Link(db, srv, "Rows")
	d.Link(srv, srv, "Transform to view model").Class = "highlight"
	d.Skip()
	d.Return(srv, cli, "Send HTML")
	d.SaveAs("img/app_sequence_diagram.svg")
}
Output:

func NewSequenceDiagram

func NewSequenceDiagram() *SequenceDiagram

NewSequenceDiagram returns a sequence diagram with default column width.

func (*SequenceDiagram) Add

func (d *SequenceDiagram) Add(name string) string

Add the name as next column and return name.

func (*SequenceDiagram) AddColumns

func (d *SequenceDiagram) AddColumns(names ...string)

AddColumns adds the names as columns in the given order.

func (*SequenceDiagram) AddInterface

func (d *SequenceDiagram) AddInterface(obj interface{}) string

func (*SequenceDiagram) AddStruct

func (d *SequenceDiagram) AddStruct(obj interface{}) string
func (d *SequenceDiagram) ClearLinks()

func (*SequenceDiagram) Group added in v0.17.0

func (me *SequenceDiagram) Group(fromColumn, toColumn, text, class string)

Group adds a colored area below span of columns. Predefined classes are red, green, blue.

func (*SequenceDiagram) Height

func (d *SequenceDiagram) Height() int

Height returns the total height of the diagram

func (*SequenceDiagram) Inline added in v0.15.0

func (d *SequenceDiagram) Inline() string

Inline returns rendered SVG with inlined style

func (d *SequenceDiagram) Link(from, to, text string) *Link

Link adds a link between from and to indicating a func call or data flow.

func (*SequenceDiagram) Return added in v0.23.0

func (d *SequenceDiagram) Return(from, to, text string) *Link

Return adds a link between from and to indicating a return signal.

func (*SequenceDiagram) SaveAs

func (d *SequenceDiagram) SaveAs(filename string) error

func (*SequenceDiagram) Skip added in v0.20.0

func (d *SequenceDiagram) Skip()

Skip adds dotted distance on all columns

func (*SequenceDiagram) String added in v0.15.0

func (d *SequenceDiagram) String() string

String returns rendered SVG

func (*SequenceDiagram) Width

func (d *SequenceDiagram) Width() int

Width returns the total width of the diagram

func (*SequenceDiagram) WriteSVG

func (d *SequenceDiagram) WriteSVG(w io.Writer) error

WriteSvg renders the diagram as SVG to the given writer.

type Task

type Task struct {
	// contains filtered or unexported fields
}

Task is the colorized span of a gantt chart.

func NewTask

func NewTask(txt string) *Task

NewTask returns a green task.

func (*Task) Blue

func (t *Task) Blue() *Task

Blue sets class of task to span-blue

func (*Task) Red

func (t *Task) Red() *Task

Red sets class of task to span-red

type VRecord

type VRecord struct {
	*shape.Record
	// contains filtered or unexported fields
}

VRecord represents a type struct or interface as a record shape.

func NewDetailedVRecord added in v0.23.0

func NewDetailedVRecord(v interface{}) *VRecord

NewDetailedVRecord returns a VRecord including method argument and return types.

func NewVRecord

func NewVRecord(v interface{}) *VRecord

func (*VRecord) Aggregates

func (vr *VRecord) Aggregates(d *VRecord) bool

func (*VRecord) ComposedOf

func (vr *VRecord) ComposedOf(d *VRecord) bool

todo shouldn't composedOf be the inverse of aggregates

func (*VRecord) Implements

func (vr *VRecord) Implements(iface *VRecord) bool

func (*VRecord) TitleOnly

func (vr *VRecord) TitleOnly()

TitleOnly hides fields and methods.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL