From 363c6a3fe24db00a732b4e65f056fb3af4eaebe8 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Mon, 20 Sep 2021 17:12:33 +0200 Subject: [PATCH 1/4] alignment: refactoring: consider a case when *RowWidget is a part of Layout added EXPERIMENTAL, public method GetWidgetWidth, which calculates a width of widget. (related with #341) --- Alignment.go | 74 ++++++++++++++++++++++++++++++++--------- examples/align/align.go | 7 ++++ 2 files changed, 65 insertions(+), 16 deletions(-) diff --git a/Alignment.go b/Alignment.go index 6344bfc1..9c651813 100644 --- a/Alignment.go +++ b/Alignment.go @@ -24,10 +24,8 @@ type AlignmentSetter struct { // Align sets widgets alignment. // usage: see examples/align // -// FIXME: DONOT put giu widgets inside of CustomWidget function in -// Align setter. CustomWidgets will be skip in alignment process -// -// BUG: DatePickerWidget doesn't work properly +// - BUG: DatePickerWidget doesn't work properly +// - BUG: there is some bug with SelectableWidget func Align(at AlignmentType) *AlignmentSetter { return &AlignmentSetter{ alignType: at, @@ -58,25 +56,14 @@ func (a *AlignmentSetter) Build() { return } - // exclude some widgets from alignment process switch item.(type) { case *CustomWidget: item.Build() return } - // save cursor position before rendering currentPos := GetCursorPos() - - // render widget in `dry` mode - imgui.PushStyleVarFloat(imgui.StyleVarAlpha, 0) - item.Build() - imgui.PopStyleVar() - - // save widget's width - size := imgui.GetItemRectSize() - w := size.X - + w := GetWidgetWidth(item) availableW, _ := GetAvailableRegion() // set cursor position to align the widget @@ -95,3 +82,58 @@ func (a *AlignmentSetter) Build() { item.Build() }) } + +// GetWidgetWidth returns a width of widget +// NOTE: user-definied widgets, which contains more than one +// giu widget will be processed incorrectly (only width of the last built +// widget will be processed) +// NOTE: THIS IS A BETA SOLUTION and may contain bugs +// there is an upstream issue for this problem: +// https://github.com/ocornut/imgui/issues/3714 +// this is just workaround used in giu. +// +// here is a list of known bugs: +// - BUG: Custom widgets are skipped, so if user put some widgets +// inside of CustomWidget, its sizes will not be returned +// +// if you find anything else, please report it on +// https://github.com/AllenDang/giu Any contribution is appreciated! +func GetWidgetWidth(w Widget) (result float32) { + // save cursor position before rendering + currentPos := GetCursorPos() + // enumerate some special cases + switch typed := w.(type) { + // Don't process custom widgets + case *CustomWidget: + return 0 + // when row, sum all widget's sizes (adding spacing) + case *RowWidget: + isFirst := true + typed.widgets.Range(func(r Widget) { + result += GetWidgetWidth(r) + if !isFirst { + spacing, _ := GetItemSpacing() + result += spacing + } else { + isFirst = false + } + }) + return result + // panic if layout - cannot calculate width of multiple widgets + case Layout, *Layout: + panic("GetWidgetWidth: requires Widget argument, but []Widget (Layout) got") + default: + // render widget in `dry` mode + imgui.PushStyleVarFloat(imgui.StyleVarAlpha, 0) + w.Build() + imgui.PopStyleVar() + + // save widget's width + size := imgui.GetItemRectSize() + result = size.X + } + + SetCursorPos(currentPos) + + return result +} diff --git a/examples/align/align.go b/examples/align/align.go index 55b7abcf..76b4de32 100644 --- a/examples/align/align.go +++ b/examples/align/align.go @@ -24,6 +24,13 @@ func loop() { }, giu.Label("I'm the last label"), ), + giu.Label("Buttons in row:"), + giu.Align(giu.AlignCenter).To( + giu.Row( + giu.Button("button 1"), + giu.Button("button 2"), + ), + ), ) } From 84fb8376f848f40eebf6801ad092f75541c50046 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Mon, 20 Sep 2021 19:06:57 +0200 Subject: [PATCH 2/4] alignsetter: add some special cases --- Alignment.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Alignment.go b/Alignment.go index 9c651813..b1f548ce 100644 --- a/Alignment.go +++ b/Alignment.go @@ -57,9 +57,17 @@ func (a *AlignmentSetter) Build() { } switch item.(type) { + // ok, it doesn't make sense to align two times :-) + case *AlignmentSetter: + item.Build() + return case *CustomWidget: item.Build() return + // there is a bug with selectables, so skip them for now + case *SelectableWidget: + item.Build() + return } currentPos := GetCursorPos() From 2baf931c2ec9336bcdc7585ee496dee0f6ef1f23 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Mon, 20 Sep 2021 19:09:48 +0200 Subject: [PATCH 3/4] alignsetter: except combos (bug) --- Alignment.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Alignment.go b/Alignment.go index b1f548ce..d03dc35d 100644 --- a/Alignment.go +++ b/Alignment.go @@ -26,6 +26,7 @@ type AlignmentSetter struct { // // - BUG: DatePickerWidget doesn't work properly // - BUG: there is some bug with SelectableWidget +// - BUG: ComboWidget and ComboCustomWidgets doesn't work properly func Align(at AlignmentType) *AlignmentSetter { return &AlignmentSetter{ alignType: at, @@ -64,8 +65,8 @@ func (a *AlignmentSetter) Build() { case *CustomWidget: item.Build() return - // there is a bug with selectables, so skip them for now - case *SelectableWidget: + // there is a bug with selectables and combos, so skip them for now + case *SelectableWidget, *ComboWidget, *ComboCustomWidget: item.Build() return } From cb2408097a0540e08ed40d180dbcbcaa890d90aa Mon Sep 17 00:00:00 2001 From: gucio321 Date: Mon, 20 Sep 2021 21:25:15 +0200 Subject: [PATCH 4/4] update comment --- Alignment.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Alignment.go b/Alignment.go index d03dc35d..f5588b72 100644 --- a/Alignment.go +++ b/Alignment.go @@ -49,8 +49,6 @@ func (a *AlignmentSetter) Build() { return } - // WORKAROUND: get widgets widths rendering them with 100% transparency - // to align them later a.layout.Range(func(item Widget) { // if item is inil, just skip it if item == nil { @@ -58,7 +56,7 @@ func (a *AlignmentSetter) Build() { } switch item.(type) { - // ok, it doesn't make sense to align two times :-) + // ok, it doesn't make sense to align again :-) case *AlignmentSetter: item.Build() return @@ -93,13 +91,16 @@ func (a *AlignmentSetter) Build() { } // GetWidgetWidth returns a width of widget +// NOTE: THIS IS A BETA SOLUTION and may contain bugs +// in most cases, you may want to use supported by imgui GetItemRectSize. +// There is an upstream issue for this problem: +// https://github.com/ocornut/imgui/issues/3714 +// +// This function is just a workaround used in giu. +// // NOTE: user-definied widgets, which contains more than one // giu widget will be processed incorrectly (only width of the last built // widget will be processed) -// NOTE: THIS IS A BETA SOLUTION and may contain bugs -// there is an upstream issue for this problem: -// https://github.com/ocornut/imgui/issues/3714 -// this is just workaround used in giu. // // here is a list of known bugs: // - BUG: Custom widgets are skipped, so if user put some widgets