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,8 +15,9 @@ type Size struct {
type Element struct {
ID string `yaml:"id"`
Layout Layout `yaml:"layout"`
Widget Widget `yaml:"widget"`
Container Container `yaml:"container"`
Layout Layout `yaml:"layout"`
Widget Widget `yaml:"widget"`
// Border Layout Elements
Top *Element `yaml:"top"`
@ -27,6 +28,7 @@ type Element struct {
// Other Layout Elements
Children []*Element `yaml:"children"`
Content *Element `yaml:"content"`
// Form Element
Label *Element `yaml:"label"`
@ -38,6 +40,9 @@ type Element struct {
RowColumns *int `yaml:"rowColumns"`
ElementSize *Size `yaml:"elementSize"`
// MinSize configuration
MinSize *Size `yaml:"minSize"`
// Widget Properties
Text string `yaml:"text"`
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 obj, err = e.Layout.Build(e, s); err != nil {
err = fmt.Errorf("failed to build layout element: %w", err)

View File

@ -4,6 +4,8 @@ import (
"errors"
"fmt"
"bitbucket.org/hevanto/ui/uilayout"
"bitbucket.org/hevanto/ui/uiwidget"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
@ -12,15 +14,16 @@ import (
type Layout string
const (
Border Layout = "Border"
Form Layout = "Form"
Grid Layout = "Grid"
HBox Layout = "HBox"
Stack Layout = "Stack"
VBox Layout = "VBox"
Border Layout = "Border"
Form Layout = "Form"
Grid Layout = "Grid"
HBox Layout = "HBox"
MinSize Layout = "MinSize"
Stack Layout = "Stack"
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 {
case Border:
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)
case HBox:
c, err = l.buildHBoxLayout(e, s)
case MinSize:
c, err = l.buildMinSizeLayout(e, s)
case Stack:
c, err = l.buildStackLayout(e, s)
case VBox:
@ -41,6 +46,15 @@ func (l Layout) Build(e *Element, s ScreenHandler) (c *fyne.Container, err error
return
}
if e.Decorators != nil {
for _, dec := range e.Decorators {
switch dec {
case "Border":
c = uiwidget.NewWidgetBorder(c)
}
}
}
if e.Hidden {
c.Hide()
}
@ -179,6 +193,29 @@ func (l Layout) buildHBoxLayout(e *Element, s ScreenHandler) (c *fyne.Container,
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) {
children := make([]fyne.CanvasObject, 0, len(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)
}
}