diff options
-rw-r--r-- | combobox.go | 71 | ||||
-rw-r--r-- | declarative/combobox.go | 1 | ||||
-rw-r--r-- | models.go | 38 | ||||
-rw-r--r-- | reflectmodels.go | 8 |
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) @@ -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 |