-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproperty.go
119 lines (92 loc) · 2.22 KB
/
property.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// 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.
package walk
type Property struct {
name string
get func() interface{}
set func(v interface{}) error
validator Validator
source interface{}
sourceChangedHandle int
changedEventPublisher *EventPublisher
customChangedEvent *Event
}
func NewProperty(name string, get func() interface{}, set func(v interface{}) error, customChangedEvent *Event) *Property {
p := &Property{name: name, get: get, set: set}
if customChangedEvent != nil {
p.customChangedEvent = customChangedEvent
} else {
p.changedEventPublisher = new(EventPublisher)
}
return p
}
func (p *Property) Name() string {
return p.name
}
func (p *Property) Get() interface{} {
return p.get()
}
func (p *Property) Set(v interface{}) error {
p.assertNotReadOnly()
if v == p.Get() {
return nil
}
if err := p.set(v); err != nil {
return err
}
if p.customChangedEvent == nil {
p.changedEventPublisher.Publish()
}
return nil
}
func (p *Property) Validator() Validator {
return p.validator
}
func (p *Property) SetValidator(v Validator) {
p.validator = v
}
func (p *Property) Source() interface{} {
return p.source
}
func (p *Property) SetSource(source interface{}) {
switch source := source.(type) {
case *Property:
if source != nil {
p.assertNotReadOnly()
}
for cur := source; cur != nil; cur, _ = cur.source.(*Property) {
if cur == p {
panic("source cycle")
}
}
if source != nil {
p.Set(source.Get())
p.sourceChangedHandle = source.Changed().Attach(func() {
p.Set(source.Get())
})
}
case string:
// nop
default:
panic("invalid source type")
}
if oldProp, ok := p.source.(*Property); ok {
oldProp.Changed().Detach(p.sourceChangedHandle)
}
p.source = source
}
func (p *Property) Changed() *Event {
if p.customChangedEvent != nil {
return p.customChangedEvent
}
return p.changedEventPublisher.Event()
}
func (p *Property) ReadOnly() bool {
return p.set == nil
}
func (p *Property) assertNotReadOnly() {
if p.ReadOnly() {
panic("property is read-only")
}
}