gregoryv/draw

View on GitHub
shape/record.go

Summary

Maintainability
A
1 hr
Test Coverage
package shape

import (
    "io"

    "github.com/gregoryv/draw"
    "github.com/gregoryv/draw/xy"
    "github.com/gregoryv/nexus"
)

func NewRecord(title string) *Record {
    return &Record{
        Title: title,
        Font:  draw.DefaultFont,
        Pad:   draw.DefaultTextPad,
        class: "record",
    }
}

type Record struct {
    x, y    int
    Title   string
    Fields  []string
    Methods []string

    Font  draw.Font
    Pad   draw.Padding
    class string
}

func (r *Record) Position() (x int, y int) { return r.x, r.y }
func (r *Record) SetX(x int)               { r.x = x }
func (r *Record) SetY(y int)               { r.y = y }
func (r *Record) Direction() Direction     { return DirectionRight }
func (r *Record) SetClass(c string)        { r.class = c }

func (r *Record) WriteSVG(out io.Writer) error {
    w, err := nexus.NewPrinter(out)
    w.Printf(
        `<rect class="%s" x="%v" y="%v" width="%v" height="%v"/>`,
        r.class, r.x, r.y, r.Width(), r.Height())
    w.Printf("\n")
    var y = boxHeight(r.Font, r.Pad, 1)
    hasFields := len(r.Fields) != 0
    if hasFields {
        r.writeSeparator(w, r.y+y)
        for _, txt := range r.Fields {
            label := &Label{

                x:     r.x + r.Pad.Left,
                y:     r.y + y,
                Font:  r.Font,
                text:  txt,
                class: "field",
            }
            label.WriteSVG(w)
            y += r.Font.LineHeight
            w.Printf("\n")
        }
    }
    if len(r.Methods) != 0 {
        if hasFields {
            y += r.Pad.Bottom
        }
        r.writeSeparator(w, r.y+y)
        for _, txt := range r.Methods {
            label := &Label{
                x:     r.x + r.Pad.Left,
                y:     r.y + y,
                Font:  r.Font,
                text:  txt,
                class: "method",
            }
            label.WriteSVG(w)
            y += r.Font.LineHeight
            w.Printf("\n")
        }
    }
    r.title().WriteSVG(w)
    return *err
}

func (r *Record) writeSeparator(w io.Writer, y1 int) error {
    line := NewLine(
        r.x, y1,
        r.x+r.Width(), y1,
    )
    line.SetClass("record-line")
    return line.WriteSVG(w)
}

func (r *Record) title() *Label {
    return &Label{
        x:     r.x + r.Pad.Left,
        y:     r.y,
        Font:  r.Font,
        text:  r.Title,
        class: "record-title",
    }
}

func (r *Record) HideFields()  { r.Fields = []string{} }
func (r *Record) HideMethods() { r.Methods = []string{} }

func (r *Record) SetFont(f draw.Font)         { r.Font = f }
func (r *Record) SetTextPad(pad draw.Padding) { r.Pad = pad }

func (r *Record) hasFields() bool  { return len(r.Fields) != 0 }
func (r *Record) hasMethods() bool { return len(r.Methods) != 0 }
func (r *Record) isEmpty() bool    { return !r.hasFields() && !r.hasMethods() }

func (r *Record) HideMethod(m string) (found bool) {
    rest := make([]string, 0)
    for _, n := range r.Methods {
        if n == m {
            found = true
            continue
        }
        rest = append(rest, n)
    }
    r.Methods = rest
    return
}

func (r *Record) Height() int {
    first := boxHeight(r.Font, r.Pad, 1)
    if r.isEmpty() {
        return first
    }
    l := len(r.Fields) + len(r.Methods)
    rest := boxHeight(r.Font, r.Pad, l)
    if r.hasFields() && r.hasMethods() {
        rest += r.Pad.Bottom
    }
    return first + rest
}

func (r *Record) Width() int {
    width := boxWidth(r.Font, r.Pad, r.Title)
    for _, txt := range r.Fields {
        w := boxWidth(r.Font, r.Pad, txt)
        if w > width {
            width = w
        }
    }
    for _, txt := range r.Methods {
        w := boxWidth(r.Font, r.Pad, txt)
        if w > width {
            width = w
        }
    }
    return width
}

// Edge returns intersecting position of a line starting at start and
// pointing to the records center.
func (r *Record) Edge(start xy.Point) xy.Point {
    return boxEdge(start, r)
}