-
Notifications
You must be signed in to change notification settings - Fork 1
/
textarea_windows.go
115 lines (98 loc) · 2.9 KB
/
textarea_windows.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
package goey
import (
"syscall"
"unsafe"
"bitbucket.org/rj/goey/base"
"github.com/lxn/win"
)
func (w *TextArea) mount(parent base.Control) (base.Element, error) {
// Create the control, and set properties
hwnd, _, err := createControlWindow(win.WS_EX_CLIENTEDGE, &edit.className[0], w.Value, w.style(), parent.HWnd)
if err != nil {
return nil, err
}
if w.Disabled {
win.EnableWindow(hwnd, false)
}
// Create placeholder, if required.
if w.Placeholder != "" {
textPlaceholder, err := syscall.UTF16PtrFromString(w.Placeholder)
if err != nil {
win.DestroyWindow(hwnd)
return nil, err
}
win.SendMessage(hwnd, win.EM_SETCUEBANNER, 0, uintptr(unsafe.Pointer(textPlaceholder)))
}
// Create the return value.
retval := &textareaElement{textinputElementBase{
Control: Control{hwnd},
onChange: w.OnChange,
onFocus: w.OnFocus,
onBlur: w.OnBlur,
},
minlinesDefault(w.MinLines),
}
// Link the control back to Go for event handling
subclassWindowProcedure(hwnd, &edit.oldWindowProc, textinputWindowProc)
win.SetWindowLongPtr(hwnd, win.GWLP_USERDATA, uintptr(unsafe.Pointer(retval)))
return retval, nil
}
func (w *TextArea) style() uint32 {
style := uint32(win.WS_CHILD | win.WS_VISIBLE | win.WS_TABSTOP | win.ES_LEFT | win.ES_MULTILINE | win.ES_WANTRETURN | win.ES_AUTOVSCROLL)
if w.ReadOnly {
style = style | win.ES_READONLY
}
return style
}
type textareaElement struct {
textinputElementBase
minLines int
}
func (w *textareaElement) Layout(bc base.Constraints) base.Size {
width := w.MinIntrinsicWidth(0)
height := w.MinIntrinsicHeight(0)
return bc.Constrain(base.Size{width, height})
}
func (w *textareaElement) MinIntrinsicHeight(base.Length) base.Length {
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
const lineHeight = 16 * DIP
return 23*DIP + lineHeight.Scale(w.minLines-1, 1)
}
func (w *textareaElement) Props() base.Widget {
var buffer [80]uint16
win.SendMessage(w.hWnd, win.EM_GETCUEBANNER, uintptr(unsafe.Pointer(&buffer[0])), 80)
ndx := 0
for i, v := range buffer {
if v == 0 {
ndx = i
break
}
}
placeholder := syscall.UTF16ToString(buffer[:ndx])
return &TextArea{
Value: w.Control.Text(),
Placeholder: placeholder,
Disabled: !win.IsWindowEnabled(w.hWnd),
ReadOnly: (win.GetWindowLong(w.hWnd, win.GWL_STYLE) & win.ES_READONLY) != 0,
MinLines: w.minLines,
OnChange: w.onChange,
OnFocus: w.onFocus,
OnBlur: w.onBlur,
}
}
func (w *textareaElement) updateProps(data *TextArea) error {
if data.Value != w.Text() {
w.SetText(data.Value)
}
err := updatePlaceholder(w.hWnd, data.Placeholder)
if err != nil {
return err
}
w.SetDisabled(data.Disabled)
win.SendMessage(w.hWnd, win.EM_SETREADONLY, uintptr(win.BoolToBOOL(data.ReadOnly)), 0)
w.minLines = minlinesDefault(data.MinLines)
w.onChange = data.OnChange
w.onFocus = data.OnFocus
w.onBlur = data.OnBlur
return nil
}