]> git.lizzy.rs Git - micro.git/blob - internal/display/tabwindow.go
706945042c11850d762a499e490629898d8f939f
[micro.git] / internal / display / tabwindow.go
1 package display
2
3 import (
4         runewidth "github.com/mattn/go-runewidth"
5         "github.com/zyedidia/micro/v2/internal/buffer"
6         "github.com/zyedidia/micro/v2/internal/config"
7         "github.com/zyedidia/micro/v2/internal/screen"
8         "github.com/zyedidia/micro/v2/internal/util"
9 )
10
11 type TabWindow struct {
12         Names   []string
13         active  int
14         Y       int
15         Width   int
16         hscroll int
17 }
18
19 func NewTabWindow(w int, y int) *TabWindow {
20         tw := new(TabWindow)
21         tw.Width = w
22         tw.Y = y
23         return tw
24 }
25
26 func (w *TabWindow) Resize(width, height int) {
27         w.Width = width
28 }
29
30 func (w *TabWindow) LocFromVisual(vloc buffer.Loc) int {
31         x := -w.hscroll
32
33         for i, n := range w.Names {
34                 x++
35                 s := util.CharacterCountInString(n)
36                 if vloc.Y == w.Y && vloc.X < x+s {
37                         return i
38                 }
39                 x += s
40                 x += 3
41                 if x >= w.Width {
42                         break
43                 }
44         }
45         return -1
46 }
47
48 func (w *TabWindow) Scroll(amt int) {
49         w.hscroll += amt
50         s := w.TotalSize()
51         w.hscroll = util.Clamp(w.hscroll, 0, s-w.Width)
52
53         if s-w.Width <= 0 {
54                 w.hscroll = 0
55         }
56 }
57
58 func (w *TabWindow) TotalSize() int {
59         sum := 2
60         for _, n := range w.Names {
61                 sum += runewidth.StringWidth(n) + 4
62         }
63         return sum - 4
64 }
65
66 func (w *TabWindow) Active() int {
67         return w.active
68 }
69
70 func (w *TabWindow) SetActive(a int) {
71         w.active = a
72         x := 2
73         s := w.TotalSize()
74
75         for i, n := range w.Names {
76                 c := util.CharacterCountInString(n)
77                 if i == a {
78                         if x+c >= w.hscroll+w.Width {
79                                 w.hscroll = util.Clamp(x+c+1-w.Width, 0, s-w.Width)
80                         } else if x < w.hscroll {
81                                 w.hscroll = util.Clamp(x-4, 0, s-w.Width)
82                         }
83                         break
84                 }
85                 x += c + 4
86         }
87
88         if s-w.Width <= 0 {
89                 w.hscroll = 0
90         }
91 }
92
93 func (w *TabWindow) Display() {
94         x := -w.hscroll
95         done := false
96
97         tabBarStyle := config.DefStyle.Reverse(true)
98         if style, ok := config.Colorscheme["tabbar"]; ok {
99                 tabBarStyle = style
100         }
101         tabBarActiveStyle := tabBarStyle
102         if style, ok := config.Colorscheme["tabbar.active"]; ok {
103                 tabBarActiveStyle = style
104         }
105
106         draw := func(r rune, n int, active bool) {
107                 style := tabBarStyle
108                 if active {
109                         style = tabBarActiveStyle
110                 }
111                 for i := 0; i < n; i++ {
112                         rw := runewidth.RuneWidth(r)
113                         for j := 0; j < rw; j++ {
114                                 c := r
115                                 if j > 0 {
116                                         c = ' '
117                                 }
118                                 if x == w.Width-1 && !done {
119                                         screen.SetContent(w.Width-1, w.Y, '>', nil, tabBarStyle)
120                                         x++
121                                         break
122                                 } else if x == 0 && w.hscroll > 0 {
123                                         screen.SetContent(0, w.Y, '<', nil, tabBarStyle)
124                                 } else if x >= 0 && x < w.Width {
125                                         screen.SetContent(x, w.Y, c, nil, style)
126                                 }
127                                 x++
128                         }
129                 }
130         }
131
132         for i, n := range w.Names {
133                 if i == w.active {
134                         draw('[', 1, true)
135                 } else {
136                         draw(' ', 1, false)
137                 }
138                 for _, c := range n {
139                         draw(c, 1, i == w.active)
140                 }
141                 if i == len(w.Names)-1 {
142                         done = true
143                 }
144                 if i == w.active {
145                         draw(']', 1, true)
146                         draw(' ', 2, true)
147                 } else {
148                         draw(' ', 3, false)
149                 }
150                 if x >= w.Width {
151                         break
152                 }
153         }
154
155         if x < w.Width {
156                 draw(' ', w.Width-x, false)
157         }
158 }