bindMapKey is a version of [Bind] that works for keys in a map.
(mapv reflect.Value, key reflect.Value, vw T)
| 228 | |
| 229 | // bindMapKey is a version of [Bind] that works for keys in a map. |
| 230 | func bindMapKey[T Value](mapv reflect.Value, key reflect.Value, vw T) T { |
| 231 | wb := vw.AsWidget() |
| 232 | alreadyBound := wb.ValueUpdate != nil |
| 233 | wb.ValueUpdate = func() { |
| 234 | if vws, ok := any(vw).(ValueSetter); ok { |
| 235 | ErrorSnackbar(vw, vws.SetWidgetValue(key.Interface())) |
| 236 | } else { |
| 237 | ErrorSnackbar(vw, reflectx.SetRobust(vw.WidgetValue(), key.Interface())) |
| 238 | } |
| 239 | } |
| 240 | wb.ValueOnChange = func() { |
| 241 | newKey := reflect.New(key.Type()) |
| 242 | ErrorSnackbar(vw, reflectx.SetRobust(newKey.Interface(), vw.WidgetValue())) |
| 243 | newKey = newKey.Elem() |
| 244 | if !mapv.MapIndex(newKey).IsValid() { // not already taken |
| 245 | mapv.SetMapIndex(newKey, mapv.MapIndex(key)) |
| 246 | mapv.SetMapIndex(key, reflect.Value{}) |
| 247 | return |
| 248 | } |
| 249 | d := NewBody().AddTitle("Key already exists").AddText(fmt.Sprintf("The key %q already exists", reflectx.ToString(newKey.Interface()))) |
| 250 | d.AddBottomBar(func(parent Widget) { |
| 251 | d.AddCancel(parent) |
| 252 | d.AddOK(parent).SetText("Overwrite").OnClick(func(e events.Event) { |
| 253 | mapv.SetMapIndex(newKey, mapv.MapIndex(key)) |
| 254 | mapv.SetMapIndex(key, reflect.Value{}) |
| 255 | wb.SendChange() |
| 256 | }) |
| 257 | }) |
| 258 | d.RunDialog(vw) |
| 259 | } |
| 260 | if alreadyBound { |
| 261 | ResetWidgetValue(vw) |
| 262 | } |
| 263 | if ob, ok := any(vw).(OnBinder); ok { |
| 264 | ob.OnBind(key.Interface(), "") |
| 265 | } |
| 266 | wb.ValueUpdate() // we update it with the initial value immediately |
| 267 | return vw |
| 268 | } |
| 269 | |
| 270 | // bindMapValue is a version of [Bind] that works for values in a map. |
| 271 | func bindMapValue[T Value](mapv reflect.Value, key reflect.Value, vw T) T { |
no test coverage detected