From 522ee6099fd349521b492922a145795db0410b90 Mon Sep 17 00:00:00 2001 From: Svart Adam Solander Date: Tue, 20 Sep 2022 15:33:37 +0200 Subject: [PATCH 1/4] "Added custom binding 'DisableableBinding' and added it to README.md." --- README.md | 16 ++++++-- data/binding/disableableBinding.go | 61 ++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 data/binding/disableableBinding.go diff --git a/README.md b/README.md index 69ee797a..0fb176e3 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Optionally, Each canvas object can be encapsulated with `Responsive()` function ```go layout := NewResponsiveLayout( Responsive(object1), // all sizes to 100% - Responsive(object2, 0.5, 0.75), // small to 50%, medium to 75%, all others to 100% + Responsive(object2, 0.5, 0.75), // small to 50%, medium to 75%, all others to 100% ) ``` @@ -59,7 +59,7 @@ Community contributed widgets. ### Calendar - + A date picker which returns a [time](https://pkg.go.dev/time) object with the selected date. @@ -69,7 +69,7 @@ A date picker which returns a [time](https://pkg.go.dev/time) object with the se

- + To use create a new calendar with a given time and a callback function: @@ -224,6 +224,16 @@ if err := token.Error(); err != nil { s, err := binding.NewMqttString(client, "fyne.io/x/string") ``` +### DisableableBinding + +A `DisableableBinding` creates a `Bool` data binding which accepts `Disableable` targets to control. +When the `bool` binding is changed, all targets `Enable` or `Disable` methods will be executed depending on the settings. + +The binding accepts targets when created with `NewDisableableBinding` or via the method `AddTargets`. +The behaviour of the binding can be inverted, so true disables and false enables. This is done through method `Invert`. + +All targets are updated when either `AddTargets` or `Invert` is executed. + ## Data Validation Community contributed validators. diff --git a/data/binding/disableableBinding.go b/data/binding/disableableBinding.go new file mode 100644 index 00000000..11ad236d --- /dev/null +++ b/data/binding/disableableBinding.go @@ -0,0 +1,61 @@ +package binding + +import ( + "log" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/data/binding" +) + +type disableableBinding struct { + binding.Bool + + inverted bool + targets []fyne.Disableable +} + +// NewDisableableBinding returns a `Bool` binding which accepts Disableable targets. +// When the Bool changes, the targets Enable or Disable method will be executed. +func NewDisableableBinding(targets ...fyne.Disableable) *disableableBinding { + newBinding := &disableableBinding{ + Bool: binding.NewBool(), + targets: targets, + } + + // Add default listener + newBinding.AddListener(binding.NewDataListener(newBinding.update)) + + return newBinding +} + +// Adding targets to the binding. +// This will update the Disable status of the targets immediately. +func (b *disableableBinding) AddTargets(targets ...fyne.Disableable) { + b.targets = append(b.targets, targets...) + b.update() +} + +// Invert will switch the behavior of when the targets will be Enabled or Disabled. +// This will update the Disable status of the targets immediately. +func (b *disableableBinding) Invert(inverted bool) { + b.inverted = inverted + b.update() +} + +func (b *disableableBinding) update() { + val, err := b.Get() + if err != nil { + log.Println(err) + return + } + + if (!b.inverted && val) || (b.inverted && !val) { + for _, target := range b.targets { + target.Enable() + } + } else { + for _, target := range b.targets { + target.Disable() + } + } +} From ba137c2fc4fecef25e11be90178dffe089b84a42 Mon Sep 17 00:00:00 2001 From: Svart Adam Solander Date: Thu, 22 Sep 2022 09:41:45 +0200 Subject: [PATCH 2/4] "Substituted the name 'targets' for 'widgets' consistantly throughout the disableable binding and in the information for it in README.md." --- README.md | 8 ++++---- data/binding/disableableBinding.go | 32 +++++++++++++++--------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 0fb176e3..ec2d4cac 100644 --- a/README.md +++ b/README.md @@ -226,13 +226,13 @@ s, err := binding.NewMqttString(client, "fyne.io/x/string") ### DisableableBinding -A `DisableableBinding` creates a `Bool` data binding which accepts `Disableable` targets to control. -When the `bool` binding is changed, all targets `Enable` or `Disable` methods will be executed depending on the settings. +A `DisableableBinding` creates a `Bool` data binding which accepts `Disableable` widgets to control. +When the `bool` binding is changed, all widgets `Enable` or `Disable` methods will be executed depending on the settings. -The binding accepts targets when created with `NewDisableableBinding` or via the method `AddTargets`. +The binding accepts widgets when created with `NewDisableableBinding` or via the method `AddWidgets`. The behaviour of the binding can be inverted, so true disables and false enables. This is done through method `Invert`. -All targets are updated when either `AddTargets` or `Invert` is executed. +All widgets are updated when either `AddWidgets` or `Invert` is executed. ## Data Validation diff --git a/data/binding/disableableBinding.go b/data/binding/disableableBinding.go index 11ad236d..7183f037 100644 --- a/data/binding/disableableBinding.go +++ b/data/binding/disableableBinding.go @@ -11,15 +11,15 @@ type disableableBinding struct { binding.Bool inverted bool - targets []fyne.Disableable + widgets []fyne.Disableable } -// NewDisableableBinding returns a `Bool` binding which accepts Disableable targets. -// When the Bool changes, the targets Enable or Disable method will be executed. -func NewDisableableBinding(targets ...fyne.Disableable) *disableableBinding { +// NewDisableableBinding returns a `Bool` binding which accepts Disableable widgets. +// When the Bool changes, the widgets Enable or Disable method will be executed. +func NewDisableableBinding(widgets ...fyne.Disableable) *disableableBinding { newBinding := &disableableBinding{ Bool: binding.NewBool(), - targets: targets, + widgets: widgets, } // Add default listener @@ -28,16 +28,16 @@ func NewDisableableBinding(targets ...fyne.Disableable) *disableableBinding { return newBinding } -// Adding targets to the binding. -// This will update the Disable status of the targets immediately. -func (b *disableableBinding) AddTargets(targets ...fyne.Disableable) { - b.targets = append(b.targets, targets...) +// Adding widgets to the binding. +// This will update the Disable status of the widgets immediately. +func (b *disableableBinding) AddWidgets(widgets ...fyne.Disableable) { + b.widgets = append(b.widgets, widgets...) b.update() } -// Invert will switch the behavior of when the targets will be Enabled or Disabled. -// This will update the Disable status of the targets immediately. -func (b *disableableBinding) Invert(inverted bool) { +// SetInverted will switch the behavior of when the widgets will be Enabled or Disabled. +// This will update the Disable status of the widgets immediately. +func (b *disableableBinding) SetInverted(inverted bool) { b.inverted = inverted b.update() } @@ -50,12 +50,12 @@ func (b *disableableBinding) update() { } if (!b.inverted && val) || (b.inverted && !val) { - for _, target := range b.targets { - target.Enable() + for _, widget := range b.widgets { + widget.Enable() } } else { - for _, target := range b.targets { - target.Disable() + for _, widget := range b.widgets { + widget.Disable() } } } From a3744b376a14dd9aea033de0a67808819102d22f Mon Sep 17 00:00:00 2001 From: Svart Adam Solander Date: Wed, 28 Sep 2022 11:33:16 +0200 Subject: [PATCH 3/4] "NewDisableableBinding now returns an interface." --- data/binding/disableableBinding.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/data/binding/disableableBinding.go b/data/binding/disableableBinding.go index 7183f037..a29a4977 100644 --- a/data/binding/disableableBinding.go +++ b/data/binding/disableableBinding.go @@ -7,7 +7,15 @@ import ( "fyne.io/fyne/v2/data/binding" ) -type disableableBinding struct { +// DisableableBinding is a `Bool` binding with accept Disableable widgets that it will control the Disabled status of. +type DisableableBinding interface { + binding.Bool + + AddWidgets(...fyne.Disableable) + SetInverted(bool) +} + +type boundDisableable struct { binding.Bool inverted bool @@ -16,8 +24,8 @@ type disableableBinding struct { // NewDisableableBinding returns a `Bool` binding which accepts Disableable widgets. // When the Bool changes, the widgets Enable or Disable method will be executed. -func NewDisableableBinding(widgets ...fyne.Disableable) *disableableBinding { - newBinding := &disableableBinding{ +func NewDisableableBinding(widgets ...fyne.Disableable) DisableableBinding { + newBinding := &boundDisableable{ Bool: binding.NewBool(), widgets: widgets, } @@ -30,19 +38,19 @@ func NewDisableableBinding(widgets ...fyne.Disableable) *disableableBinding { // Adding widgets to the binding. // This will update the Disable status of the widgets immediately. -func (b *disableableBinding) AddWidgets(widgets ...fyne.Disableable) { +func (b *boundDisableable) AddWidgets(widgets ...fyne.Disableable) { b.widgets = append(b.widgets, widgets...) b.update() } // SetInverted will switch the behavior of when the widgets will be Enabled or Disabled. // This will update the Disable status of the widgets immediately. -func (b *disableableBinding) SetInverted(inverted bool) { +func (b *boundDisableable) SetInverted(inverted bool) { b.inverted = inverted b.update() } -func (b *disableableBinding) update() { +func (b *boundDisableable) update() { val, err := b.Get() if err != nil { log.Println(err) From cd41cfdad5c09d2152422a266712fb94aadcbac4 Mon Sep 17 00:00:00 2001 From: Svart Adam Solander Date: Wed, 28 Sep 2022 11:33:40 +0200 Subject: [PATCH 4/4] "Added test for DisableableBinding." --- data/binding/disableableBinding_test.go | 64 +++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 data/binding/disableableBinding_test.go diff --git a/data/binding/disableableBinding_test.go b/data/binding/disableableBinding_test.go new file mode 100644 index 00000000..eda6eb0f --- /dev/null +++ b/data/binding/disableableBinding_test.go @@ -0,0 +1,64 @@ +package binding + +import ( + "testing" + "time" + + "fyne.io/fyne/v2/test" + "fyne.io/fyne/v2/widget" +) + +// Since it's a callback we're testing, we let it process for some time before checking for result. +const callbackWait = 10 * time.Millisecond + +func TestDisableableBinding(t *testing.T) { + test.NewApp() + + bound := NewDisableableBinding() + widget1 := widget.NewEntry() + widget2 := widget.NewSelectEntry([]string{"test1", "test2"}) + + if widget1.Disabled() || widget2.Disabled() { + t.Errorf("test ended early because of wrong initial values on widgets.") + return + } + + // Adding widgets + bound.AddWidgets(widget1, widget2) + + boundCheck := widget.NewCheckWithData("My bound checkbox", bound) + + // Checking not inverted + boundCheck.SetChecked(true) + + // Since it's a callback we're testing, we let it process for some time before checking for result. + <-time.After(callbackWait) + if widget1.Disabled() || widget2.Disabled() { + t.Errorf("Widget1 or 2 was not enabled.") + return + } + + boundCheck.SetChecked(false) + <-time.After(callbackWait) + if !widget1.Disabled() || !widget2.Disabled() { + t.Errorf("Widget1 or 2 was not disabled.") + return + } + + // Checking inverted + bound.SetInverted(true) + + boundCheck.SetChecked(true) + <-time.After(callbackWait) + if !widget1.Disabled() || !widget2.Disabled() { + t.Errorf("Widget1 or 2 was not disabled.") + return + } + + boundCheck.SetChecked(false) + <-time.After(callbackWait) + if widget1.Disabled() || widget2.Disabled() { + t.Errorf("Widget1 or 2 was not enabled.") + return + } +}