summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorAlexander Neumann <alexander.neumann@picos-software.com>2019-02-27 16:27:53 +0100
committerAlexander Neumann <alexander.neumann@picos-software.com>2019-02-27 16:27:53 +0100
commit01bb817eee24099196760666b0826d5f7d9808bf (patch)
tree73f03cb500d67fd4004f4c3724230735d1871413
parentBoxLayout: Small refactoring after removing logging code (diff)
downloadwireguard-windows-01bb817eee24099196760666b0826d5f7d9808bf.tar.xz
wireguard-windows-01bb817eee24099196760666b0826d5f7d9808bf.zip
Add support for specifying widget alignment on layout level
-rw-r--r--boxlayout.go106
-rw-r--r--declarative/layouts.go20
-rw-r--r--flowlayout.go25
-rw-r--r--gridlayout.go46
4 files changed, 184 insertions, 13 deletions
diff --git a/boxlayout.go b/boxlayout.go
index d84a7bc0..a8b7dfdb 100644
--- a/boxlayout.go
+++ b/boxlayout.go
@@ -24,6 +24,7 @@ type BoxLayout struct {
margins Margins
spacing int
orientation Orientation
+ alignment Alignment2D
hwnd2StretchFactor map[win.HWND]int
size2MinSize map[Size]Size
resetNeeded bool
@@ -104,6 +105,24 @@ func (l *BoxLayout) SetOrientation(value Orientation) error {
return nil
}
+func (l *BoxLayout) Alignment() Alignment2D {
+ return l.alignment
+}
+
+func (l *BoxLayout) SetAlignment(alignment Alignment2D) error {
+ if alignment != l.alignment {
+ if alignment < AlignHVDefault || alignment > AlignHFarVFar {
+ return newError("invalid Alignment value")
+ }
+
+ l.alignment = alignment
+
+ l.Update(false)
+ }
+
+ return nil
+}
+
func (l *BoxLayout) Spacing() int {
return l.spacing
}
@@ -230,7 +249,7 @@ func (l *BoxLayout) MinSizeForSize(size Size) Size {
bounds := Rectangle{Width: size.Width, Height: size.Height}
- items, err := boxLayoutItems(widgetsToLayout(l.Container().Children()), l.orientation, bounds, l.margins, l.spacing, l.hwnd2StretchFactor)
+ items, err := boxLayoutItems(widgetsToLayout(l.Container().Children()), l.orientation, l.alignment, bounds, l.margins, l.spacing, l.hwnd2StretchFactor)
if err != nil {
return Size{}
}
@@ -302,7 +321,7 @@ func (l *BoxLayout) Update(reset bool) error {
ifContainerIsScrollViewDoCoolSpecialLayoutStuff(l)
- items, err := boxLayoutItems(widgetsToLayout(l.Container().Children()), l.orientation, l.container.ClientBounds(), l.margins, l.spacing, l.hwnd2StretchFactor)
+ items, err := boxLayoutItems(widgetsToLayout(l.Container().Children()), l.orientation, l.alignment, l.container.ClientBounds(), l.margins, l.spacing, l.hwnd2StretchFactor)
if err != nil {
return err
}
@@ -360,7 +379,11 @@ func boxLayoutFlags(orientation Orientation, children *WidgetList) LayoutFlags {
return flags
}
-func boxLayoutItems(widgets []Widget, orientation Orientation, bounds Rectangle, margins Margins, spacing int, hwnd2StretchFactor map[win.HWND]int) ([]layoutResultItem, error) {
+func boxLayoutItems(widgets []Widget, orientation Orientation, alignment Alignment2D, bounds Rectangle, margins Margins, spacing int, hwnd2StretchFactor map[win.HWND]int) ([]layoutResultItem, error) {
+ if len(widgets) == 0 {
+ return nil, nil
+ }
+
var greedyNonSpacerCount int
var greedySpacerCount int
var stretchFactorsTotal [3]int
@@ -498,10 +521,10 @@ func boxLayoutItems(widgets []Widget, orientation Orientation, bounds Rectangle,
results := make([]layoutResultItem, 0, len(widgets))
excessTotal := space1 - minSizesRemaining - spacingRemaining
- excessShare := excessTotal / (len(widgets) + 1)
+ excessShare := excessTotal / len(widgets)
+ halfExcessShare := excessTotal / (len(widgets) * 2)
p1 := start1
for i, widget := range widgets {
- p1 += excessShare
s1 := sizes[i]
var s2 int
@@ -511,15 +534,82 @@ func boxLayoutItems(widgets []Widget, orientation Orientation, bounds Rectangle,
s2 = prefSizes2[i]
}
- p2 := start2 + (space2-s2)/2
-
- var x, y, w, h int
+ var x, y, w, h, p2 int
if orientation == Horizontal {
+ switch alignment {
+ case AlignHNearVNear, AlignHNearVCenter, AlignHNearVFar:
+ // nop
+
+ case AlignHFarVNear, AlignHFarVCenter, AlignHFarVFar:
+ p1 += excessShare
+
+ default:
+ p1 += halfExcessShare
+ }
+
+ switch alignment {
+ case AlignHNearVNear, AlignHCenterVNear, AlignHFarVNear:
+ p2 = start2
+
+ case AlignHNearVFar, AlignHCenterVFar, AlignHFarVFar:
+ p2 = start2 + space2 - s2
+
+ default:
+ p2 = start2 + (space2-s2)/2
+ }
+
x, y, w, h = p1, p2, s1, s2
} else {
+ switch alignment {
+ case AlignHNearVNear, AlignHCenterVNear, AlignHFarVNear:
+ // nop
+
+ case AlignHNearVFar, AlignHCenterVFar, AlignHFarVFar:
+ p1 += excessShare
+
+ default:
+ p1 += halfExcessShare
+ }
+
+ switch alignment {
+ case AlignHNearVNear, AlignHNearVCenter, AlignHNearVFar:
+ p2 = start2
+
+ case AlignHFarVNear, AlignHFarVCenter, AlignHFarVFar:
+ p2 = start2 + space2 - s2
+
+ default:
+ p2 = start2 + (space2-s2)/2
+ }
+
x, y, w, h = p2, p1, s2, s1
}
+ if orientation == Horizontal {
+ switch alignment {
+ case AlignHNearVNear, AlignHNearVCenter, AlignHNearVFar:
+ p1 += excessShare
+
+ case AlignHFarVNear, AlignHFarVCenter, AlignHFarVFar:
+ // nop
+
+ default:
+ p1 += halfExcessShare
+ }
+
+ } else {
+ switch alignment {
+ case AlignHNearVNear, AlignHCenterVNear, AlignHFarVNear:
+ p1 += excessShare
+
+ case AlignHNearVFar, AlignHCenterVFar, AlignHFarVFar:
+ // nop
+
+ default:
+ p1 += halfExcessShare
+ }
+ }
+
p1 += s1 + spacing
results = append(results, layoutResultItem{widget: widget, bounds: Rectangle{X: x, Y: y, Width: w, Height: h}})
diff --git a/declarative/layouts.go b/declarative/layouts.go
index 601c3ffb..158a0cbb 100644
--- a/declarative/layouts.go
+++ b/declarative/layouts.go
@@ -61,6 +61,7 @@ func setLayoutSpacing(layout walk.Layout, spacing int, spacingZero bool) error {
type HBox struct {
Margins Margins
+ Alignment Alignment2D
Spacing int
MarginsZero bool
SpacingZero bool
@@ -77,11 +78,16 @@ func (hb HBox) Create() (walk.Layout, error) {
return nil, err
}
+ if err := l.SetAlignment(walk.Alignment2D(hb.Alignment)); err != nil {
+ return nil, err
+ }
+
return l, nil
}
type VBox struct {
Margins Margins
+ Alignment Alignment2D
Spacing int
MarginsZero bool
SpacingZero bool
@@ -98,6 +104,10 @@ func (vb VBox) Create() (walk.Layout, error) {
return nil, err
}
+ if err := l.SetAlignment(walk.Alignment2D(vb.Alignment)); err != nil {
+ return nil, err
+ }
+
return l, nil
}
@@ -105,6 +115,7 @@ type Grid struct {
Rows int
Columns int
Margins Margins
+ Alignment Alignment2D
Spacing int
MarginsZero bool
SpacingZero bool
@@ -125,11 +136,16 @@ func (g Grid) Create() (walk.Layout, error) {
return nil, err
}
+ if err := l.SetAlignment(walk.Alignment2D(g.Alignment)); err != nil {
+ return nil, err
+ }
+
return l, nil
}
type Flow struct {
Margins Margins
+ Alignment Alignment2D
Spacing int
MarginsZero bool
SpacingZero bool
@@ -146,5 +162,9 @@ func (f Flow) Create() (walk.Layout, error) {
return nil, err
}
+ if err := l.SetAlignment(walk.Alignment2D(f.Alignment)); err != nil {
+ return nil, err
+ }
+
return l, nil
}
diff --git a/flowlayout.go b/flowlayout.go
index e85ef820..1cf2ec4e 100644
--- a/flowlayout.go
+++ b/flowlayout.go
@@ -16,6 +16,7 @@ type FlowLayout struct {
margins Margins
size2MinSize map[Size]Size
spacing int
+ alignment Alignment2D
resetNeeded bool
}
@@ -86,6 +87,24 @@ func (l *FlowLayout) SetSpacing(value int) error {
return nil
}
+func (l *FlowLayout) Alignment() Alignment2D {
+ return l.alignment
+}
+
+func (l *FlowLayout) SetAlignment(alignment Alignment2D) error {
+ if alignment != l.alignment {
+ if alignment < AlignHVDefault || alignment > AlignHFarVFar {
+ return newError("invalid Alignment value")
+ }
+
+ l.alignment = alignment
+
+ l.Update(false)
+ }
+
+ return nil
+}
+
func (l *FlowLayout) StretchFactor(widget Widget) int {
if factor, ok := l.hwnd2StretchFactor[widget.Handle()]; ok {
return factor
@@ -176,7 +195,7 @@ func (l *FlowLayout) MinSizeForSize(size Size) Size {
margins.VFar = 0
}
- layoutItems, err := boxLayoutItems(widgets, Horizontal, bounds, margins, l.spacing, l.hwnd2StretchFactor)
+ layoutItems, err := boxLayoutItems(widgets, Horizontal, l.alignment, bounds, margins, l.spacing, l.hwnd2StretchFactor)
if err != nil {
return Size{}
}
@@ -258,7 +277,7 @@ func (l *FlowLayout) Update(reset bool) error {
margins.VFar = 0
}
- layoutItems, err := boxLayoutItems(widgets, Horizontal, bounds, margins, l.spacing, l.hwnd2StretchFactor)
+ layoutItems, err := boxLayoutItems(widgets, Horizontal, l.alignment, bounds, margins, l.spacing, l.hwnd2StretchFactor)
if err != nil {
return err
}
@@ -277,7 +296,7 @@ func (l *FlowLayout) Update(reset bool) error {
bounds.Height = maxSecondary + margins.VNear + margins.VFar
- if layoutItems, err = boxLayoutItems(widgets, Horizontal, bounds, margins, l.spacing, l.hwnd2StretchFactor); err != nil {
+ if layoutItems, err = boxLayoutItems(widgets, Horizontal, l.alignment, bounds, margins, l.spacing, l.hwnd2StretchFactor); err != nil {
return err
}
diff --git a/gridlayout.go b/gridlayout.go
index 313c8e60..5a3032b9 100644
--- a/gridlayout.go
+++ b/gridlayout.go
@@ -33,6 +33,7 @@ type GridLayout struct {
container Container
margins Margins
spacing int
+ alignment Alignment2D
resetNeeded bool
rowStretchFactors []int
columnStretchFactors []int
@@ -102,6 +103,24 @@ func (l *GridLayout) SetSpacing(value int) error {
return nil
}
+func (l *GridLayout) Alignment() Alignment2D {
+ return l.alignment
+}
+
+func (l *GridLayout) SetAlignment(alignment Alignment2D) error {
+ if alignment != l.alignment {
+ if alignment < AlignHVDefault || alignment > AlignHFarVFar {
+ return newError("invalid Alignment value")
+ }
+
+ l.alignment = alignment
+
+ l.Update(false)
+ }
+
+ return nil
+}
+
func (l *GridLayout) sufficientStretchFactors(stretchFactors []int, required int) []int {
oldLen := len(stretchFactors)
if oldLen < required {
@@ -595,8 +614,11 @@ func (l *GridLayout) Update(reset bool) error {
}
}
- w := l.spannedWidth(info, widths)
- h := l.spannedHeight(info, heights)
+ width := l.spannedWidth(info, widths)
+ height := l.spannedHeight(info, heights)
+
+ w := width
+ h := height
if lf := widget.LayoutFlags(); lf&GrowableHorz == 0 || lf&GrowableVert == 0 {
s := widget.SizeHint()
@@ -616,6 +638,26 @@ func (l *GridLayout) Update(reset bool) error {
}
}
+ if w != width {
+ switch l.alignment {
+ case AlignHCenterVNear, AlignHCenterVCenter, AlignHCenterVFar:
+ x += (width - w) / 2
+
+ case AlignHFarVNear, AlignHFarVCenter, AlignHFarVFar:
+ x += width - w
+ }
+ }
+
+ if h != height {
+ switch l.alignment {
+ case AlignHNearVCenter, AlignHCenterVCenter, AlignHFarVCenter:
+ y += (height - h) / 2
+
+ case AlignHNearVFar, AlignHCenterVFar, AlignHFarVFar:
+ y += height - h
+ }
+ }
+
items = append(items, layoutResultItem{widget: widget, bounds: Rectangle{X: x, Y: y, Width: w, Height: h}})
}