Skip to content

Commit

Permalink
Add two-way binding for checked menu item to bool property via Action…
Browse files Browse the repository at this point in the history
….Checked
  • Loading branch information
lxn committed Feb 25, 2019
1 parent 7cd9fcf commit 2b4f36e
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 6 deletions.
42 changes: 42 additions & 0 deletions action.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type Action struct {
text string
toolTip string
image *Bitmap
checkedCondition Condition
checkedConditionChangedHandle int
enabledCondition Condition
enabledConditionChangedHandle int
visibleCondition Condition
Expand Down Expand Up @@ -114,6 +116,16 @@ func (a *Action) Checked() bool {
}

func (a *Action) SetChecked(value bool) (err error) {
if a.checkedCondition != nil {
if bp, ok := a.checkedCondition.(*boolProperty); ok {
if err := bp.Set(value); err != nil {
return err
}
} else {
return newError("CheckedCondition != nil")
}
}

if value != a.checked {
old := a.checked

Expand All @@ -128,6 +140,32 @@ func (a *Action) SetChecked(value bool) (err error) {
return
}

func (a *Action) CheckedCondition() Condition {
return a.checkedCondition
}

func (a *Action) SetCheckedCondition(c Condition) {
if a.checkedCondition != nil {
a.checkedCondition.Changed().Detach(a.checkedConditionChangedHandle)
}

a.checkedCondition = c

if c != nil {
a.checked = c.Satisfied()

a.checkedConditionChangedHandle = c.Changed().Attach(func() {
if a.checked != c.Satisfied() {
a.checked = !a.checked

a.raiseChanged()
}
})
}

a.raiseChanged()
}

func (a *Action) Enabled() bool {
return a.enabled
}
Expand Down Expand Up @@ -341,6 +379,10 @@ func (a *Action) Triggered() *Event {
}

func (a *Action) raiseTriggered() {
if a.Checkable() {
a.SetChecked(!a.Checked())
}

a.triggeredPublisher.Publish()
}

Expand Down
9 changes: 7 additions & 2 deletions declarative/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type Action struct {
AssignTo **walk.Action
Text string
Image interface{}
Checked Property
Enabled Property
Visible Property
Shortcut Shortcut
Expand All @@ -45,17 +46,21 @@ func (a Action) createAction(builder *Builder, menu *walk.Menu) (*walk.Action, e
if err := setActionImage(action, a.Image); err != nil {
return nil, err
}
if err := action.SetCheckable(a.Checkable); err != nil {

if err := setActionBoolOrCondition(action.SetChecked, action.SetCheckedCondition, a.Checked, "Action.Checked", builder); err != nil {
return nil, err
}

if err := setActionBoolOrCondition(action.SetEnabled, action.SetEnabledCondition, a.Enabled, "Action.Enabled", builder); err != nil {
return nil, err
}
if err := setActionBoolOrCondition(action.SetVisible, action.SetVisibleCondition, a.Visible, "Action.Visible", builder); err != nil {
return nil, err
}

if err := action.SetCheckable(a.Checkable || action.CheckedCondition() != nil); err != nil {
return nil, err
}

s := a.Shortcut
if err := action.SetShortcut(walk.Shortcut{s.Modifiers, s.Key}); err != nil {
return nil, err
Expand Down
13 changes: 13 additions & 0 deletions examples/actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,19 @@ func main() {
},
},
},
Menu{
Text: "&View",
Items: []MenuItem{
Action{
Text: "Open / Special Enabled",
Checked: Bind("enabledCB.Visible"),
},
Action{
Text: "Open Hidden",
Checked: Bind("openHiddenCB.Visible"),
},
},
},
Menu{
Text: "&Help",
Items: []MenuItem{
Expand Down
33 changes: 29 additions & 4 deletions menu.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import (
"fmt"
"syscall"
"unsafe"
)

import (
"github.com/lxn/win"
)

Expand Down Expand Up @@ -83,9 +81,9 @@ func (m *Menu) initMenuItemInfoFromAction(mii *win.MENUITEMINFO, action *Action)
mii.HbmpItem = action.image.handle()
}
if action.IsSeparator() {
mii.FType = win.MFT_SEPARATOR
mii.FType |= win.MFT_SEPARATOR
} else {
mii.FType = win.MFT_STRING
mii.FType |= win.MFT_STRING
var text string
if s := action.shortcut; s.Key != 0 {
text = fmt.Sprintf("%s\t%s", action.text, s.String())
Expand All @@ -109,6 +107,9 @@ func (m *Menu) initMenuItemInfoFromAction(mii *win.MENUITEMINFO, action *Action)
if action.Checked() {
mii.FState |= win.MFS_CHECKED
}
if action.Exclusive() {
mii.FType |= win.MFT_RADIOCHECK
}

menu := action.menu
if menu != nil {
Expand All @@ -130,6 +131,30 @@ func (m *Menu) onActionChanged(action *Action) error {
return newError("SetMenuItemInfo failed")
}

if action.Exclusive() && action.Checked() {
var first, last int

index := m.actions.Index(action)

for i := index; i >= 0; i-- {
first = i
if !m.actions.At(i).Exclusive() {
break
}
}

for i := index; i < m.actions.Len(); i++ {
last = i
if !m.actions.At(i).Exclusive() {
break
}
}

if !win.CheckMenuRadioItem(m.hMenu, uint32(first), uint32(last), uint32(index), win.MF_BYPOSITION) {
return newError("CheckMenuRadioItem failed")
}
}

return nil
}

Expand Down

0 comments on commit 2b4f36e

Please sign in to comment.