package views import ( "git.tordarus.net/Tordarus/tui" ) // FlowGroup ia a tui.Group which places its children in a linear layout type FlowGroup struct { tui.ViewTmpl views []tui.View lastLayoutPhase *LayoutResult // Orientation defines in which direction the children will be placed Orientation tui.Orientation } var _ tui.Group = &FlowGroup{} func NewFlowGroup(orientation tui.Orientation) *FlowGroup { return &FlowGroup{ views: make([]tui.View, 0), Orientation: orientation, } } func (g *FlowGroup) Views() []tui.View { return g.views[:] } func (g *FlowGroup) AppendViews(v ...tui.View) { g.views = append(g.views, v...) } func (g *FlowGroup) PrependViews(v ...tui.View) { g.views = append(v, g.views...) } func (g *FlowGroup) InsertView(v tui.View, index int) { g.views = append(g.views[:index], append([]tui.View{v}, g.views[index:]...)...) } func (g *FlowGroup) RemoveView(v tui.View) { for index, view := range g.Views() { if view == v { g.views = append(g.views[:index], g.views[index:]...) return } } } func (g *FlowGroup) Draw(buf *tui.ViewBuffer) { g.ViewTmpl.Draw(buf) if g.lastLayoutPhase == nil { g.Layout() } layout := g.lastLayoutPhase if g.Orientation == tui.Horizontal { remainingSpacePerView := buf.Width() - layout.Sum.Width if layout.HorizontalNegativeCount > 0 { remainingSpacePerView /= layout.HorizontalNegativeCount } x := 0 for _, view := range g.views { size := layout.Sizes[view] size.Height = iff(size.Height < 0, buf.Height(), size.Height) if size.Width < 0 { size.Width = iff(layout.Sum.Width > buf.Width(), 0, remainingSpacePerView) } view.Draw(buf.Sub(x, 0, size.Width, size.Height)) x += size.Width } } else if g.Orientation == tui.Vertical { remainingSpacePerView := buf.Height() - layout.Sum.Height if layout.VerticalNegativeCount > 0 { remainingSpacePerView /= layout.VerticalNegativeCount } y := 0 for _, view := range g.views { size := layout.Sizes[view] size.Width = iff(size.Width < 0, buf.Width(), size.Width) if size.Height < 0 { size.Height = iff(layout.Sum.Height > buf.Height(), 0, remainingSpacePerView) } view.Draw(buf.Sub(0, y, size.Width, size.Height)) y += size.Height } } g.lastLayoutPhase = nil } func (g *FlowGroup) Layout() (prefWidth, prefHeight int) { layout := CalculateLayoutResult(g.Views()) g.lastLayoutPhase = layout if g.Orientation == tui.Horizontal { prefWidth = iff(layout.HorizontalNegativeCount == 0, layout.Sum.Width, -1) prefHeight = iff(layout.VerticalNegativeCount == 0, layout.Max.Height, -1) } else if g.Orientation == tui.Vertical { prefWidth = iff(layout.HorizontalNegativeCount == 0, layout.Max.Width, -1) prefHeight = iff(layout.VerticalNegativeCount == 0, layout.Sum.Width, -1) } layout.Pref = tui.Size{Width: prefWidth, Height: prefHeight} return } func (g *FlowGroup) OnKeyPressed(event *tui.KeyEvent) (consumed bool) { for _, view := range g.Views() { if view.OnKeyPressed(event) { return true } } return false }