Thanks to visit codestin.com
Credit goes to github.com

Skip to content
2 changes: 1 addition & 1 deletion core/colormapbutton.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
// which can be edited using a [ColorMapButton].
type ColorMapName string

func (cm ColorMapName) Value() Value { return NewColorMapButton() }
func (cm ColorMapName) Widget() Value { return NewColorMapButton() }

// ColorMapButton displays a [colormap.Map] and can be clicked on
// to display a dialog for selecting different color map options.
Expand Down
2 changes: 1 addition & 1 deletion core/form.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ func (fm *Form) Init() {
})

tree.AddNew(p, valnm, func() Value {
return NewValue(reflectx.UnderlyingPointer(f.value).Interface(), f.field.Tag)
return NewFieldValue(f.field.Name, reflectx.UnderlyingPointer(f.parent).Interface(), reflectx.UnderlyingPointer(f.value).Interface(), f.field.Tag)
}, func(w Value) {
valueWidget = w
wb := w.AsWidget()
Expand Down
13 changes: 13 additions & 0 deletions core/form_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ type morePerson struct {
LikesPython bool
}

func (mp *morePerson) FieldWidget(field string) Value {
if field == "Job" {
return NewChooser().SetStrings("plumber", "dentist", "other")
}
return nil
}

func TestForm(t *testing.T) {
b := NewBody()
NewForm(b).SetStruct(&person{Name: "Go", Age: 35})
Expand All @@ -46,6 +53,12 @@ func TestFormReadOnly(t *testing.T) {
b.AssertRender(t, "form/read-only")
}

func TestFormFieldValue(t *testing.T) {
b := NewBody()
NewForm(b).SetStruct(&morePerson{Name: "Go", Age: 35})
b.AssertRender(t, "form/field-value")
}

func TestFormChange(t *testing.T) {
b := NewBody()
p := person{Name: "Go", Age: 35}
Expand Down
4 changes: 2 additions & 2 deletions core/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ func (tb *Table) MakeRow(p *tree.Plan, i int) {
si, _, invis := svi.SliceIndex(i)
itxt := strconv.Itoa(i)
val := tb.sliceElementValue(si)
// stru := val.Interface()
valPtr := reflectx.UnderlyingPointer(val).Interface()

if tb.ShowIndexes {
tb.MakeGridIndex(p, i, si, itxt, invis)
Expand All @@ -315,7 +315,7 @@ func (tb *Table) MakeRow(p *tree.Plan, i int) {
readOnlyTag := tags.Get("edit") == "-"

tree.AddNew(p, valnm, func() Value {
return NewValue(uvp.Interface(), tags)
return NewFieldValue(field.Name, valPtr, uvp.Interface(), tags)
}, func(w Value) {
wb := w.AsWidget()
tb.MakeValue(w, i)
Expand Down
7 changes: 7 additions & 0 deletions core/table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ type language struct {
Rating int
}

func (l *language) FieldWidget(field string) Value {
if field == "Rating" {
return NewSlider().SetMin(1).SetMax(10).SetStep(1)
}
return nil
}

func TestTable(t *testing.T) {
b := NewBody()
NewTable(b).SetSlice(&[]language{{"Go", 10}, {"Python", 5}})
Expand Down
40 changes: 36 additions & 4 deletions core/valuer.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ import (
)

// Valuer is an interface that types can implement to specify the
// [Value] that should be used to represent them in the GUI.
// [Value] Widget that should be used to represent them in the GUI.
type Valuer interface {

// Value returns the [Value] that should be used to represent
// Widget returns the [Value] Widget that should be used to represent
// the value in the GUI. If it returns nil, then [ToValue] will
// fall back onto the next step. This function must NOT call [Bind].
Value() Value
Widget() Value
}

// ValueTypes is a map of functions that return a [Value]
Expand Down Expand Up @@ -76,7 +76,7 @@ func NewValue(value any, tags reflect.StructTag, parent ...tree.Node) Value {
// it falls back on the next step.
func toValue(value any, tags reflect.StructTag) Value {
if vwr, ok := value.(Valuer); ok {
if vw := vwr.Value(); vw != nil {
if vw := vwr.Widget(); vw != nil {
return vw
}
}
Expand Down Expand Up @@ -155,6 +155,38 @@ func toValue(value any, tags reflect.StructTag) Value {
return NewTextField() // final fallback
}

// FieldWidgeter is an interface that struct types can implement to specify the
// [Value] Widget that should be used to represent specific fields in the GUI,
// via the FieldWidget method. For [Form] and [Table] widgets.
type FieldWidgeter interface {

// FieldWidget returns the [Value] that should be used to represent
// the field with the given name in the GUI. If it returns nil, then
// the default is used based on display tags, type, etc. This function
// must NOT call [Bind].
FieldWidget(field string) Value
}

// NewFieldValue converts the given value into an appropriate [Value] widget
// whose associated value is bound to the given value. The given value must
// be a pointer. It uses the given field name and parent struct pointer for
// context, such as if the parent struct implements [FieldWidgeter]. This
// function is used in [Form] and [Table] and generally should not be called
// by end users directly.
//
// It uses the given optional struct tags for additional context
// and to determine styling properties via [styleFromTags]. It also adds the
// resulting [Value] to the given optional parent if it specified.
func NewFieldValue(field string, str any, value any, tags reflect.StructTag, parent ...tree.Node) Value {
if fw, ok := str.(FieldWidgeter); ok {
v := fw.FieldWidget(field)
if v != nil {
return v
}
}
return NewValue(value, tags, parent...)
}

func init() {
AddValueType[icons.Icon, IconButton]()
AddValueType[time.Time, TimeInput]()
Expand Down
2 changes: 1 addition & 1 deletion svg/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,7 @@ func (sv *SVG) UnmarshalXML(decoder *xml.Decoder, se xml.StartElement) error {
func (sv *SVG) XMLString() string {
var b bytes.Buffer
sv.WriteXML(&b, false)
return string(b.Bytes())
return b.String()
}

// SaveXML saves the svg to a XML-encoded file, using WriteXML
Expand Down
2 changes: 1 addition & 1 deletion xyz/xyzcore/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (mb *MeshButton) Init() {
TODO: This doesn't work because texture is on Material which doesn't have a pointer to the Scene! (https://github.com/cogentcore/core/issues/1023)

// Value restylesers TexValue as the viewer of TexName
func (mn TexName) Value() core.Value {
func (mn TexName) Widget() core.Value {
vv := TexValue{}
vv.Init(&vv)
return &vv
Expand Down
Loading