func RunAnimalDialog(owner walk.Form, animal *Animal) (int, error) { var dlg *walk.Dialog var db *walk.DataBinder var ep walk.ErrorPresenter var acceptPB, cancelPB *walk.PushButton return Dialog{ AssignTo: &dlg, Title: "Animal Details", DefaultButton: &acceptPB, CancelButton: &cancelPB, DataBinder: DataBinder{ AssignTo: &db, DataSource: animal, ErrorPresenter: ErrorPresenterRef{&ep}, }, MinSize: Size{300, 300}, Layout: VBox{}, Children: []Widget{ Composite{ Layout: Grid{Columns: 2}, Children: []Widget{ Label{ Text: "Name:", }, LineEdit{ Text: Bind("Name"), }, Label{ Text: "Arrival Date:", }, DateEdit{ Date: Bind("ArrivalDate"), }, Label{ Text: "Species:", }, ComboBox{ Value: Bind("SpeciesId", SelRequired{}), BindingMember: "Id", DisplayMember: "Name", Model: KnownSpecies(), }, RadioButtonGroupBox{ ColumnSpan: 2, Title: "Sex", Layout: HBox{}, DataMember: "Sex", Buttons: []RadioButton{ {Text: "Male", Value: SexMale}, {Text: "Female", Value: SexFemale}, {Text: "Hermaphrodite", Value: SexHermaphrodite}, }, }, Label{ Text: "Weight:", }, NumberEdit{ Value: Bind("Weight", Range{0.01, 9999.99}), Suffix: " kg", Decimals: 2, }, Label{ Text: "Preferred Food:", }, ComboBox{ Editable: true, Value: Bind("PreferredFood"), Model: []string{"Fruit", "Grass", "Fish", "Meat"}, }, Label{ Text: "Domesticated:", }, CheckBox{ Checked: Bind("Domesticated"), }, VSpacer{ ColumnSpan: 2, Size: 8, }, Label{ ColumnSpan: 2, Text: "Remarks:", }, TextEdit{ ColumnSpan: 2, MinSize: Size{100, 50}, Text: Bind("Remarks"), }, LineErrorPresenter{ AssignTo: &ep, ColumnSpan: 2, }, }, }, Composite{ Layout: HBox{}, Children: []Widget{ HSpacer{}, PushButton{ AssignTo: &acceptPB, Text: "OK", OnClicked: func() { if err := db.Submit(); err != nil { log.Print(err) return } dlg.Accept() }, }, PushButton{ AssignTo: &cancelPB, Text: "Cancel", OnClicked: func() { dlg.Cancel() }, }, }, }, }, }.Run(owner) }
func (d Dialog) Create(owner walk.Form) error { w, err := walk.NewDialog(owner) if err != nil { return err } tlwi := topLevelWindowInfo{ Name: d.Name, Font: d.Font, ToolTipText: "", MinSize: d.MinSize, MaxSize: d.MaxSize, ContextMenuItems: d.ContextMenuItems, DataBinder: d.DataBinder, Layout: d.Layout, Children: d.Children, OnKeyDown: d.OnKeyDown, OnKeyPress: d.OnKeyPress, OnKeyUp: d.OnKeyUp, OnMouseDown: d.OnMouseDown, OnMouseMove: d.OnMouseMove, OnMouseUp: d.OnMouseUp, OnSizeChanged: d.OnSizeChanged, } var db *walk.DataBinder if d.DataBinder.AssignTo == nil { d.DataBinder.AssignTo = &db } builder := NewBuilder(nil) w.SetSuspended(true) builder.Defer(func() error { w.SetSuspended(false) return nil }) return builder.InitWidget(tlwi, w, func() error { if err := w.SetTitle(d.Title); err != nil { return err } if err := w.SetSize(d.Size.toW()); err != nil { return err } if d.DefaultButton != nil { if err := w.SetDefaultButton(*d.DefaultButton); err != nil { return err } if db := *d.DataBinder.AssignTo; db != nil { (*d.DefaultButton).SetEnabled(db.CanSubmit()) db.CanSubmitChanged().Attach(func() { (*d.DefaultButton).SetEnabled(db.CanSubmit()) }) } } if d.CancelButton != nil { if err := w.SetCancelButton(*d.CancelButton); err != nil { return err } } if d.AssignTo != nil { *d.AssignTo = w } return nil }) }
func (b *Builder) InitWidget(d Widget, w walk.Window, customInit func() error) error { b.level++ defer func() { b.level-- }() var succeeded bool defer func() { if !succeeded { w.Dispose() } }() b.declWidgets = append(b.declWidgets, declWidget{d, w}) // Widget name, _, _, font, toolTipText, minSize, maxSize, stretchFactor, row, rowSpan, column, columnSpan, contextMenuItems, onKeyDown, onKeyPress, onKeyUp, onMouseDown, onMouseMove, onMouseUp, onSizeChanged := d.WidgetInfo() w.SetName(name) if name != "" { b.name2Window[name] = w } if toolTipText != "" { if widget, ok := w.(walk.Widget); ok { if err := widget.SetToolTipText(toolTipText); err != nil { return err } } } if err := w.SetMinMaxSize(minSize.toW(), maxSize.toW()); err != nil { return err } if len(contextMenuItems) > 0 { cm, err := walk.NewMenu() if err != nil { return err } b.deferBuildMenuActions(cm, contextMenuItems) w.SetContextMenu(cm) } if onKeyDown != nil { w.KeyDown().Attach(onKeyDown) } if onKeyPress != nil { w.KeyPress().Attach(onKeyPress) } if onKeyUp != nil { w.KeyUp().Attach(onKeyUp) } if onMouseDown != nil { w.MouseDown().Attach(onMouseDown) } if onMouseMove != nil { w.MouseMove().Attach(onMouseMove) } if onMouseUp != nil { w.MouseUp().Attach(onMouseUp) } if onSizeChanged != nil { w.SizeChanged().Attach(onSizeChanged) } if widget, ok := w.(walk.Widget); ok { if p := widget.Parent(); p != nil { switch l := p.Layout().(type) { case *walk.BoxLayout: if stretchFactor < 1 { stretchFactor = 1 } if err := l.SetStretchFactor(widget, stretchFactor); err != nil { return err } case *walk.GridLayout: if rowSpan < 1 { rowSpan = 1 } if columnSpan < 1 { columnSpan = 1 } if b.columns > 0 && row == 0 && column == 0 { if b.col+columnSpan > b.columns { b.row++ b.col = 0 } row = b.row column = b.col b.col += columnSpan } r := walk.Rectangle{column, row, columnSpan, rowSpan} if err := l.SetRange(widget, r); err != nil { return err } } } } oldParent := b.parent // Container var db *walk.DataBinder if dc, ok := d.(Container); ok { if wc, ok := w.(walk.Container); ok { dataBinder, layout, children := dc.ContainerInfo() if layout != nil { l, err := layout.Create() if err != nil { return err } if err := wc.SetLayout(l); err != nil { return err } } b.parent = wc defer func() { b.parent = oldParent }() if g, ok := layout.(Grid); ok { columns := b.columns defer func() { b.columns, b.row, b.col = columns, row, column+columnSpan }() b.columns = g.Columns b.row = 0 b.col = 0 } for _, child := range children { if err := child.Create(b); err != nil { return err } } var err error if db, err = dataBinder.create(); err != nil { return err } } } // Custom if customInit != nil { if err := customInit(); err != nil { return err } } b.parent = oldParent // Widget continued if font != nil { if f, err := font.Create(); err != nil { return err } else if f != nil { w.SetFont(f) } } if b.level == 1 { if err := b.initProperties(); err != nil { return err } } // Call Reset on DataBinder after customInit, so a Dialog gets a chance to first // wire up its DefaultButton to the CanSubmitChanged event of a DataBinder. if db != nil { if _, ok := d.(Container); ok { if wc, ok := w.(walk.Container); ok { b.Defer(func() error { // FIXME: Currently SetDataBinder must be called after initProperties. wc.SetDataBinder(db) return db.Reset() }) } } } if b.level == 1 { for _, f := range b.deferredFuncs { if err := f(); err != nil { return err } } } succeeded = true return nil }