-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Displayed icon in widget alternates between 2 different icons. Simple demo app provided.
- Loading branch information
Showing
6 changed files
with
241 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
|
||
"fyne.io/fyne/v2/app" | ||
"fyne.io/fyne/v2/container" | ||
"fyne.io/fyne/v2/theme" | ||
"fyne.io/fyne/v2/widget" | ||
xwidget "fyne.io/x/fyne/widget" | ||
) | ||
|
||
func main() { | ||
a := app.New() | ||
w := a.NewWindow("Two State Demo") | ||
|
||
twoState0 := xwidget.NewTwoStateToolbarAction(nil, | ||
nil, func(on bool) { | ||
fmt.Println(on) | ||
}) | ||
sep := widget.NewToolbarSeparator() | ||
tb := widget.NewToolbar(twoState0, sep) | ||
|
||
toggleButton := widget.NewButton("Toggle State", func() { | ||
on := twoState0.GetOn() | ||
twoState0.SetOn(!on) | ||
}) | ||
offIconButton := widget.NewButton("Set OffIcon", func() { | ||
twoState0.SetOffIcon(theme.MediaPlayIcon()) | ||
}) | ||
onIconButton := widget.NewButton("Set OnIcon", func() { | ||
twoState0.SetOnIcon(theme.MediaStopIcon()) | ||
}) | ||
vc := container.NewVBox(toggleButton, offIconButton, onIconButton) | ||
c := container.NewBorder(tb, vc, nil, nil) | ||
w.SetContent(c) | ||
w.ShowAndRun() | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package widget | ||
|
||
import ( | ||
"fyne.io/fyne/v2" | ||
"fyne.io/fyne/v2/widget" | ||
) | ||
|
||
// TwoStateToolbarAction is a push button style of ToolbarItem that displays a different | ||
// icon depending on its state. | ||
// | ||
// state is a boolean indicating off and on. The actual meaning of the boolean depends on how it is used. For | ||
// example, in a media play app, false might indicate that the medium file is not being played, and true might | ||
// indicate that the file is being played. | ||
// Similarly, the two states could be used to indicate that a panel is being hidden or shown. | ||
type TwoStateToolbarAction struct { | ||
on bool | ||
offIcon fyne.Resource | ||
onIcon fyne.Resource | ||
OnActivated func(bool) `json:"-"` | ||
|
||
button widget.Button | ||
} | ||
|
||
// NewTwoStateToolbarAction returns a new push button style of Toolbar item that displays | ||
// a different icon for each of its two states | ||
func NewTwoStateToolbarAction(offStateIcon fyne.Resource, | ||
onStateIcon fyne.Resource, | ||
onTapped func(bool)) *TwoStateToolbarAction { | ||
t := &TwoStateToolbarAction{offIcon: offStateIcon, onIcon: onStateIcon, OnActivated: onTapped} | ||
t.button.SetIcon(t.offIcon) | ||
t.button.OnTapped = t.activated | ||
return t | ||
} | ||
|
||
// GetOn returns the current state of the toolbaraction | ||
func (t *TwoStateToolbarAction) GetOn() bool { | ||
return t.on | ||
} | ||
|
||
// SetOn sets the state of the toolbaraction | ||
func (t *TwoStateToolbarAction) SetOn(on bool) { | ||
t.on = on | ||
if t.OnActivated != nil { | ||
t.OnActivated(t.on) | ||
} | ||
t.setButtonIcon() | ||
t.button.Refresh() | ||
} | ||
|
||
// SetOffIcon sets the icon that is displayed when the state is false | ||
func (t *TwoStateToolbarAction) SetOffIcon(icon fyne.Resource) { | ||
t.offIcon = icon | ||
t.setButtonIcon() | ||
t.button.Refresh() | ||
} | ||
|
||
// SetOnIcon sets the icon that is displayed when the state is true | ||
func (t *TwoStateToolbarAction) SetOnIcon(icon fyne.Resource) { | ||
t.onIcon = icon | ||
t.setButtonIcon() | ||
t.button.Refresh() | ||
} | ||
|
||
// ToolbarObject gets a button to render this ToolbarAction | ||
func (t *TwoStateToolbarAction) ToolbarObject() fyne.CanvasObject { | ||
t.button.Importance = widget.LowImportance | ||
|
||
// synchronize properties | ||
t.setButtonIcon() | ||
t.button.OnTapped = t.activated | ||
return &t.button | ||
} | ||
|
||
func (t *TwoStateToolbarAction) activated() { | ||
if !t.on { | ||
t.on = true | ||
} else { | ||
t.on = false | ||
} | ||
t.setButtonIcon() | ||
if t.OnActivated != nil { | ||
t.OnActivated(t.on) | ||
} | ||
t.button.Refresh() | ||
} | ||
|
||
func (t *TwoStateToolbarAction) setButtonIcon() { | ||
if !t.on { | ||
t.button.Icon = t.offIcon | ||
} else { | ||
t.button.Icon = t.onIcon | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package widget | ||
|
||
import ( | ||
"testing" | ||
|
||
"fyne.io/fyne/v2/test" | ||
"fyne.io/fyne/v2/theme" | ||
"fyne.io/fyne/v2/widget" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestNewTwoStateToolbarAction(t *testing.T) { | ||
action := NewTwoStateToolbarAction(theme.MediaPlayIcon(), | ||
theme.MediaPauseIcon(), | ||
func(_ bool) {}) | ||
assert.Equal(t, theme.MediaPlayIcon().Name(), action.offIcon.Name()) | ||
assert.Equal(t, theme.MediaPauseIcon().Name(), action.onIcon.Name()) | ||
assert.Equal(t, action.offIcon.Name(), action.button.Icon.Name()) | ||
} | ||
|
||
func TestTwoStateToolbarAction_Activated(t *testing.T) { | ||
action := NewTwoStateToolbarAction(theme.MediaPlayIcon(), | ||
theme.MediaPauseIcon(), | ||
func(_ bool) {}) | ||
require.Equal(t, action.offIcon.Name(), action.button.Icon.Name()) | ||
action.button.Tapped(nil) | ||
assert.Equal(t, action.onIcon.Name(), action.button.Icon.Name()) | ||
} | ||
|
||
func TestTwoStateToolbarAction_Tapped(t *testing.T) { | ||
test.NewApp() | ||
action := NewTwoStateToolbarAction(theme.MediaPlayIcon(), | ||
theme.MediaPauseIcon(), | ||
func(_ bool) {}) | ||
tb := widget.NewToolbar(action) | ||
w := test.NewWindow(tb) | ||
defer w.Close() | ||
test.AssertRendersToImage(t, "twostatetoolbaraction/offstate.png", w.Canvas()) | ||
action.button.Tapped(nil) | ||
test.AssertRendersToImage(t, "twostatetoolbaraction/onstate.png", w.Canvas()) | ||
} | ||
|
||
func TestTwoStateToolbarAction_GetSetState(t *testing.T) { | ||
var ts bool | ||
playState := false | ||
test.NewApp() | ||
action := NewTwoStateToolbarAction(theme.MediaPlayIcon(), | ||
theme.MediaPauseIcon(), | ||
func(on bool) { | ||
ts = on | ||
}) | ||
tb := widget.NewToolbar(action) | ||
w := test.NewWindow(tb) | ||
defer w.Close() | ||
assert.Equal(t, playState, action.GetOn()) | ||
action.SetOn(true) | ||
assert.Equal(t, true, action.GetOn()) | ||
assert.Equal(t, true, ts) | ||
test.AssertRendersToImage(t, "twostatetoolbaraction/onstate.png", w.Canvas()) | ||
} | ||
|
||
func TestTwoStateToolbarAction_SetOffStateIcon(t *testing.T) { | ||
test.NewApp() | ||
action := NewTwoStateToolbarAction(nil, | ||
theme.MediaPauseIcon(), | ||
func(staone bool) {}) | ||
tb := widget.NewToolbar(action) | ||
w := test.NewWindow(tb) | ||
defer w.Close() | ||
|
||
action.SetOffIcon(theme.MediaPlayIcon()) | ||
assert.Equal(t, theme.MediaPlayIcon().Name(), action.offIcon.Name()) | ||
} | ||
|
||
func TestTwoStateToolbarAction_SetOnStateIcon(t *testing.T) { | ||
test.NewApp() | ||
action := NewTwoStateToolbarAction(theme.MediaPlayIcon(), | ||
nil, | ||
func(on bool) {}) | ||
tb := widget.NewToolbar(action) | ||
w := test.NewWindow(tb) | ||
defer w.Close() | ||
|
||
action.SetOnIcon(theme.MediaPauseIcon()) | ||
assert.Equal(t, theme.MediaPauseIcon().Name(), action.onIcon.Name()) | ||
} |