summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorAlexander Neumann <alexander.neumann@picos-software.com>2019-02-25 17:13:33 +0100
committerAlexander Neumann <alexander.neumann@picos-software.com>2019-02-25 17:13:33 +0100
commit3b7a0abe29730d5cc5fb200162a3601d5d87865a (patch)
treed6a4e72c7e7d36d3621c519936a1e3f67f475ab5
parentReplace some occurrences of Widget with *WidgetBase (diff)
downloadwireguard-windows-3b7a0abe29730d5cc5fb200162a3601d5d87865a.tar.xz
wireguard-windows-3b7a0abe29730d5cc5fb200162a3601d5d87865a.zip
Add ItemsInserted + ItemsRemoved to ListModel and support them in ComboBox + ListBox
-rw-r--r--combobox.go71
-rw-r--r--declarative/combobox.go1
-rw-r--r--models.go38
-rw-r--r--reflectmodels.go8
4 files changed, 114 insertions, 4 deletions
diff --git a/combobox.go b/combobox.go
index 598af788..0548d30b 100644
--- a/combobox.go
+++ b/combobox.go
@@ -9,12 +9,12 @@ package walk
import (
"fmt"
"math/big"
+ "reflect"
+ "strconv"
"syscall"
"time"
"unsafe"
-)
-import (
"github.com/lxn/win"
)
@@ -29,6 +29,8 @@ type ComboBox struct {
precision int
itemsResetHandlerHandle int
itemChangedHandlerHandle int
+ itemsInsertedHandlerHandle int
+ itemsRemovedHandlerHandle int
maxItemTextWidth int
prevCurIndex int
selChangeIndex int
@@ -38,6 +40,7 @@ type ComboBox struct {
editingFinishedPublisher EventPublisher
editOrigWndProcPtr uintptr
editing bool
+ persistent bool
}
var comboBoxEditWndProcPtr = syscall.NewCallback(comboBoxEditWndProc)
@@ -155,6 +158,18 @@ func newComboBoxWithStyle(parent Container, style uint32) (*ComboBox, error) {
},
event))
+ cb.MustRegisterProperty("CurrentItem", NewReadOnlyProperty(
+ func() interface{} {
+ if rlm, ok := cb.providedModel.(ReflectListModel); ok {
+ if i := cb.CurrentIndex(); i > -1 {
+ return reflect.ValueOf(rlm.Items()).Index(i).Interface()
+ }
+ }
+
+ return nil
+ },
+ cb.CurrentIndexChanged()))
+
cb.MustRegisterProperty("HasCurrentItem", NewReadOnlyBoolProperty(
func() bool {
return cb.CurrentIndex() != -1
@@ -281,6 +296,14 @@ func (cb *ComboBox) insertItemAt(index int) error {
return nil
}
+func (cb *ComboBox) removeItem(index int) error {
+ if win.CB_ERR == cb.SendMessage(win.CB_DELETESTRING, uintptr(index), 0) {
+ return newError("SendMessage(CB_DELETESTRING")
+ }
+
+ return nil
+}
+
func (cb *ComboBox) resetItems() error {
cb.SetSuspended(true)
defer cb.SetSuspended(false)
@@ -328,11 +351,25 @@ func (cb *ComboBox) attachModel() {
cb.SetCurrentIndex(cb.prevCurIndex)
}
cb.itemChangedHandlerHandle = cb.model.ItemChanged().Attach(itemChangedHandler)
+
+ cb.itemsInsertedHandlerHandle = cb.model.ItemsInserted().Attach(func(from, to int) {
+ for i := from; i <= to; i++ {
+ cb.insertItemAt(i)
+ }
+ })
+
+ cb.itemsRemovedHandlerHandle = cb.model.ItemsRemoved().Attach(func(from, to int) {
+ for i := to; i >= from; i-- {
+ cb.removeItem(i)
+ }
+ })
}
func (cb *ComboBox) detachModel() {
cb.model.ItemsReset().Detach(cb.itemsResetHandlerHandle)
cb.model.ItemChanged().Detach(cb.itemChangedHandlerHandle)
+ cb.model.ItemsInserted().Detach(cb.itemsInsertedHandlerHandle)
+ cb.model.ItemsRemoved().Detach(cb.itemsRemovedHandlerHandle)
}
// Model returns the model of the ComboBox.
@@ -580,6 +617,36 @@ func (cb *ComboBox) EditingFinished() *Event {
return cb.editingFinishedPublisher.Event()
}
+func (cb *ComboBox) Persistent() bool {
+ return cb.persistent
+}
+
+func (cb *ComboBox) SetPersistent(value bool) {
+ cb.persistent = value
+}
+
+func (cb *ComboBox) SaveState() error {
+ cb.WriteState(strconv.Itoa(cb.CurrentIndex()))
+
+ return nil
+}
+
+func (cb *ComboBox) RestoreState() error {
+ state, err := cb.ReadState()
+ if err != nil {
+ return err
+ }
+ if state == "" {
+ return nil
+ }
+
+ if i, err := strconv.Atoi(state); err == nil {
+ cb.SetCurrentIndex(i)
+ }
+
+ return nil
+}
+
func (cb *ComboBox) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr {
switch msg {
case win.WM_COMMAND:
diff --git a/declarative/combobox.go b/declarative/combobox.go
index 53782aa0..8dea7635 100644
--- a/declarative/combobox.go
+++ b/declarative/combobox.go
@@ -87,6 +87,7 @@ func (cb ComboBox) Create(builder *Builder) error {
}
return builder.InitWidget(cb, w, func() error {
+ w.SetPersistent(cb.Persistent)
w.SetFormat(cb.Format)
w.SetPrecision(cb.Precision)
w.SetMaxLength(cb.MaxLength)
diff --git a/models.go b/models.go
index abfae310..704f5bad 100644
--- a/models.go
+++ b/models.go
@@ -30,13 +30,23 @@ type ListModel interface {
// ItemChanged returns the event that the model should publish when an item
// was changed.
ItemChanged() *IntEvent
+
+ // ItemsInserted returns the event that the model should publish when a
+ // contiguous range of items was inserted.
+ ItemsInserted() *IntRangeEvent
+
+ // ItemsRemoved returns the event that the model should publish when a
+ // contiguous range of items was removed.
+ ItemsRemoved() *IntRangeEvent
}
// ListModelBase implements the ItemsReset and ItemChanged methods of the
// ListModel interface.
type ListModelBase struct {
- itemsResetPublisher EventPublisher
- itemChangedPublisher IntEventPublisher
+ itemsResetPublisher EventPublisher
+ itemChangedPublisher IntEventPublisher
+ itemsInsertedPublisher IntRangeEventPublisher
+ itemsRemovedPublisher IntRangeEventPublisher
}
func (lmb *ListModelBase) ItemsReset() *Event {
@@ -47,6 +57,14 @@ func (lmb *ListModelBase) ItemChanged() *IntEvent {
return lmb.itemChangedPublisher.Event()
}
+func (lmb *ListModelBase) ItemsInserted() *IntRangeEvent {
+ return lmb.itemsInsertedPublisher.Event()
+}
+
+func (lmb *ListModelBase) ItemsRemoved() *IntRangeEvent {
+ return lmb.itemsRemovedPublisher.Event()
+}
+
func (lmb *ListModelBase) PublishItemsReset() {
lmb.itemsResetPublisher.Publish()
}
@@ -55,6 +73,14 @@ func (lmb *ListModelBase) PublishItemChanged(index int) {
lmb.itemChangedPublisher.Publish(index)
}
+func (lmb *ListModelBase) PublishItemsInserted(from, to int) {
+ lmb.itemsInsertedPublisher.Publish(from, to)
+}
+
+func (lmb *ListModelBase) PublishItemsRemoved(from, to int) {
+ lmb.itemsRemovedPublisher.Publish(from, to)
+}
+
// ReflectListModel provides an alternative to the ListModel interface. It
// uses reflection to obtain data.
type ReflectListModel interface {
@@ -69,6 +95,14 @@ type ReflectListModel interface {
// was changed.
ItemChanged() *IntEvent
+ // ItemsInserted returns the event that the model should publish when a
+ // contiguous range of items was inserted.
+ ItemsInserted() *IntRangeEvent
+
+ // ItemsRemoved returns the event that the model should publish when a
+ // contiguous range of items was removed.
+ ItemsRemoved() *IntRangeEvent
+
setValueFunc(value func(index int) interface{})
}
diff --git a/reflectmodels.go b/reflectmodels.go
index 48bc95db..c3132a24 100644
--- a/reflectmodels.go
+++ b/reflectmodels.go
@@ -57,6 +57,14 @@ func newReflectListModel(dataSource interface{}) (ListModel, error) {
m.PublishItemsReset()
})
+
+ rlm.ItemsInserted().Attach(func(from, to int) {
+ m.PublishItemsInserted(from, to)
+ })
+
+ rlm.ItemsRemoved().Attach(func(from, to int) {
+ m.PublishItemsRemoved(from, to)
+ })
}
return m, nil