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/gdamore/tcell" 27 "github.com/gdamore/tcell/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.ColorBlack). 116 Foreground(tcell.ColorWhite) 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) 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