Added scroll container and minsize layout

This commit is contained in:
Maarten Heremans 2024-03-30 19:26:48 +01:00
parent 18cf7858d6
commit b9d2b680bc
4 changed files with 184 additions and 9 deletions

93
screen/container.go Normal file
View File

@ -0,0 +1,93 @@
package screen
import (
"errors"
"fmt"
"bitbucket.org/hevanto/ui/uiwidget"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
)
type Container string
const (
HScroll Container = "HScroll"
Scroll Container = "Scroll"
VScroll Container = "VScroll"
)
func (cnt Container) Build(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
switch cnt {
case HScroll:
c, err = cnt.buildHScrollContainer(e, s)
case Scroll:
c, err = cnt.buildScrollContainer(e, s)
case VScroll:
c, err = cnt.buildVScrollContainer(e, s)
default:
err = errors.New("invalid container")
}
if err != nil {
return
}
if e.Decorators != nil {
for _, dec := range e.Decorators {
switch dec {
case "Border":
c = uiwidget.NewWidgetBorder(c)
}
}
}
if e.Hidden {
c.Hide()
}
return
}
func (ctn Container) buildHScrollContainer(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
if e.Content == nil {
err = errors.New("HScroll: no content defined")
return
}
content, err := e.Content.BuildUI(s)
if err != nil {
err = fmt.Errorf("HScroll: failed to build content: %w", err)
return
}
c = container.NewHScroll(content)
return
}
func (ctn Container) buildScrollContainer(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
if e.Content == nil {
err = errors.New("Scroll: no content defined")
return
}
content, err := e.Content.BuildUI(s)
if err != nil {
err = fmt.Errorf("Scroll: failed to build content: %w", err)
return
}
c = container.NewScroll(content)
return
}
func (ctn Container) buildVScrollContainer(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
if e.Content == nil {
err = errors.New("VScroll: no content defined")
return
}
content, err := e.Content.BuildUI(s)
if err != nil {
err = fmt.Errorf("VScroll: failed to build content: %w", err)
return
}
c = container.NewScroll(content)
return
}

View File

@ -15,6 +15,7 @@ type Size struct {
type Element struct { type Element struct {
ID string `yaml:"id"` ID string `yaml:"id"`
Container Container `yaml:"container"`
Layout Layout `yaml:"layout"` Layout Layout `yaml:"layout"`
Widget Widget `yaml:"widget"` Widget Widget `yaml:"widget"`
@ -27,6 +28,7 @@ type Element struct {
// Other Layout Elements // Other Layout Elements
Children []*Element `yaml:"children"` Children []*Element `yaml:"children"`
Content *Element `yaml:"content"`
// Form Element // Form Element
Label *Element `yaml:"label"` Label *Element `yaml:"label"`
@ -38,6 +40,9 @@ type Element struct {
RowColumns *int `yaml:"rowColumns"` RowColumns *int `yaml:"rowColumns"`
ElementSize *Size `yaml:"elementSize"` ElementSize *Size `yaml:"elementSize"`
// MinSize configuration
MinSize *Size `yaml:"minSize"`
// Widget Properties // Widget Properties
Text string `yaml:"text"` Text string `yaml:"text"`
Localized bool `yaml:"localized"` Localized bool `yaml:"localized"`
@ -81,6 +86,13 @@ func (e *Element) BuildUI(s ScreenHandler) (obj fyne.CanvasObject, err error) {
} }
}() }()
if e.Container != "" {
if obj, err = e.Container.Build(e, s); err != nil {
err = fmt.Errorf("failed to build container element: %w", err)
return
}
return
}
if e.Layout != "" { if e.Layout != "" {
if obj, err = e.Layout.Build(e, s); err != nil { if obj, err = e.Layout.Build(e, s); err != nil {
err = fmt.Errorf("failed to build layout element: %w", err) err = fmt.Errorf("failed to build layout element: %w", err)

View File

@ -4,6 +4,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"bitbucket.org/hevanto/ui/uilayout"
"bitbucket.org/hevanto/ui/uiwidget"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/layout"
@ -16,11 +18,12 @@ const (
Form Layout = "Form" Form Layout = "Form"
Grid Layout = "Grid" Grid Layout = "Grid"
HBox Layout = "HBox" HBox Layout = "HBox"
MinSize Layout = "MinSize"
Stack Layout = "Stack" Stack Layout = "Stack"
VBox Layout = "VBox" VBox Layout = "VBox"
) )
func (l Layout) Build(e *Element, s ScreenHandler) (c *fyne.Container, err error) { func (l Layout) Build(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
switch l { switch l {
case Border: case Border:
c, err = l.buildBorderLayout(e, s) c, err = l.buildBorderLayout(e, s)
@ -30,6 +33,8 @@ func (l Layout) Build(e *Element, s ScreenHandler) (c *fyne.Container, err error
c, err = l.buildGridLayout(e, s) c, err = l.buildGridLayout(e, s)
case HBox: case HBox:
c, err = l.buildHBoxLayout(e, s) c, err = l.buildHBoxLayout(e, s)
case MinSize:
c, err = l.buildMinSizeLayout(e, s)
case Stack: case Stack:
c, err = l.buildStackLayout(e, s) c, err = l.buildStackLayout(e, s)
case VBox: case VBox:
@ -41,6 +46,15 @@ func (l Layout) Build(e *Element, s ScreenHandler) (c *fyne.Container, err error
return return
} }
if e.Decorators != nil {
for _, dec := range e.Decorators {
switch dec {
case "Border":
c = uiwidget.NewWidgetBorder(c)
}
}
}
if e.Hidden { if e.Hidden {
c.Hide() c.Hide()
} }
@ -179,6 +193,29 @@ func (l Layout) buildHBoxLayout(e *Element, s ScreenHandler) (c *fyne.Container,
return return
} }
func (l Layout) buildMinSizeLayout(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("MinSizeLayout failed to create child element: %w", err)
return
}
children = append(children, obj)
}
if e.MinSize == nil {
e.MinSize = &Size{
Width: 0,
Height: 0,
}
}
c = container.New(
uilayout.NewMinSizeLayout(
fyne.NewSize(e.MinSize.Width, e.MinSize.Height)),
children...)
return
}
func (l Layout) buildStackLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) { func (l Layout) buildStackLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
children := make([]fyne.CanvasObject, 0, len(e.Children)) children := make([]fyne.CanvasObject, 0, len(e.Children))
for _, child := range e.Children { for _, child := range e.Children {

33
uilayout/minsize.go Normal file
View File

@ -0,0 +1,33 @@
package uilayout
import "fyne.io/fyne/v2"
type MinSize struct {
minSize fyne.Size
}
func NewMinSizeLayout(minSize fyne.Size) *MinSize {
return &MinSize{minSize: minSize}
}
func (l *MinSize) MinSize(objects []fyne.CanvasObject) fyne.Size {
size := l.minSize
for _, o := range objects {
childSize := o.MinSize()
if size.Width < childSize.Width {
size.Width = childSize.Width
}
if size.Height < childSize.Height {
size.Height = childSize.Height
}
}
return size
}
func (l *MinSize) Layout(objects []fyne.CanvasObject, containerSize fyne.Size) {
pos := fyne.NewPos(0, 0)
for _, o := range objects {
o.Resize(containerSize)
o.Move(pos)
}
}