1// +build ignore
2
3// Copyright 2015 The TCell Authors
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use file except in compliance with the License.
7// You may obtain a copy of the license at
8//
9//    http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17// mouse displays a text box and tests mouse interaction.  As you click
18// and drag, boxes are displayed on screen.  Other events are reported in
19// the box.  Press ESC twice to exit the program.
20package main
21
22import (
23	"fmt"
24	"os"
25
26	"github.com/zyedidia/tcell/v2"
27	"github.com/zyedidia/tcell/v2/encoding"
28
29	"github.com/mattn/go-runewidth"
30)
31
32var defStyle tcell.Style
33
34func emitStr(s tcell.Screen, x, y int, style tcell.Style, str string) {
35	for _, c := range str {
36		var comb []rune
37		w := runewidth.RuneWidth(c)
38		if w == 0 {
39			comb = []rune{c}
40			c = ' '
41			w = 1
42		}
43		s.SetContent(x, y, c, comb, style)
44		x += w
45	}
46}
47
48func drawBox(s tcell.Screen, x1, y1, x2, y2 int, style tcell.Style, r rune) {
49	if y2 < y1 {
50		y1, y2 = y2, y1
51	}
52	if x2 < x1 {
53		x1, x2 = x2, x1
54	}
55
56	for col := x1; col <= x2; col++ {
57		s.SetContent(col, y1, tcell.RuneHLine, nil, style)
58		s.SetContent(col, y2, tcell.RuneHLine, nil, style)
59	}
60	for row := y1 + 1; row < y2; row++ {
61		s.SetContent(x1, row, tcell.RuneVLine, nil, style)
62		s.SetContent(x2, row, tcell.RuneVLine, nil, style)
63	}
64	if y1 != y2 && x1 != x2 {
65		// Only add corners if we need to
66		s.SetContent(x1, y1, tcell.RuneULCorner, nil, style)
67		s.SetContent(x2, y1, tcell.RuneURCorner, nil, style)
68		s.SetContent(x1, y2, tcell.RuneLLCorner, nil, style)
69		s.SetContent(x2, y2, tcell.RuneLRCorner, nil, style)
70	}
71	for row := y1 + 1; row < y2; row++ {
72		for col := x1 + 1; col < x2; col++ {
73			s.SetContent(col, row, r, nil, style)
74		}
75	}
76}
77
78func drawSelect(s tcell.Screen, x1, y1, x2, y2 int, sel bool) {
79
80	if y2 < y1 {
81		y1, y2 = y2, y1
82	}
83	if x2 < x1 {
84		x1, x2 = x2, x1
85	}
86	for row := y1; row <= y2; row++ {
87		for col := x1; col <= x2; col++ {
88			mainc, combc, style, width := s.GetContent(col, row)
89			if style == tcell.StyleDefault {
90				style = defStyle
91			}
92			style = style.Reverse(sel)
93			s.SetContent(col, row, mainc, combc, style)
94			col += width - 1
95		}
96	}
97}
98
99// This program just shows simple mouse and keyboard events.  Press ESC twice to
100// exit.
101func main() {
102
103	encoding.Register()
104
105	s, e := tcell.NewScreen()
106	if e != nil {
107		fmt.Fprintf(os.Stderr, "%v\n", e)
108		os.Exit(1)
109	}
110	if e := s.Init(); e != nil {
111		fmt.Fprintf(os.Stderr, "%v\n", e)
112		os.Exit(1)
113	}
114	defStyle = tcell.StyleDefault.
115		Background(tcell.ColorReset).
116		Foreground(tcell.ColorReset)
117	s.SetStyle(defStyle)
118	s.EnableMouse()
119	s.Clear()
120
121	posfmt := "Mouse: %d, %d  "
122	btnfmt := "Buttons: %s"
123	keyfmt := "Keys: %s"
124	white := tcell.StyleDefault.
125		Foreground(tcell.ColorWhite).Background(tcell.ColorRed)
126
127	mx, my := -1, -1
128	ox, oy := -1, -1
129	bx, by := -1, -1
130	w, h := s.Size()
131	lchar := '*'
132	bstr := ""
133	lks := ""
134	ecnt := 0
135
136	for {
137		drawBox(s, 1, 1, 42, 6, white, ' ')
138		emitStr(s, 2, 2, white, "Press ESC twice to exit, C to clear.")
139		emitStr(s, 2, 3, white, fmt.Sprintf(posfmt, mx, my))
140		emitStr(s, 2, 4, white, fmt.Sprintf(btnfmt, bstr))
141		emitStr(s, 2, 5, white, fmt.Sprintf(keyfmt, lks))
142
143		s.Show()
144		bstr = ""
145		ev := s.PollEvent()
146		st := tcell.StyleDefault.Background(tcell.ColorRed)
147		up := tcell.StyleDefault.
148			Background(tcell.ColorBlue).
149			Foreground(tcell.ColorBlack)
150		w, h = s.Size()
151
152		// always clear any old selection box
153		if ox >= 0 && oy >= 0 && bx >= 0 {
154			drawSelect(s, ox, oy, bx, by, false)
155		}
156
157		switch ev := ev.(type) {
158		case *tcell.EventResize:
159			s.Sync()
160			s.SetContent(w-1, h-1, 'R', nil, st)
161		case *tcell.EventKey:
162			s.SetContent(w-2, h-2, ev.Rune(), nil, st)
163			s.SetContent(w-1, h-1, 'K', nil, st)
164			if ev.Key() == tcell.KeyEscape {
165				ecnt++
166				if ecnt > 1 {
167					s.Fini()
168					os.Exit(0)
169				}
170			} else if ev.Key() == tcell.KeyCtrlL {
171				s.Sync()
172			} else {
173				ecnt = 0
174				if ev.Rune() == 'C' || ev.Rune() == 'c' {
175					s.Clear()
176				}
177			}
178			lks = ev.Name()
179		case *tcell.EventMouse:
180			x, y := ev.Position()
181			button := ev.Buttons()
182			for i := uint(0); i < 8; i++ {
183				if int(button)&(1<<i) != 0 {
184					bstr += fmt.Sprintf(" Button%d", i+1)
185				}
186			}
187			if button&tcell.WheelUp != 0 {
188				bstr += " WheelUp"
189			}
190			if button&tcell.WheelDown != 0 {
191				bstr += " WheelDown"
192			}
193			if button&tcell.WheelLeft != 0 {
194				bstr += " WheelLeft"
195			}
196			if button&tcell.WheelRight != 0 {
197				bstr += " WheelRight"
198			}
199			// Only buttons, not wheel events
200			button &= tcell.ButtonMask(0xff)
201			ch := '*'
202
203			if button != tcell.ButtonNone && ox < 0 {
204				ox, oy = x, y
205			}
206			switch ev.Buttons() {
207			case tcell.ButtonNone:
208				if ox >= 0 {
209					bg := tcell.Color((lchar-'0')*2) | tcell.ColorValid
210					drawBox(s, ox, oy, x, y,
211						up.Background(bg),
212						lchar)
213					ox, oy = -1, -1
214					bx, by = -1, -1
215				}
216			case tcell.Button1:
217				ch = '1'
218			case tcell.Button2:
219				ch = '2'
220			case tcell.Button3:
221				ch = '3'
222			case tcell.Button4:
223				ch = '4'
224			case tcell.Button5:
225				ch = '5'
226			case tcell.Button6:
227				ch = '6'
228			case tcell.Button7:
229				ch = '7'
230			case tcell.Button8:
231				ch = '8'
232			default:
233				ch = '*'
234
235			}
236			if button != tcell.ButtonNone {
237				bx, by = x, y
238			}
239			lchar = ch
240			s.SetContent(w-1, h-1, 'M', nil, st)
241			mx, my = x, y
242		default:
243			s.SetContent(w-1, h-1, 'X', nil, st)
244		}
245
246		if ox >= 0 && bx >= 0 {
247			drawSelect(s, ox, oy, bx, by, true)
248		}
249	}
250}
251