7 "github.com/zyedidia/tcell"
13 // This contains all the views in this tab
14 // There is generally only one view per tab, but you can have
15 // multiple views with splits
17 // This is the current view for this tab
23 // NewTabFromView creates a new tab and puts the given view in the tab
24 func NewTabFromView(v *View) *Tab {
26 t.views = append(t.views, v)
29 t.tree = new(SplitTree)
30 t.tree.kind = VerticalSplit
31 t.tree.children = []Node{NewLeafNode(t.views[0], t.tree)}
37 if globalSettings["infobar"].(bool) {
46 // SetNum sets all this tab's views to have the correct tab number
47 func (t *Tab) SetNum(num int) {
49 for _, v := range t.views {
54 func (t *Tab) Cleanup() {
58 func (t *Tab) Resize() {
63 if globalSettings["infobar"].(bool) {
69 for i, v := range t.views {
74 // CurView returns the current view
75 func CurView() *View {
76 curTab := tabs[curTab]
77 return curTab.views[curTab.CurView]
80 // TabbarString returns the string that should be displayed in the tabbar
81 // It also returns a map containing which indicies correspond to which tab number
82 // This is useful when we know that the mouse click has occurred at an x location
83 // but need to know which tab that corresponds to to accurately change the tab
84 func TabbarString() (string, map[int]int) {
86 indicies := make(map[int]int)
87 for i, t := range tabs {
93 //To address issue 556.2
94 _, name := filepath.Split(t.views[t.CurView].Buf.GetName())
101 indicies[len(str)-1] = i + 1
107 // TabbarHandleMouseEvent checks the given mouse event if it is clicking on the tabbar
108 // If it is it changes the current tab accordingly
109 // This function returns true if the tab is changed
110 func TabbarHandleMouseEvent(event tcell.Event) bool {
111 // There is no tabbar displayed if there are less than 2 tabs
116 switch e := event.(type) {
117 case *tcell.EventMouse:
118 button := e.Buttons()
119 // Must be a left click
120 if button == tcell.Button1 {
125 str, indicies := TabbarString()
126 if x+tabBarOffset >= len(str) {
131 for k := range indicies {
132 keys = append(keys, k)
135 for _, k := range keys {
136 if x+tabBarOffset <= k {
137 tabnum = indicies[k] - 1
149 // DisplayTabs displays the tabbar at the top of the editor if there are multiple tabs
155 str, indicies := TabbarString()
157 tabBarStyle := defStyle.Reverse(true)
158 if style, ok := colorscheme["tabbar"]; ok {
162 // Maybe there is a unicode filename?
163 fileRunes := []rune(str)
164 w, _ := screen.Size()
165 tooWide := (w < len(fileRunes))
167 // if the entire tab-bar is longer than the screen is wide,
168 // then it should be truncated appropriately to keep the
169 // active tab visible on the UI.
171 // first we have to work out where the selected tab is
172 // out of the total length of the tab bar. this is done
173 // by extracting the hit-areas from the indicies map
174 // that was constructed by `TabbarString()`
176 for offset := range indicies {
177 keys = append(keys, offset)
179 // sort them to be in ascending order so that values will
180 // correctly reflect the displayed ordering of the tabs
182 // record the offset of each tab and the previous tab so
183 // we can find the position of the tab's hit-box.
184 previousTabOffset := 0
185 currentTabOffset := 0
186 for _, k := range keys {
187 tabIndex := indicies[k] - 1
188 if tabIndex == curTab {
192 // this is +2 because there are two padding spaces that aren't accounted
193 // for in the display. please note that this is for cosmetic purposes only.
194 previousTabOffset = k + 2
196 // get the width of the hitbox of the active tab, from there calculate the offsets
197 // to the left and right of it to approximately center it on the tab bar display.
198 centeringOffset := (w - (currentTabOffset - previousTabOffset))
199 leftBuffer := previousTabOffset - (centeringOffset / 2)
200 rightBuffer := currentTabOffset + (centeringOffset / 2)
202 // check to make sure we haven't overshot the bounds of the string,
203 // if we have, then take that remainder and put it on the left side
204 overshotRight := rightBuffer - len(fileRunes)
205 if overshotRight > 0 {
206 leftBuffer = leftBuffer + overshotRight
209 overshotLeft := leftBuffer - 0
210 if overshotLeft < 0 {
212 rightBuffer = leftBuffer + (w - 1)
214 rightBuffer = leftBuffer + (w - 2)
217 if rightBuffer > len(fileRunes)-1 {
218 rightBuffer = len(fileRunes) - 1
221 // construct a new buffer of text to put the
222 // newly formatted tab bar text into.
223 var displayText []rune
225 // if the left-side of the tab bar isn't at the start
226 // of the constructed tab bar text, then show that are
227 // more tabs to the left by displaying a "+"
229 displayText = append(displayText, '+')
231 // copy the runes in from the original tab bar text string
232 // into the new display buffer
233 for x := leftBuffer; x < rightBuffer; x++ {
234 displayText = append(displayText, fileRunes[x])
236 // if there is more text to the right of the right-most
237 // column in the tab bar text, then indicate there are more
238 // tabs to the right by displaying a "+"
239 if rightBuffer < len(fileRunes)-1 {
240 displayText = append(displayText, '+')
243 // now store the offset from zero of the left-most text
244 // that is being displayed. This is to ensure that when
245 // clicking on the tab bar, the correct tab gets selected.
246 tabBarOffset = leftBuffer
248 // use the constructed buffer as the display buffer to print
250 fileRunes = displayText
255 // iterate over the width of the terminal display and for each column,
256 // write a character into the tab display area with the appropriate style.
257 for x := 0; x < w; x++ {
258 if x < len(fileRunes) {
259 screen.SetContent(x, 0, fileRunes[x], nil, tabBarStyle)
261 screen.SetContent(x, 0, ' ', nil, tabBarStyle)