2015-03-20 14:21:50 -06:00
|
|
|
// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
|
|
|
|
// Use of this source code is governed by a MIT license that can
|
|
|
|
// be found in the LICENSE file.
|
|
|
|
|
2015-02-03 12:13:51 -07:00
|
|
|
package termui
|
|
|
|
|
2015-04-21 07:56:10 -06:00
|
|
|
import "image"
|
|
|
|
|
2015-03-24 15:16:43 -06:00
|
|
|
// Block is a base struct for all other upper level widgets,
|
|
|
|
// consider it as css: display:block.
|
|
|
|
// Normally you do not need to create it manually.
|
2015-02-03 18:56:49 -07:00
|
|
|
type Block struct {
|
2015-04-21 07:56:10 -06:00
|
|
|
Area image.Rectangle
|
|
|
|
innerArea image.Rectangle
|
2015-02-04 14:57:24 -07:00
|
|
|
X int
|
|
|
|
Y int
|
2015-04-21 07:56:10 -06:00
|
|
|
Border LabeledBorder
|
2015-02-04 14:57:24 -07:00
|
|
|
IsDisplay bool
|
|
|
|
HasBorder bool
|
2015-04-21 07:56:10 -06:00
|
|
|
Bg Attribute
|
2015-02-04 14:57:24 -07:00
|
|
|
Width int
|
|
|
|
Height int
|
|
|
|
PaddingTop int
|
|
|
|
PaddingBottom int
|
|
|
|
PaddingLeft int
|
|
|
|
PaddingRight int
|
2015-02-03 12:13:51 -07:00
|
|
|
}
|
|
|
|
|
2015-03-24 15:16:43 -06:00
|
|
|
// NewBlock returns a *Block which inherits styles from current theme.
|
2015-02-03 18:56:49 -07:00
|
|
|
func NewBlock() *Block {
|
|
|
|
d := Block{}
|
2015-02-03 12:13:51 -07:00
|
|
|
d.IsDisplay = true
|
2015-03-11 14:15:59 -06:00
|
|
|
d.HasBorder = theme.HasBorder
|
2015-04-21 07:56:10 -06:00
|
|
|
d.Border.Left = true
|
|
|
|
d.Border.Right = true
|
|
|
|
d.Border.Top = true
|
|
|
|
d.Border.Bottom = true
|
|
|
|
d.Border.Bg = theme.BorderBg
|
|
|
|
d.Border.Fg = theme.BorderFg
|
|
|
|
d.Border.LabelBgClr = theme.BorderLabelTextBg
|
|
|
|
d.Border.LabelFgClr = theme.BorderLabelTextFg
|
|
|
|
d.Bg = theme.BlockBg
|
2015-02-03 12:13:51 -07:00
|
|
|
d.Width = 2
|
|
|
|
d.Height = 2
|
2015-02-03 18:56:49 -07:00
|
|
|
return &d
|
2015-02-03 12:13:51 -07:00
|
|
|
}
|
|
|
|
|
2015-04-21 07:56:10 -06:00
|
|
|
// Align computes box model
|
|
|
|
func (d *Block) Align() {
|
|
|
|
d.Area.Min.X = d.X
|
|
|
|
d.Area.Min.Y = d.Y
|
|
|
|
d.Area.Max.X = d.X + d.Width - 1
|
|
|
|
d.Area.Max.Y = d.Y + d.Height - 1
|
2015-02-03 12:13:51 -07:00
|
|
|
|
2015-04-21 07:56:10 -06:00
|
|
|
d.innerArea.Min.X = d.X + d.PaddingLeft
|
|
|
|
d.innerArea.Min.Y = d.Y + d.PaddingTop
|
|
|
|
d.innerArea.Max.X = d.Area.Max.X - d.PaddingRight
|
|
|
|
d.innerArea.Max.Y = d.Area.Max.Y - d.PaddingBottom
|
2015-03-28 10:58:23 -06:00
|
|
|
|
2015-04-21 07:56:10 -06:00
|
|
|
d.Border.Area = d.Area
|
2015-03-28 10:58:23 -06:00
|
|
|
|
2015-04-21 07:56:10 -06:00
|
|
|
if d.HasBorder {
|
|
|
|
switch {
|
|
|
|
case d.Border.Left:
|
|
|
|
d.innerArea.Min.X++
|
|
|
|
fallthrough
|
|
|
|
case d.Border.Right:
|
|
|
|
d.innerArea.Max.X--
|
|
|
|
fallthrough
|
|
|
|
case d.Border.Top:
|
|
|
|
d.innerArea.Min.Y++
|
|
|
|
fallthrough
|
|
|
|
case d.Border.Bottom:
|
|
|
|
d.innerArea.Max.Y--
|
|
|
|
}
|
|
|
|
}
|
2015-02-03 12:13:51 -07:00
|
|
|
}
|
|
|
|
|
2015-04-08 20:19:43 -06:00
|
|
|
// InnerBounds returns the internal bounds of the block after aligning and
|
|
|
|
// calculating the padding and border, if any.
|
2015-04-21 07:56:10 -06:00
|
|
|
func (d *Block) InnerBounds() image.Rectangle {
|
|
|
|
d.Align()
|
|
|
|
return d.innerArea
|
2015-04-08 20:19:43 -06:00
|
|
|
}
|
|
|
|
|
2015-03-24 15:16:43 -06:00
|
|
|
// Buffer implements Bufferer interface.
|
|
|
|
// Draw background and border (if any).
|
2015-04-21 07:56:10 -06:00
|
|
|
func (d *Block) Buffer() Buffer {
|
|
|
|
d.Align()
|
2015-02-03 12:13:51 -07:00
|
|
|
|
2015-04-21 07:56:10 -06:00
|
|
|
buf := NewBuffer()
|
|
|
|
buf.Area = d.Area
|
2015-02-03 12:13:51 -07:00
|
|
|
if !d.IsDisplay {
|
2015-04-21 07:56:10 -06:00
|
|
|
return buf
|
2015-02-03 12:13:51 -07:00
|
|
|
}
|
|
|
|
|
2015-04-21 07:56:10 -06:00
|
|
|
// render border
|
2015-02-03 12:13:51 -07:00
|
|
|
if d.HasBorder {
|
2015-04-21 07:56:10 -06:00
|
|
|
buf.Union(d.Border.Buffer())
|
2015-02-03 12:13:51 -07:00
|
|
|
}
|
|
|
|
|
2015-04-21 07:56:10 -06:00
|
|
|
// render background
|
|
|
|
for p := range buf.CellMap {
|
|
|
|
if p.In(d.innerArea) {
|
|
|
|
buf.CellMap[p] = Cell{' ', ColorDefault, d.Bg}
|
2015-02-03 12:13:51 -07:00
|
|
|
}
|
|
|
|
}
|
2015-04-21 07:56:10 -06:00
|
|
|
return buf
|
2015-02-03 12:13:51 -07:00
|
|
|
}
|
2015-03-15 13:56:38 -06:00
|
|
|
|
2015-03-24 15:16:43 -06:00
|
|
|
// GetHeight implements GridBufferer.
|
|
|
|
// It returns current height of the block.
|
2015-03-15 13:56:38 -06:00
|
|
|
func (d Block) GetHeight() int {
|
|
|
|
return d.Height
|
|
|
|
}
|
|
|
|
|
2015-03-24 15:16:43 -06:00
|
|
|
// SetX implements GridBufferer interface, which sets block's x position.
|
2015-03-15 13:56:38 -06:00
|
|
|
func (d *Block) SetX(x int) {
|
|
|
|
d.X = x
|
|
|
|
}
|
|
|
|
|
2015-03-24 15:16:43 -06:00
|
|
|
// SetY implements GridBufferer interface, it sets y position for block.
|
2015-03-15 13:56:38 -06:00
|
|
|
func (d *Block) SetY(y int) {
|
|
|
|
d.Y = y
|
|
|
|
}
|
|
|
|
|
2015-03-24 15:16:43 -06:00
|
|
|
// SetWidth implements GridBuffer interface, it sets block's width.
|
2015-03-15 13:56:38 -06:00
|
|
|
func (d *Block) SetWidth(w int) {
|
|
|
|
d.Width = w
|
|
|
|
}
|