diff options
Diffstat (limited to 'examples/go-dashboard/src/github.com/mum4k/termdash/container/draw.go')
-rw-r--r-- | examples/go-dashboard/src/github.com/mum4k/termdash/container/draw.go | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/examples/go-dashboard/src/github.com/mum4k/termdash/container/draw.go b/examples/go-dashboard/src/github.com/mum4k/termdash/container/draw.go new file mode 100644 index 000000000..d186b1272 --- /dev/null +++ b/examples/go-dashboard/src/github.com/mum4k/termdash/container/draw.go @@ -0,0 +1,175 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package container + +// draw.go contains logic to draw containers and the contained widgets. + +import ( + "errors" + "fmt" + "image" + + "github.com/mum4k/termdash/cell" + "github.com/mum4k/termdash/private/area" + "github.com/mum4k/termdash/private/canvas" + "github.com/mum4k/termdash/private/draw" + "github.com/mum4k/termdash/widgetapi" +) + +// drawTree draws this container and all of its sub containers. +func drawTree(c *Container) error { + var errStr string + + root := rootCont(c) + size := root.term.Size() + ar, err := root.opts.margin.apply(image.Rect(0, 0, size.X, size.Y)) + if err != nil { + return err + } + root.area = ar + + preOrder(root, &errStr, visitFunc(func(c *Container) error { + first, second, err := c.split() + if err != nil { + return err + } + if c.first != nil { + ar, err := c.first.opts.margin.apply(first) + if err != nil { + return err + } + c.first.area = ar + } + + if c.second != nil { + ar, err := c.second.opts.margin.apply(second) + if err != nil { + return err + } + c.second.area = ar + } + return drawCont(c) + })) + if errStr != "" { + return errors.New(errStr) + } + return nil +} + +// drawBorder draws the border around the container if requested. +func drawBorder(c *Container) error { + if !c.hasBorder() { + return nil + } + + cvs, err := canvas.New(c.area) + if err != nil { + return err + } + + ar, err := area.FromSize(cvs.Size()) + if err != nil { + return err + } + + var cOpts []cell.Option + if c.focusTracker.isActive(c) { + cOpts = append(cOpts, cell.FgColor(c.opts.inherited.focusedColor)) + } else { + cOpts = append(cOpts, cell.FgColor(c.opts.inherited.borderColor)) + } + + if err := draw.Border(cvs, ar, + draw.BorderLineStyle(c.opts.border), + draw.BorderTitle(c.opts.borderTitle, draw.OverrunModeThreeDot, cOpts...), + draw.BorderTitleAlign(c.opts.borderTitleHAlign), + draw.BorderCellOpts(cOpts...), + ); err != nil { + return err + } + return cvs.Apply(c.term) +} + +// drawWidget requests the widget to draw on the canvas. +func drawWidget(c *Container) error { + widgetArea, err := c.widgetArea() + if err != nil { + return err + } + if widgetArea == image.ZR { + return nil + } + + if !c.hasWidget() { + return nil + } + + needSize := image.Point{1, 1} + wOpts := c.opts.widget.Options() + if wOpts.MinimumSize.X > 0 && wOpts.MinimumSize.Y > 0 { + needSize = wOpts.MinimumSize + } + + if widgetArea.Dx() < needSize.X || widgetArea.Dy() < needSize.Y { + return drawResize(c, c.usable()) + } + + cvs, err := canvas.New(widgetArea) + if err != nil { + return err + } + + meta := &widgetapi.Meta{ + Focused: c.focusTracker.isActive(c), + } + + if err := c.opts.widget.Draw(cvs, meta); err != nil { + return err + } + return cvs.Apply(c.term) +} + +// drawResize draws an unicode character indicating that the size is too small to draw this container. +// Does nothing if the size is smaller than one cell, leaving no space for the character. +func drawResize(c *Container, area image.Rectangle) error { + if area.Dx() < 1 || area.Dy() < 1 { + return nil + } + + cvs, err := canvas.New(area) + if err != nil { + return err + } + if err := draw.ResizeNeeded(cvs); err != nil { + return err + } + return cvs.Apply(c.term) +} + +// drawCont draws the container and its widget. +func drawCont(c *Container) error { + if us := c.usable(); us.Dx() <= 0 || us.Dy() <= 0 { + return drawResize(c, c.area) + } + + if err := drawBorder(c); err != nil { + return fmt.Errorf("unable to draw container border: %v", err) + } + + if err := drawWidget(c); err != nil { + return fmt.Errorf("unable to draw widget %T: %v", c.opts.widget, err) + } + return nil +} |