summary refs log tree commit diff stats
path: root/lib/ui
diff options
context:
space:
mode:
authorJeffas <dev@jeffas.io>2020-03-07 16:42:41 +0000
committerDrew DeVault <sir@cmpwn.com>2020-03-09 09:31:02 -0400
commit3156d481feaffd2e6df6d860b980e9160b706e42 (patch)
tree82a6362a76015273a7a43105e15e7cdb41f96ada /lib/ui
parent258a3f11ae379b96f4743d6d709b7c42bafd6dbc (diff)
downloadaerc-3156d481feaffd2e6df6d860b980e9160b706e42.tar.gz
Add pinned tabs
This adds the commands pin-tab and unpin-tab. Once pinned a tab lives on
the left of the tabstrip and has a configurable marker, defaulting to `
before its name.
Diffstat (limited to 'lib/ui')
-rw-r--r--lib/ui/tab.go67
1 files changed, 62 insertions, 5 deletions
diff --git a/lib/ui/tab.go b/lib/ui/tab.go
index e1c53ea..7d1ce63 100644
--- a/lib/ui/tab.go
+++ b/lib/ui/tab.go
@@ -3,6 +3,8 @@ package ui
 import (
 	"github.com/gdamore/tcell"
 	"github.com/mattn/go-runewidth"
+
+	"git.sr.ht/~sircmpwn/aerc/config"
 )
 
 type Tabs struct {
@@ -12,6 +14,8 @@ type Tabs struct {
 	Selected   int
 	history    []int
 
+	uiConfig *config.UIConfig
+
 	onInvalidateStrip   func(d Drawable)
 	onInvalidateContent func(d Drawable)
 
@@ -20,16 +24,19 @@ type Tabs struct {
 }
 
 type Tab struct {
-	Content Drawable
-	Name    string
-	invalid bool
+	Content        Drawable
+	Name           string
+	invalid        bool
+	pinned         bool
+	indexBeforePin int
 }
 
 type TabStrip Tabs
 type TabContent Tabs
 
-func NewTabs() *Tabs {
+func NewTabs(uiConf *config.UIConfig) *Tabs {
 	tabs := &Tabs{}
+	tabs.uiConfig = uiConf
 	tabs.TabStrip = (*TabStrip)(tabs)
 	tabs.TabStrip.parent = tabs
 	tabs.TabContent = (*TabContent)(tabs)
@@ -173,6 +180,52 @@ func (tabs *Tabs) MoveTab(to int) {
 	tabs.TabStrip.Invalidate()
 }
 
+func (tabs *Tabs) PinTab() {
+	if tabs.Tabs[tabs.Selected].pinned {
+		return
+	}
+
+	pinEnd := len(tabs.Tabs)
+	for i, t := range tabs.Tabs {
+		if !t.pinned {
+			pinEnd = i
+			break
+		}
+	}
+
+	for _, t := range tabs.Tabs {
+		if t.pinned && t.indexBeforePin > tabs.Selected-pinEnd {
+			t.indexBeforePin -= 1
+		}
+	}
+
+	tabs.Tabs[tabs.Selected].pinned = true
+	tabs.Tabs[tabs.Selected].indexBeforePin = tabs.Selected - pinEnd
+
+	tabs.MoveTab(pinEnd)
+}
+
+func (tabs *Tabs) UnpinTab() {
+	if !tabs.Tabs[tabs.Selected].pinned {
+		return
+	}
+
+	pinEnd := len(tabs.Tabs)
+	for i, t := range tabs.Tabs {
+		if i != tabs.Selected && t.pinned && t.indexBeforePin > tabs.Tabs[tabs.Selected].indexBeforePin {
+			t.indexBeforePin += 1
+		}
+		if !t.pinned {
+			pinEnd = i
+			break
+		}
+	}
+
+	tabs.Tabs[tabs.Selected].pinned = false
+
+	tabs.MoveTab(tabs.Tabs[tabs.Selected].indexBeforePin + pinEnd - 1)
+}
+
 func (tabs *Tabs) NextTab() {
 	next := tabs.Selected + 1
 	if next >= len(tabs.Tabs) {
@@ -233,7 +286,11 @@ func (strip *TabStrip) Draw(ctx *Context) {
 		if ctx.Width()-x < tabWidth {
 			tabWidth = ctx.Width() - x - 2
 		}
-		trunc := runewidth.Truncate(tab.Name, tabWidth, "…")
+		name := tab.Name
+		if tab.pinned {
+			name = strip.uiConfig.PinnedTabMarker + name
+		}
+		trunc := runewidth.Truncate(name, tabWidth, "…")
 		x += ctx.Printf(x, 0, style, " %s ", trunc)
 		if x >= ctx.Width() {
 			break