From a9199dd9f2fa4b79a3c8b16d2cd46446651fdb81 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Wed, 10 Apr 2019 22:49:33 +0300 Subject: Split container/text HTML entities and add support for
--- ui/messages/html/container.go | 144 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 ui/messages/html/container.go (limited to 'ui/messages/html/container.go') diff --git a/ui/messages/html/container.go b/ui/messages/html/container.go new file mode 100644 index 0000000..b17bc1f --- /dev/null +++ b/ui/messages/html/container.go @@ -0,0 +1,144 @@ +// gomuks - A terminal Matrix client written in Go. +// Copyright (C) 2019 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package html + +import ( + "fmt" + "strings" + + "maunium.net/go/mauview" +) + +type ContainerEntity struct { + *BaseEntity + + // The children of this container entity. + Children []Entity + // Number of cells to indent children. + Indent int +} + +// PlainText returns the plaintext content in this entity and all its children. +func (ce *ContainerEntity) PlainText() string { + if len(ce.Children) == 0 { + return "" + } + var buf strings.Builder + newlined := false + for _, child := range ce.Children { + text := child.PlainText() + if !strings.HasPrefix(text, "\n") && child.IsBlock() && !newlined { + buf.WriteRune('\n') + } + newlined = false + buf.WriteString(text) + if child.IsBlock() { + if !strings.HasSuffix(text, "\n") { + buf.WriteRune('\n') + } + newlined = true + } + } + return strings.TrimSpace(buf.String()) +} + +// AdjustStyle recursively changes the style of this entity and all its children. +func (ce *ContainerEntity) AdjustStyle(fn AdjustStyleFunc) Entity { + for _, child := range ce.Children { + child.AdjustStyle(fn) + } + ce.Style = fn(ce.Style) + return ce +} + +// clone creates a deep copy of this base entity. +func (ce *ContainerEntity) Clone() Entity { + children := make([]Entity, len(ce.Children)) + for i, child := range ce.Children { + children[i] = child.Clone() + } + return &ContainerEntity{ + BaseEntity: ce.BaseEntity.Clone().(*BaseEntity), + Children: children, + Indent: ce.Indent, + } +} + +// String returns a textual representation of this BaseEntity struct. +func (ce *ContainerEntity) String() string { + if len(ce.Children) == 0 { + return fmt.Sprintf(`&html.ContainerEntity{Base=%s, Indent=%d, Children=[]}`, ce.BaseEntity, ce.Indent) + } + var buf strings.Builder + _, _ = fmt.Fprintf(&buf, `&html.ContainerEntity{Base=%s, Indent=%d, Children=[`, ce.BaseEntity, ce.Indent) + for _, child := range ce.Children { + buf.WriteString("\n ") + buf.WriteString(strings.Join(strings.Split(strings.TrimRight(child.String(), "\n"), "\n"), "\n ")) + } + buf.WriteString("\n]}\n,") + return buf.String() +} + +// Draw draws this entity onto the given mauview Screen. +func (ce *ContainerEntity) Draw(screen mauview.Screen) { + if len(ce.Children) == 0 { + return + } + width, _ := screen.Size() + prevBreak := false + proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: ce.Indent, Width: width - ce.Indent, Style: ce.Style} + for i, entity := range ce.Children { + if i != 0 && entity.getStartX() == 0 { + proxyScreen.OffsetY++ + } + proxyScreen.Height = entity.Height() + entity.Draw(proxyScreen) + proxyScreen.SetStyle(ce.Style) + proxyScreen.OffsetY += entity.Height() - 1 + _, isBreak := entity.(*BreakEntity) + if prevBreak && isBreak { + proxyScreen.OffsetY++ + } + prevBreak = isBreak + } +} + +// CalculateBuffer prepares this entity and all its children for rendering with the given parameters +func (ce *ContainerEntity) CalculateBuffer(width, startX int, bare bool) int { + ce.BaseEntity.CalculateBuffer(width, startX, bare) + if len(ce.Children) > 0 { + ce.height = 0 + childStartX := ce.startX + prevBreak := false + for _, entity := range ce.Children { + if entity.IsBlock() || childStartX == 0 || ce.height == 0 { + ce.height++ + } + childStartX = entity.CalculateBuffer(width-ce.Indent, childStartX, bare) + ce.height += entity.Height() - 1 + _, isBreak := entity.(*BreakEntity) + if prevBreak && isBreak { + ce.height++ + } + prevBreak = isBreak + } + if !ce.Block { + return childStartX + } + } + return ce.startX +} -- cgit v1.2.3