mirror of https://github.com/veonik/squirssi
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
4.0 KiB
196 lines
4.0 KiB
package squirssi
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"code.dopame.me/veonik/squircy3/event"
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"code.dopame.me/veonik/squirssi/widget"
|
|
)
|
|
|
|
type WindowManager struct {
|
|
windows []Window
|
|
activeIndex int
|
|
|
|
status *StatusWindow
|
|
|
|
events *event.Dispatcher
|
|
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
func NewWindowManager(ev *event.Dispatcher) *WindowManager {
|
|
wm := &WindowManager{events: ev}
|
|
wm.status = &StatusWindow{bufferedWindow: newBufferedWindow("status", ev)}
|
|
wm.windows = []Window{wm.status}
|
|
return wm
|
|
}
|
|
|
|
func (wm *WindowManager) TabNames() ([]string, map[int]widget.ActivityType) {
|
|
wm.mu.RLock()
|
|
defer wm.mu.RUnlock()
|
|
res := make([]string, len(wm.windows))
|
|
activity := make(map[int]widget.ActivityType)
|
|
for i := 0; i < len(wm.windows); i++ {
|
|
win := wm.windows[i]
|
|
if win.HasNotice() {
|
|
activity[i] = widget.TabHasNotice
|
|
} else if win.HasActivity() {
|
|
activity[i] = widget.TabHasActivity
|
|
}
|
|
if wm.activeIndex == i {
|
|
res[i] = fmt.Sprintf(" %s ", win.Title())
|
|
} else {
|
|
res[i] = fmt.Sprintf(" %d ", i)
|
|
}
|
|
}
|
|
return res, activity
|
|
}
|
|
|
|
func (wm *WindowManager) Windows() []Window {
|
|
wm.mu.RLock()
|
|
defer wm.mu.RUnlock()
|
|
wins := make([]Window, len(wm.windows))
|
|
copy(wins, wm.windows)
|
|
return wins
|
|
}
|
|
|
|
func (wm *WindowManager) Len() int {
|
|
wm.mu.RLock()
|
|
defer wm.mu.RUnlock()
|
|
return len(wm.windows)
|
|
}
|
|
|
|
func (wm *WindowManager) ActiveIndex() int {
|
|
wm.mu.RLock()
|
|
defer wm.mu.RUnlock()
|
|
return wm.activeIndex
|
|
}
|
|
|
|
func (wm *WindowManager) Active() Window {
|
|
wm.mu.RLock()
|
|
defer wm.mu.RUnlock()
|
|
return wm.windows[wm.activeIndex]
|
|
}
|
|
|
|
func (wm *WindowManager) Append(w Window) {
|
|
wm.mu.Lock()
|
|
defer wm.mu.Unlock()
|
|
wm.windows = append(wm.windows, w)
|
|
}
|
|
|
|
func (wm *WindowManager) NamedOrActive(name string) Window {
|
|
var win Window
|
|
wm.mu.RLock()
|
|
defer wm.mu.RUnlock()
|
|
for _, w := range wm.windows {
|
|
if w.Title() == name {
|
|
win = w
|
|
break
|
|
}
|
|
}
|
|
if win == nil {
|
|
return wm.windows[wm.activeIndex]
|
|
}
|
|
return win
|
|
}
|
|
|
|
// Named returns the window with the given name, if it exists.
|
|
func (wm *WindowManager) Named(name string) Window {
|
|
var win Window
|
|
wm.mu.RLock()
|
|
defer wm.mu.RUnlock()
|
|
for _, w := range wm.windows {
|
|
if w.Title() == name {
|
|
win = w
|
|
break
|
|
}
|
|
}
|
|
return win
|
|
}
|
|
|
|
func (wm *WindowManager) Index(idx int) Window {
|
|
wm.mu.RLock()
|
|
defer wm.mu.RUnlock()
|
|
if idx >= len(wm.windows) || idx < 0 {
|
|
return nil
|
|
}
|
|
return wm.windows[idx]
|
|
}
|
|
|
|
func (wm *WindowManager) SelectIndex(idx int) {
|
|
wm.mu.Lock()
|
|
defer wm.mu.Unlock()
|
|
if idx >= len(wm.windows) || idx < 0 {
|
|
logrus.Warnf("failed to select window; no window #%d", idx)
|
|
return
|
|
}
|
|
wm.activeIndex = idx
|
|
wm.events.Emit("ui.DIRTY", nil)
|
|
}
|
|
|
|
func (wm *WindowManager) SelectNext() {
|
|
wm.mu.Lock()
|
|
defer wm.mu.Unlock()
|
|
idx := wm.activeIndex + 1
|
|
if idx >= len(wm.windows) || idx < 0 {
|
|
idx = 0
|
|
}
|
|
wm.activeIndex = idx
|
|
wm.events.Emit("ui.DIRTY", nil)
|
|
}
|
|
|
|
func (wm *WindowManager) SelectPrev() {
|
|
wm.mu.Lock()
|
|
defer wm.mu.Unlock()
|
|
idx := wm.activeIndex - 1
|
|
if idx >= len(wm.windows) || idx < 0 {
|
|
idx = len(wm.windows) - 1
|
|
}
|
|
wm.activeIndex = idx
|
|
wm.events.Emit("ui.DIRTY", nil)
|
|
}
|
|
|
|
// CloseIndex closes a window denoted by tab index.
|
|
func (wm *WindowManager) CloseIndex(ch int) {
|
|
if ch == 0 {
|
|
logrus.Warnln("cannot close status window")
|
|
return
|
|
}
|
|
wm.mu.Lock()
|
|
defer wm.mu.Unlock()
|
|
if ch >= len(wm.windows) {
|
|
logrus.Warnf("failed to close window; no window #%d", ch)
|
|
return
|
|
}
|
|
wm.windows = append(wm.windows[:ch], wm.windows[ch+1:]...)
|
|
if ch >= len(wm.windows) {
|
|
wm.activeIndex = len(wm.windows) - 1
|
|
}
|
|
wm.events.Emit("ui.DIRTY", nil)
|
|
}
|
|
|
|
// ScrollTo scrolls the currently active window up relative to the current line.
|
|
func (wm *WindowManager) ScrollOffset(offset int) {
|
|
wm.mu.RLock()
|
|
win := wm.windows[wm.activeIndex]
|
|
wm.mu.RUnlock()
|
|
wm.ScrollTo(win.CurrentLine() + offset)
|
|
}
|
|
|
|
// ScrollTo scrolls the currently active window to the given position.
|
|
func (wm *WindowManager) ScrollTo(pos int) {
|
|
wm.mu.Lock()
|
|
defer wm.mu.Unlock()
|
|
win := wm.windows[wm.activeIndex]
|
|
if pos < 0 {
|
|
pos = 0
|
|
} else if pos >= len(win.Lines()) {
|
|
pos = -1
|
|
}
|
|
win.ScrollTo(pos)
|
|
wm.events.Emit("ui.DIRTY", nil)
|
|
}
|