ui/screen/layout.go

209 lines
5.3 KiB
Go
Raw Normal View History

2024-03-30 17:45:07 +01:00
package screen
import (
"errors"
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
)
type Layout string
const (
Border Layout = "Border"
Form Layout = "Form"
Grid Layout = "Grid"
HBox Layout = "HBox"
Stack Layout = "Stack"
VBox Layout = "VBox"
)
func (l Layout) Build(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
switch l {
case Border:
c, err = l.buildBorderLayout(e, s)
case Form:
c, err = l.buildFormLayout(e, s)
case Grid:
c, err = l.buildGridLayout(e, s)
case HBox:
c, err = l.buildHBoxLayout(e, s)
case Stack:
c, err = l.buildStackLayout(e, s)
case VBox:
c, err = l.buildVBoxLayout(e, s)
default:
err = errors.New("invalid layout")
}
if err != nil {
return
}
if e.Hidden {
c.Hide()
}
return
}
func (l Layout) buildBorderLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
var top, left, right, bottom fyne.CanvasObject
var center []fyne.CanvasObject
if e.Top != nil {
if top, err = e.Top.BuildUI(s); err != nil {
err = fmt.Errorf("BorderLayout: failed to create top element: %w", err)
return
}
}
if e.Left != nil {
if left, err = e.Left.BuildUI(s); err != nil {
err = fmt.Errorf("BorderLayout: failed to create left element: %w", err)
return
}
}
if e.Center != nil {
center = make([]fyne.CanvasObject, 0, len(e.Center))
for _, elem := range e.Center {
var ce fyne.CanvasObject
if ce, err = elem.BuildUI(s); err != nil {
err = fmt.Errorf("BorderLayout: failed to create center element: %w", err)
return
}
center = append(center, ce)
}
}
if e.Right != nil {
if right, err = e.Right.BuildUI(s); err != nil {
err = fmt.Errorf("BorderLayout: failed to create right element: %w", err)
return
}
}
if e.Bottom != nil {
if bottom, err = e.Bottom.BuildUI(s); err != nil {
err = fmt.Errorf("BorderLayout: failed to create bottom element: %w", err)
return
}
}
c = container.NewBorder(top, bottom, left, right, center...)
return
}
func (l Layout) buildFormLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
children := make([]fyne.CanvasObject, 0, len(e.Children)*2)
for _, child := range e.Children {
if child.Label == nil {
child.Label = &Element{
Text: "",
}
}
if child.Field == nil {
child.Field = &Element{
Widget: Label,
Text: "",
}
}
child.Label.Widget = Label
if child.Label.Options == nil {
child.Label.Options = make(map[string]any)
}
if child.Label.Options["TextStyle"] == nil {
child.Label.Options["TextStyle"] = make(map[string]any)
}
child.Label.Options["TextStyle"].(map[string]any)["Bold"] = true
var label, field fyne.CanvasObject
if label, err = child.Label.BuildUI(s); err != nil {
err = fmt.Errorf("FormLayout: failed to create label element: %w", err)
return
}
if field, err = child.Field.BuildUI(s); err != nil {
err = fmt.Errorf("FormLayout: failed to create field element: %w", err)
return
}
children = append(children, label, field)
}
c = container.New(layout.NewFormLayout(), children...)
return
}
func (l Layout) buildGridLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
children := make([]fyne.CanvasObject, 0, len(e.Children))
for _, child := range e.Children {
var obj fyne.CanvasObject
if obj, err = child.BuildUI(s); err != nil {
err = fmt.Errorf("GridLayout failed to create child element %w", err)
return
}
children = append(children, obj)
}
if e.Columns != nil {
c = container.NewGridWithColumns(*e.Columns, children...)
return
}
if e.Rows != nil {
c = container.NewGridWithRows(*e.Rows, children...)
return
}
if e.RowColumns != nil {
c = container.NewAdaptiveGrid(*e.RowColumns, children...)
return
}
if e.ElementSize != nil {
c = container.NewGridWrap(fyne.NewSize(e.ElementSize.Width, e.ElementSize.Height), children...)
return
}
err = errors.New("GridLayout failed due to incomplete grid type definition")
return
}
func (l Layout) buildHBoxLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
children := make([]fyne.CanvasObject, 0, len(e.Children))
for _, child := range e.Children {
var obj fyne.CanvasObject
if obj, err = child.BuildUI(s); err != nil {
err = fmt.Errorf("HBoxLayout failed to create child element: %w", err)
return
}
children = append(children, obj)
}
c = container.New(layout.NewHBoxLayout(), children...)
return
}
func (l Layout) buildStackLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
children := make([]fyne.CanvasObject, 0, len(e.Children))
for _, child := range e.Children {
var obj fyne.CanvasObject
if obj, err = child.BuildUI(s); err != nil {
err = fmt.Errorf("StackLayout failed to create child element: %w", err)
return
}
children = append(children, obj)
}
c = container.New(layout.NewStackLayout(), children...)
return
}
func (l Layout) buildVBoxLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
children := make([]fyne.CanvasObject, 0, len(e.Children))
for _, child := range e.Children {
var obj fyne.CanvasObject
if obj, err = child.BuildUI(s); err != nil {
err = fmt.Errorf("VBoxLayout failed to create child element: %w", err)
return
}
children = append(children, obj)
}
c = container.New(layout.NewVBoxLayout(), children...)
return
}