Skip to content

Commit

Permalink
Add LinearLayout
Browse files Browse the repository at this point in the history
LinearLayout serves as a wrapper for several gio layout structs and
it reduces the amount of code required when applying basic attributes
like padding, margin, border, etc to a layout.
  • Loading branch information
beansgum committed Aug 18, 2021
1 parent 2690884 commit 04cb8f1
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 62 deletions.
49 changes: 49 additions & 0 deletions ui/decredmaterial/border.go
@@ -0,0 +1,49 @@
package decredmaterial

import (
"image/color"

"gioui.org/f32"
"gioui.org/layout"
"gioui.org/op/clip"
"gioui.org/op/paint"
"gioui.org/unit"
)

// Border lays out a widget and draws a border inside it.
type Border struct {
Color color.NRGBA
Radius CornerRadius
Width unit.Value
}

func (b Border) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions {
dims := w(gtx)
sz := layout.FPt(dims.Size)

width := float32(gtx.Px(b.Width))
sz.X -= width
sz.Y -= width

r := f32.Rectangle{Max: sz}
r = r.Add(f32.Point{X: width * 0.5, Y: width * 0.5})

tr := float32(gtx.Px(unit.Dp(b.Radius.TopRight)))
tl := float32(gtx.Px(unit.Dp(b.Radius.TopLeft)))
br := float32(gtx.Px(unit.Dp(b.Radius.BottomRight)))
bl := float32(gtx.Px(unit.Dp(b.Radius.BottomLeft)))
radius := clip.RRect{
Rect: r,
NW: tl, NE: tr, SE: br, SW: bl,
}

paint.FillShape(gtx.Ops,
b.Color,
clip.Stroke{
Path: radius.Path(gtx.Ops),
Style: clip.StrokeStyle{Width: width},
}.Op(),
)

return dims
}
42 changes: 19 additions & 23 deletions ui/decredmaterial/card.go
Expand Up @@ -43,28 +43,24 @@ func (t *Theme) Card() Card {
}

func (c Card) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions {
dims := layout.Stack{}.Layout(gtx,
layout.Stacked(func(gtx C) D {
return c.Inset.Layout(gtx, func(gtx C) D {
return layout.Stack{}.Layout(gtx,
layout.Expanded(func(gtx C) D {
tr := float32(gtx.Px(unit.Dp(c.Radius.TopRight)))
tl := float32(gtx.Px(unit.Dp(c.Radius.TopLeft)))
br := float32(gtx.Px(unit.Dp(c.Radius.BottomRight)))
bl := float32(gtx.Px(unit.Dp(c.Radius.BottomLeft)))
clip.RRect{
Rect: f32.Rectangle{Max: f32.Point{
X: float32(gtx.Constraints.Min.X),
Y: float32(gtx.Constraints.Min.Y),
}},
NW: tl, NE: tr, SE: br, SW: bl,
}.Add(gtx.Ops)
return fill(gtx, c.Color)
}),
layout.Stacked(w),
)
})
}),
)
dims := c.Inset.Layout(gtx, func(gtx C) D {
return layout.Stack{}.Layout(gtx,
layout.Expanded(func(gtx C) D {
tr := float32(gtx.Px(unit.Dp(c.Radius.TopRight)))
tl := float32(gtx.Px(unit.Dp(c.Radius.TopLeft)))
br := float32(gtx.Px(unit.Dp(c.Radius.BottomRight)))
bl := float32(gtx.Px(unit.Dp(c.Radius.BottomLeft)))
clip.RRect{
Rect: f32.Rectangle{Max: f32.Point{
X: float32(gtx.Constraints.Min.X),
Y: float32(gtx.Constraints.Min.Y),
}},
NW: tl, NE: tr, SE: br, SW: bl,
}.Add(gtx.Ops)
return fill(gtx, c.Color)
}),
layout.Stacked(w),
)
})
return dims
}
78 changes: 78 additions & 0 deletions ui/decredmaterial/linearlayout.go
@@ -0,0 +1,78 @@
package decredmaterial

import (
"image/color"

"gioui.org/f32"
"gioui.org/layout"
"gioui.org/op/clip"
"gioui.org/unit"
)

const (
WRAP_CONTENT = -1
MATCH_PARENT = -2
)

type LinearLayout struct {
Width int
Height int
Orientation layout.Axis
Background color.NRGBA
Border Border
Margin layout.Inset
Padding layout.Inset
Direction layout.Direction
}

func (ll LinearLayout) Layout(gtx C, children ...layout.FlexChild) D {
// draw margin
return ll.Margin.Layout(gtx, func(gtx C) D {
return layout.Stack{}.Layout(gtx,
layout.Expanded(func(gtx C) D {
ll.applyDimension(&gtx)
// // draw background and and clip the background to border radius
tr := float32(gtx.Px(unit.Dp(ll.Border.Radius.TopRight)))
tl := float32(gtx.Px(unit.Dp(ll.Border.Radius.TopLeft)))
br := float32(gtx.Px(unit.Dp(ll.Border.Radius.BottomRight)))
bl := float32(gtx.Px(unit.Dp(ll.Border.Radius.BottomLeft)))
clip.RRect{
Rect: f32.Rectangle{Max: f32.Point{
X: float32(gtx.Constraints.Min.X),
Y: float32(gtx.Constraints.Min.Y),
}},
NW: tl, NE: tr, SE: br, SW: bl,
}.Add(gtx.Ops)
return fill(gtx, ll.Background)
}),
layout.Stacked(func(gtx C) D {
ll.applyDimension(&gtx)
return ll.Border.Layout(gtx, func(gtx C) D {
// draw padding
return ll.Padding.Layout(gtx, func(gtx C) D {
// draw layout direction
return ll.Direction.Layout(gtx, func(gtx C) D {
return layout.Flex{Axis: ll.Orientation}.Layout(gtx, children...)
})
})
})
}),
)
})
}

func (ll LinearLayout) applyDimension(gtx *C) {
if ll.Width == MATCH_PARENT {
gtx.Constraints.Min.X = gtx.Constraints.Max.X
} else if ll.Width != WRAP_CONTENT {
gtx.Constraints.Min.X = ll.Width
gtx.Constraints.Max.X = ll.Width
}

if ll.Height == MATCH_PARENT {
gtx.Constraints.Min.Y = gtx.Constraints.Max.Y
} else if ll.Height != WRAP_CONTENT {
gtx.Constraints.Min.Y = ll.Height
gtx.Constraints.Max.Y = ll.Height
}
}
71 changes: 32 additions & 39 deletions ui/page/more_page.go
Expand Up @@ -108,47 +108,40 @@ func (pg *MorePage) Layout(gtx layout.Context) layout.Dimensions {
}

func (pg *MorePage) layoutMoreItems(gtx layout.Context) layout.Dimensions {
return layout.Stack{}.Layout(gtx,
layout.Stacked(func(gtx C) D {
list := layout.List{Axis: layout.Vertical}
return list.Layout(gtx, len(pg.morePageListItems), func(gtx C, i int) D {
return layout.Inset{Bottom: values.MarginPadding5}.Layout(gtx, func(gtx C) D {
return decredmaterial.Clickable(gtx, pg.morePageListItems[i].clickable, func(gtx C) D {
background := pg.Theme.Color.Surface
card := pg.Theme.Card()
card.Color = background
return card.Layout(gtx, func(gtx C) D {
gtx.Constraints.Min.X = gtx.Constraints.Max.X
return layout.Stack{}.Layout(gtx,
layout.Stacked(func(gtx C) D {
return layout.UniformInset(values.MarginPadding15).Layout(gtx, func(gtx C) D {
gtx.Constraints.Min.X = gtx.Constraints.Max.X
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
layout.Rigid(func(gtx C) D {
return layout.Center.Layout(gtx, pg.morePageListItems[i].image.Layout)
}),
layout.Rigid(func(gtx C) D {
return layout.Inset{
Left: values.MarginPadding15,
Top: values.MarginPadding2,
}.Layout(gtx, func(gtx C) D {
return layout.Center.Layout(gtx, func(gtx C) D {
page := pg.morePageListItems[i].page
if page == SecurityToolsPageID {
page = "Security Tools"
}
return pg.Theme.Body1(page).Layout(gtx)
})
})
}),
)

list := layout.List{Axis: layout.Vertical}
return list.Layout(gtx, len(pg.morePageListItems), func(gtx C, i int) D {
return layout.Inset{Bottom: values.MarginPadding5}.Layout(gtx, func(gtx C) D {
return decredmaterial.Clickable(gtx, pg.morePageListItems[i].clickable, func(gtx C) D {
background := pg.Theme.Color.Surface
card := pg.Theme.Card()
card.Color = background
return card.Layout(gtx, func(gtx C) D {
gtx.Constraints.Min.X = gtx.Constraints.Max.X
return layout.UniformInset(values.MarginPadding15).Layout(gtx, func(gtx C) D {
gtx.Constraints.Min.X = gtx.Constraints.Max.X
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
layout.Rigid(func(gtx C) D {
return layout.Center.Layout(gtx, pg.morePageListItems[i].image.Layout)
}),
layout.Rigid(func(gtx C) D {
return layout.Inset{
Left: values.MarginPadding15,
Top: values.MarginPadding2,
}.Layout(gtx, func(gtx C) D {
return layout.Center.Layout(gtx, func(gtx C) D {
page := pg.morePageListItems[i].page
if page == SecurityToolsPageID {
page = "Security Tools"
}
return pg.Theme.Body1(page).Layout(gtx)
})
}),
)
})
})
}),
)
})
})
})
}),
)
})
})
}

0 comments on commit 04cb8f1

Please sign in to comment.