123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- // Copyright 2012 The Walk Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // +build windows
- package walk
- import (
- "errors"
- )
- var (
- ErrPropertyReadOnly = errors.New("read-only property")
- ErrPropertyNotValidatable = errors.New("property not validatable")
- )
- type Property interface {
- ReadOnly() bool
- Get() interface{}
- Set(value interface{}) error
- Changed() *Event
- Source() interface{}
- SetSource(source interface{}) error
- Validatable() bool
- Validator() Validator
- SetValidator(validator Validator) error
- }
- type property struct {
- get func() interface{}
- set func(v interface{}) error
- changed *Event
- source interface{}
- sourceChangedHandle int
- validator Validator
- }
- func NewProperty(get func() interface{}, set func(v interface{}) error, changed *Event) Property {
- return &property{get: get, set: set, changed: changed}
- }
- func (p *property) ReadOnly() bool {
- return p.set == nil
- }
- func (p *property) Get() interface{} {
- return p.get()
- }
- func (p *property) Set(value interface{}) error {
- if p.ReadOnly() {
- return ErrPropertyReadOnly
- }
- if oldValue := p.get(); value == oldValue {
- return nil
- }
- return p.set(value)
- }
- func (p *property) Changed() *Event {
- return p.changed
- }
- func (p *property) Source() interface{} {
- return p.source
- }
- func (p *property) SetSource(source interface{}) error {
- if p.ReadOnly() {
- return ErrPropertyReadOnly
- }
- if source != nil {
- switch source := source.(type) {
- case string:
- // nop
- case Property:
- if err := checkPropertySource(p, source); err != nil {
- return err
- }
- if source != nil {
- p.Set(source.Get())
- p.sourceChangedHandle = source.Changed().Attach(func() {
- p.Set(source.Get())
- })
- }
- default:
- return newError("invalid source type")
- }
- }
- if oldProp, ok := p.source.(Property); ok {
- oldProp.Changed().Detach(p.sourceChangedHandle)
- }
- p.source = source
- return nil
- }
- func (p *property) Validatable() bool {
- return true
- }
- func (p *property) Validator() Validator {
- return p.validator
- }
- func (p *property) SetValidator(validator Validator) error {
- if p.ReadOnly() {
- return ErrPropertyReadOnly
- }
- p.validator = validator
- return nil
- }
- type readOnlyProperty struct {
- get func() interface{}
- changed *Event
- }
- func NewReadOnlyProperty(get func() interface{}, changed *Event) Property {
- return &readOnlyProperty{get: get, changed: changed}
- }
- func (*readOnlyProperty) ReadOnly() bool {
- return true
- }
- func (rop *readOnlyProperty) Get() interface{} {
- return rop.get()
- }
- func (*readOnlyProperty) Set(value interface{}) error {
- return ErrPropertyReadOnly
- }
- func (rop *readOnlyProperty) Changed() *Event {
- return rop.changed
- }
- func (*readOnlyProperty) Source() interface{} {
- return nil
- }
- func (*readOnlyProperty) SetSource(source interface{}) error {
- return ErrPropertyReadOnly
- }
- func (*readOnlyProperty) Validatable() bool {
- return false
- }
- func (*readOnlyProperty) Validator() Validator {
- return nil
- }
- func (*readOnlyProperty) SetValidator(validator Validator) error {
- return ErrPropertyReadOnly
- }
- type boolProperty struct {
- get func() bool
- set func(v bool) error
- changed *Event
- source interface{}
- sourceChangedHandle int
- }
- func NewBoolProperty(get func() bool, set func(b bool) error, changed *Event) Property {
- return &boolProperty{get: get, set: set, changed: changed}
- }
- func (bp *boolProperty) ReadOnly() bool {
- return bp.set == nil
- }
- func (bp *boolProperty) Get() interface{} {
- return bp.get()
- }
- func (bp *boolProperty) Set(value interface{}) error {
- if bp.ReadOnly() {
- return ErrPropertyReadOnly
- }
- /* FIXME: Visible property doesn't like this.
- if oldValue := bp.get(); value == oldValue {
- return nil
- }*/
- return bp.set(value.(bool))
- }
- func (bp *boolProperty) Changed() *Event {
- return bp.changed
- }
- func (bp *boolProperty) Source() interface{} {
- return bp.source
- }
- func (bp *boolProperty) SetSource(source interface{}) error {
- if bp.ReadOnly() {
- return ErrPropertyReadOnly
- }
- if source != nil {
- switch source := source.(type) {
- case string:
- // nop
- case Condition:
- if err := checkPropertySource(bp, source); err != nil {
- return err
- }
- if err := bp.Set(source.Satisfied()); err != nil {
- return err
- }
- bp.sourceChangedHandle = source.Changed().Attach(func() {
- bp.Set(source.Satisfied())
- })
- default:
- return newError("invalid source type")
- }
- }
- if oldCond, ok := bp.source.(Condition); ok {
- oldCond.Changed().Detach(bp.sourceChangedHandle)
- }
- bp.source = source
- return nil
- }
- func (bp *boolProperty) Validatable() bool {
- return false
- }
- func (*boolProperty) Validator() Validator {
- return nil
- }
- func (*boolProperty) SetValidator(validator Validator) error {
- return ErrPropertyNotValidatable
- }
- func (bp *boolProperty) Satisfied() bool {
- return bp.get()
- }
- type readOnlyBoolProperty struct {
- get func() bool
- changed *Event
- }
- func NewReadOnlyBoolProperty(get func() bool, changed *Event) Property {
- return &readOnlyBoolProperty{get: get, changed: changed}
- }
- func (*readOnlyBoolProperty) ReadOnly() bool {
- return true
- }
- func (robp *readOnlyBoolProperty) Get() interface{} {
- return robp.get()
- }
- func (*readOnlyBoolProperty) Set(value interface{}) error {
- return ErrPropertyReadOnly
- }
- func (robp *readOnlyBoolProperty) Changed() *Event {
- return robp.changed
- }
- func (*readOnlyBoolProperty) Source() interface{} {
- return nil
- }
- func (*readOnlyBoolProperty) SetSource(source interface{}) error {
- return ErrPropertyReadOnly
- }
- func (*readOnlyBoolProperty) Validatable() bool {
- return false
- }
- func (*readOnlyBoolProperty) Validator() Validator {
- return nil
- }
- func (*readOnlyBoolProperty) SetValidator(validator Validator) error {
- return ErrPropertyNotValidatable
- }
- func (robp *readOnlyBoolProperty) Satisfied() bool {
- return robp.get()
- }
- func checkPropertySource(prop Property, source interface{}) error {
- switch source := source.(type) {
- case Property:
- for cur := source; cur != nil; cur, _ = cur.Source().(Property) {
- if cur == prop {
- return newError("source cycle")
- }
- }
- }
- return nil
- }
|