package views import ( "git.tordarus.net/Tordarus/tui" ) // BorderGroup ia a tui.Group which places its children in a linear layout type BorderGroup struct { tui.ViewTmpl views map[Slot]tui.View horizontalLayout *LayoutResult verticalLayout *LayoutResult } var _ tui.Group = &BorderGroup{} func NewBorderGroup() *BorderGroup { return &BorderGroup{ views: map[Slot]tui.View{}, } } func (g *BorderGroup) Views() []tui.View { s := make([]tui.View, 0, len(g.views)) for _, view := range g.views { s = append(s, view) } return s } func (g *BorderGroup) SetView(v tui.View, slot Slot) { g.views[slot] = v } func (g *BorderGroup) View(slot Slot) tui.View { return g.views[slot] } func (g *BorderGroup) Draw(buf *tui.ViewBuffer) { g.ViewTmpl.Draw(buf) if g.verticalLayout == nil { g.Layout() } verticalLayout := g.verticalLayout if g.horizontalLayout == nil { g.Layout() } horizontalLayout := g.horizontalLayout remainingVerticalSpacePerView := (buf.Height() - verticalLayout.Sum.Height) if verticalLayout.VerticalNegativeCount > 0 { remainingVerticalSpacePerView /= verticalLayout.VerticalNegativeCount } remainingHorizontalSpacePerView := (buf.Width() - horizontalLayout.Sum.Width) if horizontalLayout.HorizontalNegativeCount > 0 { remainingHorizontalSpacePerView /= horizontalLayout.HorizontalNegativeCount } fitsVertically := buf.Height() >= verticalLayout.Sum.Height fitsHorizontally := buf.Width() >= horizontalLayout.Sum.Width var topHeight int var bottomHeight int var leftWidth int var rightWidth int if view, ok := g.views[Top]; ok { _, topHeight = view.Layout() if fitsVertically { topHeight = iff(topHeight < 0, remainingVerticalSpacePerView, topHeight) } else { topHeight = int(float64(buf.Height()) * float64(topHeight) / float64(verticalLayout.Sum.Height)) } view.Draw(buf.Sub(0, 0, buf.Width(), topHeight)) } if view, ok := g.views[Bottom]; ok { _, bottomHeight = view.Layout() if fitsVertically { bottomHeight = iff(bottomHeight < 0, remainingVerticalSpacePerView, bottomHeight) } else { bottomHeight = int(float64(buf.Height()) * float64(bottomHeight) / float64(verticalLayout.Sum.Height)) } view.Draw(buf.Sub(0, buf.Height()-bottomHeight, buf.Width(), bottomHeight)) } if view, ok := g.views[Left]; ok { leftWidth, _ = view.Layout() if fitsHorizontally { leftWidth = iff(leftWidth < 0, remainingHorizontalSpacePerView, leftWidth) } else { leftWidth = int(float64(buf.Width()) * float64(leftWidth) / float64(horizontalLayout.Sum.Width)) } view.Draw(buf.Sub(0, topHeight, leftWidth, buf.Height()-topHeight-bottomHeight)) } if view, ok := g.views[Right]; ok { rightWidth, _ = view.Layout() if fitsHorizontally { rightWidth = iff(rightWidth < 0, remainingHorizontalSpacePerView, rightWidth) } else { rightWidth = int(float64(buf.Width()) * float64(rightWidth) / float64(horizontalLayout.Sum.Width)) } view.Draw(buf.Sub(buf.Width()-rightWidth, topHeight, rightWidth, buf.Height()-topHeight-bottomHeight)) } if view, ok := g.views[Center]; ok { view.Draw(buf.Sub(leftWidth, topHeight, buf.Width()-leftWidth-rightWidth, buf.Height()-topHeight-bottomHeight)) } g.verticalLayout = nil g.horizontalLayout = nil } func (g *BorderGroup) Layout() (prefWidth, prefHeight int) { g.verticalLayout = CalculateLayoutResult([]tui.View{g.View(Top), g.View(Center), g.View(Bottom)}) g.horizontalLayout = CalculateLayoutResult([]tui.View{g.View(Left), g.View(Center), g.View(Right)}) return -1, -1 } func (g *BorderGroup) OnKeyPressed(event *tui.KeyEvent) (consumed bool) { for _, view := range g.Views() { if view.OnKeyPressed(event) { return true } } return false } type Slot uint8 const ( Top Slot = iota Bottom Left Right Center )