4 "github.com/zyedidia/micro/cmd/micro/buffer"
5 "github.com/zyedidia/micro/cmd/micro/display"
6 "github.com/zyedidia/micro/cmd/micro/screen"
7 "github.com/zyedidia/micro/cmd/micro/views"
8 "github.com/zyedidia/tcell"
16 func NewTabList(bufs []*buffer.Buffer) *TabList {
17 w, h := screen.Screen.Size()
19 tl.List = make([]*TabPane, len(bufs))
21 for i, b := range bufs {
22 tl.List[i] = NewTabPane(0, 1, w, h-2, b)
25 tl.List[0] = NewTabPane(0, 0, w, h-1, bufs[0])
27 tl.TabWindow = display.NewTabWindow(w, 0)
28 tl.Names = make([]string, len(bufs))
33 func (t *TabList) UpdateNames() {
35 for _, p := range t.List {
36 t.Names = append(t.Names, p.Panes[p.active].Buf.GetName())
40 func (t *TabList) AddTab(p *TabPane) {
41 t.List = append(t.List, p)
46 func (t *TabList) RemoveTab(id uint64) {
47 for i, p := range t.List {
48 if len(p.Panes) == 0 {
51 if p.Panes[0].splitID == id {
52 copy(t.List[i:], t.List[i+1:])
53 t.List[len(t.List)-1] = nil
54 t.List = t.List[:len(t.List)-1]
55 if t.Active() >= len(t.List) {
56 t.SetActive(len(t.List) - 1)
65 func (t *TabList) Resize() {
66 w, h := screen.Screen.Size()
67 InfoBar.Resize(w, h-1)
69 for _, p := range t.List {
74 } else if len(t.List) == 1 {
76 t.List[0].Node.Resize(w, h-1)
81 func (t *TabList) HandleEvent(event tcell.Event) {
82 switch e := event.(type) {
83 case *tcell.EventResize:
85 case *tcell.EventMouse:
86 mx, my := e.Position()
89 ind := t.GetMouseLoc(buffer.Loc{mx, my})
105 t.List[t.Active()].HandleEvent(event)
108 func (t *TabList) Display() {
111 t.TabWindow.Display()
117 func InitTabs(bufs []*buffer.Buffer) {
118 Tabs = NewTabList(bufs)
121 func MainTab() *TabPane {
122 return Tabs.List[Tabs.Active()]
125 // A TabPane represents a single tab
126 // It consists of a list of edit panes (the open buffers),
127 // a split tree (stored as just the root node), and a uiwindow
128 // to display the UI elements like the borders between splits
129 type TabPane struct {
135 resizing *views.Node // node currently being resized
138 // HandleEvent takes a tcell event and usually dispatches it to the current
139 // active pane. However if the event is a resize or a mouse event where the user
140 // is interacting with the UI (resizing splits) then the event is consumed here
141 // If the event is a mouse event in a pane, that pane will become active and get
143 func (t *TabPane) HandleEvent(event tcell.Event) {
144 switch e := event.(type) {
145 case *tcell.EventMouse:
146 mx, my := e.Position()
149 resizeID := t.GetMouseSplitID(buffer.Loc{mx, my})
150 if t.resizing != nil {
152 if t.resizing.Kind == views.STVert {
153 size = mx - t.resizing.X
155 size = my - t.resizing.Y + 1
157 t.resizing.ResizeSplit(size)
163 t.resizing = t.GetNode(uint64(resizeID))
167 for i, p := range t.Panes {
169 inpane := mx >= v.X && mx < v.X+v.Width && my >= v.Y && my < v.Y+v.Height
177 case tcell.ButtonNone:
180 for _, p := range t.Panes {
182 inpane := mx >= v.X && mx < v.X+v.Width && my >= v.Y && my < v.Y+v.Height
191 t.Panes[t.active].HandleEvent(event)
194 // SetActive changes the currently active pane to the specified index
195 func (t *TabPane) SetActive(i int) {
197 for j, p := range t.Panes {
206 // GetPane returns the pane with the given split index
207 func (t *TabPane) GetPane(splitid uint64) int {
208 for i, p := range t.Panes {
209 if p.splitID == splitid {
216 // Remove pane removes the pane with the given index
217 func (t *TabPane) RemovePane(i int) {
218 copy(t.Panes[i:], t.Panes[i+1:])
219 t.Panes[len(t.Panes)-1] = nil
220 t.Panes = t.Panes[:len(t.Panes)-1]
223 // Resize resizes all panes according to their corresponding split nodes
224 func (t *TabPane) Resize() {
225 for _, p := range t.Panes {
226 n := t.GetNode(p.splitID)
232 pv.X, pv.Y = n.X+offset, n.Y
234 p.Resize(n.W-offset, n.H)
238 // CurPane returns the currently active pane
239 func (t *TabPane) CurPane() *EditPane {
240 return t.Panes[t.active]