From 164b76070224c1a64695b1b9fa5ee02a0ae841ef Mon Sep 17 00:00:00 2001 From: "U-ultrahorst\\elmar" Date: Fri, 1 Jun 2018 13:26:26 +0200 Subject: [PATCH] add Target assignments to widgets This allows to define widgets inside the main UI in the natural order. Widgets that are referenced from other widgets can do so by Target pointers. This is an example implementation for mjl-/duit#9 --- examples/alert/alert.go | 9 +++++---- examples/basic/main.go | 5 +++-- examples/demo/main.go | 6 ++++-- field.go | 5 +++++ label.go | 11 ++++++++--- radiobutton.go | 5 +++++ 6 files changed, 30 insertions(+), 11 deletions(-) diff --git a/examples/alert/alert.go b/examples/alert/alert.go index 3f42d0e..d60bb9f 100644 --- a/examples/alert/alert.go +++ b/examples/alert/alert.go @@ -17,16 +17,17 @@ func main() { dui, err := duit.NewDUI("ex/alert", &duit.DUIOpts{Dimensions: "400x300"}) check(err, "new dui") - field := &duit.Field{ - Text: "type an alert message here", - } + var field *duit.Field dui.Top.UI = &duit.Box{ Padding: duit.SpaceXY(6, 4), Margin: image.Pt(6, 4), Valign: duit.ValignMiddle, Kids: duit.NewKids( - field, + &duit.Field{ + Target: &field, + Text: "type an alert message here", + }, &duit.Button{ Text: "click me to create an alert", Click: func() (e duit.Event) { diff --git a/examples/basic/main.go b/examples/basic/main.go index 793f081..eef5216 100644 --- a/examples/basic/main.go +++ b/examples/basic/main.go @@ -18,7 +18,8 @@ func main() { // assign some UIs to variables, so we can reference // and modify them in the button click handler. - status := &duit.Label{Text: "status: not logged in yet"} + var status *duit.Label + username := &duit.Field{} password := &duit.Field{Password: true} login := &duit.Button{ @@ -57,7 +58,7 @@ func main() { Margin: image.Pt(6, 4), // space between kids in this box // duit.NewKids is a convenience function turning UIs into Kids Kids: duit.NewKids( - status, + &duit.Label{Target: &status, Text: "status: not logged in yet"}, &duit.Grid{ Columns: 2, Padding: []duit.Space{ diff --git a/examples/demo/main.go b/examples/demo/main.go index f93a9ca..68e05dd 100644 --- a/examples/demo/main.go +++ b/examples/demo/main.go @@ -30,7 +30,7 @@ func main() { } count := 0 - counter := &duit.Label{Text: fmt.Sprintf("%d", count)} + var counter *duit.Label tick := make(chan struct{}, 0) go func() { for { @@ -39,6 +39,8 @@ func main() { } }() + // We cannot define the RadiobuttonGroup inside the main UI. + // It cannot be assigned to a Target, as it is just a slice. radio1 := &duit.Radiobutton{ Selected: true, Value: 1, @@ -116,7 +118,7 @@ func main() { Margin: image.Pt(6, 4), Kids: duit.NewKids( &duit.Label{Text: "counter:"}, - counter, + &duit.Label{Target: &counter, Text: fmt.Sprintf("%d", count)}, &duit.Button{ Text: "button1", Colorset: &dui.Primary, diff --git a/field.go b/field.go index 2310244..dce68e0 100644 --- a/field.go +++ b/field.go @@ -12,6 +12,7 @@ import ( // Field is a single line text field. The cursor is always visible, and determines which part of the text is shown. type Field struct { + Target **Field `json:"-"` // Reference to itself. Text string // Current text. Placeholder string // Text displayed in lighter color as example. Disabled bool // If disabled, mouse and key input have no effect. @@ -80,6 +81,10 @@ func (ui *Field) removeSelection() { func (ui *Field) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool) { dui.debugLayout(self) + if ui.Target != nil { + *ui.Target = ui + } + ui.size = image.Point{sizeAvail.X, ui.font(dui).Height + 2*ui.space(dui).Y} self.R = rect(ui.size) return diff --git a/label.go b/label.go index cca08e6..e3e8fc1 100644 --- a/label.go +++ b/label.go @@ -12,9 +12,10 @@ import ( // cmd-c, copy text // \n, like button1 click, calls the Click function type Label struct { - Text string // Text to draw, wrapped at glyph boundary. - Font *draw.Font `json:"-"` // For drawing text. - Click func() (e Event) `json:"-"` // Called on button1 click. + Target **Label `json:"-"` + Text string // Text to draw, wrapped at glyph boundary. + Font *draw.Font `json:"-"` // For drawing text. + Click func() (e Event) `json:"-"` // Called on button1 click. lines []string size image.Point @@ -30,6 +31,10 @@ func (ui *Label) font(dui *DUI) *draw.Font { func (ui *Label) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool) { dui.debugLayout(self) + if ui.Target != nil { + *ui.Target = ui + } + font := ui.font(dui) ui.lines = []string{} s := 0 diff --git a/radiobutton.go b/radiobutton.go index 277f13f..9e63468 100644 --- a/radiobutton.go +++ b/radiobutton.go @@ -8,6 +8,7 @@ import ( // Radiobutton is typically part of a group of radiobuttons, with exactly one of them selected. Labels are not part of the radiobutton itself. type Radiobutton struct { + Target **Radiobutton `json:"-"` Selected bool Disabled bool // If set, cannot be selected. Group RadiobuttonGroup // Other radiobuttons as part of this group. If a radiobutton is selected, others in the group are unselected. @@ -54,6 +55,10 @@ func (ui *Radiobutton) innerDim(dui *DUI) int { func (ui *Radiobutton) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool) { dui.debugLayout(self) + if ui.Target != nil { + *ui.Target = ui + } + hit := image.Point{0, 1} size := pt(2*BorderSize + 7*dui.Display.DefaultFont.Height/10).Add(hit) self.R = rect(size)